1 /* 2 * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann (at) kde.org> 3 * Copyright (C) 2004, 2005 Rob Buis <buis (at) kde.org> 4 * Copyright (C) 2005 Eric Seidel <eric (at) webkit.org> 5 * Copyright (C) 2009 Dirk Schulze <krit (at) webkit.org> 6 * Copyright (C) Research In Motion Limited 2010. All rights reserved. 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public License 19 * along with this library; see the file COPYING.LIB. If not, write to 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 * Boston, MA 02110-1301, USA. 22 */ 23 24 #include "config.h" 25 26 #if ENABLE(FILTERS) 27 #include "FEDisplacementMap.h" 28 29 #include "Filter.h" 30 #include "GraphicsContext.h" 31 #include "RenderTreeAsText.h" 32 #include "TextStream.h" 33 34 #include <wtf/ByteArray.h> 35 36 namespace WebCore { 37 38 FEDisplacementMap::FEDisplacementMap(Filter* filter, ChannelSelectorType xChannelSelector, ChannelSelectorType yChannelSelector, float scale) 39 : FilterEffect(filter) 40 , m_xChannelSelector(xChannelSelector) 41 , m_yChannelSelector(yChannelSelector) 42 , m_scale(scale) 43 { 44 } 45 46 PassRefPtr<FEDisplacementMap> FEDisplacementMap::create(Filter* filter, ChannelSelectorType xChannelSelector, 47 ChannelSelectorType yChannelSelector, float scale) 48 { 49 return adoptRef(new FEDisplacementMap(filter, xChannelSelector, yChannelSelector, scale)); 50 } 51 52 ChannelSelectorType FEDisplacementMap::xChannelSelector() const 53 { 54 return m_xChannelSelector; 55 } 56 57 bool FEDisplacementMap::setXChannelSelector(const ChannelSelectorType xChannelSelector) 58 { 59 if (m_xChannelSelector == xChannelSelector) 60 return false; 61 m_xChannelSelector = xChannelSelector; 62 return true; 63 } 64 65 ChannelSelectorType FEDisplacementMap::yChannelSelector() const 66 { 67 return m_yChannelSelector; 68 } 69 70 bool FEDisplacementMap::setYChannelSelector(const ChannelSelectorType yChannelSelector) 71 { 72 if (m_yChannelSelector == yChannelSelector) 73 return false; 74 m_yChannelSelector = yChannelSelector; 75 return true; 76 } 77 78 float FEDisplacementMap::scale() const 79 { 80 return m_scale; 81 } 82 83 bool FEDisplacementMap::setScale(float scale) 84 { 85 if (m_scale == scale) 86 return false; 87 m_scale = scale; 88 return true; 89 } 90 91 void FEDisplacementMap::apply() 92 { 93 if (hasResult()) 94 return; 95 FilterEffect* in = inputEffect(0); 96 FilterEffect* in2 = inputEffect(1); 97 in->apply(); 98 in2->apply(); 99 if (!in->hasResult() || !in2->hasResult()) 100 return; 101 102 if (m_xChannelSelector == CHANNEL_UNKNOWN || m_yChannelSelector == CHANNEL_UNKNOWN) 103 return; 104 105 ByteArray* dstPixelArray = createPremultipliedImageResult(); 106 if (!dstPixelArray) 107 return; 108 109 IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); 110 RefPtr<ByteArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect); 111 112 IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect()); 113 RefPtr<ByteArray> srcPixelArrayB = in2->asUnmultipliedImage(effectBDrawingRect); 114 115 ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length()); 116 117 Filter* filter = this->filter(); 118 IntSize paintSize = absolutePaintRect().size(); 119 float scaleX = filter->applyHorizontalScale(m_scale / 255); 120 float scaleY = filter->applyVerticalScale(m_scale / 255); 121 float scaleAdjustmentX = filter->applyHorizontalScale(0.5f - 0.5f * m_scale); 122 float scaleAdjustmentY = filter->applyVerticalScale(0.5f - 0.5f * m_scale); 123 int stride = paintSize.width() * 4; 124 for (int y = 0; y < paintSize.height(); ++y) { 125 int line = y * stride; 126 for (int x = 0; x < paintSize.width(); ++x) { 127 int dstIndex = line + x * 4; 128 int srcX = x + static_cast<int>(scaleX * srcPixelArrayB->get(dstIndex + m_xChannelSelector - 1) + scaleAdjustmentX); 129 int srcY = y + static_cast<int>(scaleY * srcPixelArrayB->get(dstIndex + m_yChannelSelector - 1) + scaleAdjustmentY); 130 for (unsigned channel = 0; channel < 4; ++channel) { 131 if (srcX < 0 || srcX >= paintSize.width() || srcY < 0 || srcY >= paintSize.height()) 132 dstPixelArray->set(dstIndex + channel, static_cast<unsigned char>(0)); 133 else { 134 unsigned char pixelValue = srcPixelArrayA->get(srcY * stride + srcX * 4 + channel); 135 dstPixelArray->set(dstIndex + channel, pixelValue); 136 } 137 } 138 } 139 } 140 } 141 142 void FEDisplacementMap::dump() 143 { 144 } 145 146 static TextStream& operator<<(TextStream& ts, const ChannelSelectorType& type) 147 { 148 switch (type) { 149 case CHANNEL_UNKNOWN: 150 ts << "UNKNOWN"; 151 break; 152 case CHANNEL_R: 153 ts << "RED"; 154 break; 155 case CHANNEL_G: 156 ts << "GREEN"; 157 break; 158 case CHANNEL_B: 159 ts << "BLUE"; 160 break; 161 case CHANNEL_A: 162 ts << "ALPHA"; 163 break; 164 } 165 return ts; 166 } 167 168 TextStream& FEDisplacementMap::externalRepresentation(TextStream& ts, int indent) const 169 { 170 writeIndent(ts, indent); 171 ts << "[feDisplacementMap"; 172 FilterEffect::externalRepresentation(ts); 173 ts << " scale=\"" << m_scale << "\" " 174 << "xChannelSelector=\"" << m_xChannelSelector << "\" " 175 << "yChannelSelector=\"" << m_yChannelSelector << "\"]\n"; 176 inputEffect(0)->externalRepresentation(ts, indent + 1); 177 inputEffect(1)->externalRepresentation(ts, indent + 1); 178 return ts; 179 } 180 181 } // namespace WebCore 182 183 #endif // ENABLE(FILTERS) 184