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