1/* 2 * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> 3 * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> 4 * Copyright (C) 2005 Eric Seidel <eric@webkit.org> 5 * Copyright (C) 2009 Dirk Schulze <krit@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/Uint8ClampedArray.h> 35 36namespace WebCore { 37 38FEDisplacementMap::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 46PassRefPtr<FEDisplacementMap> FEDisplacementMap::create(Filter* filter, ChannelSelectorType xChannelSelector, 47 ChannelSelectorType yChannelSelector, float scale) 48{ 49 return adoptRef(new FEDisplacementMap(filter, xChannelSelector, yChannelSelector, scale)); 50} 51 52ChannelSelectorType FEDisplacementMap::xChannelSelector() const 53{ 54 return m_xChannelSelector; 55} 56 57bool FEDisplacementMap::setXChannelSelector(const ChannelSelectorType xChannelSelector) 58{ 59 if (m_xChannelSelector == xChannelSelector) 60 return false; 61 m_xChannelSelector = xChannelSelector; 62 return true; 63} 64 65ChannelSelectorType FEDisplacementMap::yChannelSelector() const 66{ 67 return m_yChannelSelector; 68} 69 70bool FEDisplacementMap::setYChannelSelector(const ChannelSelectorType yChannelSelector) 71{ 72 if (m_yChannelSelector == yChannelSelector) 73 return false; 74 m_yChannelSelector = yChannelSelector; 75 return true; 76} 77 78float FEDisplacementMap::scale() const 79{ 80 return m_scale; 81} 82 83bool FEDisplacementMap::setScale(float scale) 84{ 85 if (m_scale == scale) 86 return false; 87 m_scale = scale; 88 return true; 89} 90 91void FEDisplacementMap::setResultColorSpace(ColorSpace) 92{ 93 // Spec: The 'color-interpolation-filters' property only applies to the 'in2' source image 94 // and does not apply to the 'in' source image. The 'in' source image must remain in its 95 // current color space. 96 // The result is in that smae color space because it is a displacement of the 'in' image. 97 FilterEffect::setResultColorSpace(inputEffect(0)->resultColorSpace()); 98} 99 100void FEDisplacementMap::transformResultColorSpace(FilterEffect* in, const int index) 101{ 102 // Do not transform the first primitive input, as per the spec. 103 if (index) 104 in->transformResultColorSpace(operatingColorSpace()); 105} 106 107void FEDisplacementMap::platformApplySoftware() 108{ 109 FilterEffect* in = inputEffect(0); 110 FilterEffect* in2 = inputEffect(1); 111 112 ASSERT(m_xChannelSelector != CHANNEL_UNKNOWN); 113 ASSERT(m_yChannelSelector != CHANNEL_UNKNOWN); 114 115 Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult(); 116 if (!dstPixelArray) 117 return; 118 119 IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); 120 RefPtr<Uint8ClampedArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect); 121 122 IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect()); 123 RefPtr<Uint8ClampedArray> srcPixelArrayB = in2->asUnmultipliedImage(effectBDrawingRect); 124 125 ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length()); 126 127 Filter* filter = this->filter(); 128 IntSize paintSize = absolutePaintRect().size(); 129 float scaleX = filter->applyHorizontalScale(m_scale); 130 float scaleY = filter->applyVerticalScale(m_scale); 131 float scaleForColorX = scaleX / 255.0; 132 float scaleForColorY = scaleY / 255.0; 133 float scaledOffsetX = 0.5 - scaleX * 0.5; 134 float scaledOffsetY = 0.5 - scaleY * 0.5; 135 int stride = paintSize.width() * 4; 136 for (int y = 0; y < paintSize.height(); ++y) { 137 int line = y * stride; 138 for (int x = 0; x < paintSize.width(); ++x) { 139 int dstIndex = line + x * 4; 140 int srcX = x + static_cast<int>(scaleForColorX * srcPixelArrayB->item(dstIndex + m_xChannelSelector - 1) + scaledOffsetX); 141 int srcY = y + static_cast<int>(scaleForColorY * srcPixelArrayB->item(dstIndex + m_yChannelSelector - 1) + scaledOffsetY); 142 for (unsigned channel = 0; channel < 4; ++channel) { 143 if (srcX < 0 || srcX >= paintSize.width() || srcY < 0 || srcY >= paintSize.height()) 144 dstPixelArray->set(dstIndex + channel, static_cast<unsigned char>(0)); 145 else { 146 unsigned char pixelValue = srcPixelArrayA->item(srcY * stride + srcX * 4 + channel); 147 dstPixelArray->set(dstIndex + channel, pixelValue); 148 } 149 } 150 } 151 } 152} 153 154void FEDisplacementMap::dump() 155{ 156} 157 158static TextStream& operator<<(TextStream& ts, const ChannelSelectorType& type) 159{ 160 switch (type) { 161 case CHANNEL_UNKNOWN: 162 ts << "UNKNOWN"; 163 break; 164 case CHANNEL_R: 165 ts << "RED"; 166 break; 167 case CHANNEL_G: 168 ts << "GREEN"; 169 break; 170 case CHANNEL_B: 171 ts << "BLUE"; 172 break; 173 case CHANNEL_A: 174 ts << "ALPHA"; 175 break; 176 } 177 return ts; 178} 179 180TextStream& FEDisplacementMap::externalRepresentation(TextStream& ts, int indent) const 181{ 182 writeIndent(ts, indent); 183 ts << "[feDisplacementMap"; 184 FilterEffect::externalRepresentation(ts); 185 ts << " scale=\"" << m_scale << "\" " 186 << "xChannelSelector=\"" << m_xChannelSelector << "\" " 187 << "yChannelSelector=\"" << m_yChannelSelector << "\"]\n"; 188 inputEffect(0)->externalRepresentation(ts, indent + 1); 189 inputEffect(1)->externalRepresentation(ts, indent + 1); 190 return ts; 191} 192 193} // namespace WebCore 194 195#endif // ENABLE(FILTERS) 196