1 /*
2 Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3 2004, 2005 Rob Buis <buis@kde.org>
4 2005 Eric Seidel <eric@webkit.org>
5 2009 Dirk Schulze <krit@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
FEDisplacementMap(FilterEffect * in,FilterEffect * in2,ChannelSelectorType xChannelSelector,ChannelSelectorType yChannelSelector,const float & scale)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
create(FilterEffect * in,FilterEffect * in2,ChannelSelectorType xChannelSelector,ChannelSelectorType yChannelSelector,const float & scale)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
xChannelSelector() const53 ChannelSelectorType FEDisplacementMap::xChannelSelector() const
54 {
55 return m_xChannelSelector;
56 }
57
setXChannelSelector(const ChannelSelectorType xChannelSelector)58 void FEDisplacementMap::setXChannelSelector(const ChannelSelectorType xChannelSelector)
59 {
60 m_xChannelSelector = xChannelSelector;
61 }
62
yChannelSelector() const63 ChannelSelectorType FEDisplacementMap::yChannelSelector() const
64 {
65 return m_yChannelSelector;
66 }
67
setYChannelSelector(const ChannelSelectorType yChannelSelector)68 void FEDisplacementMap::setYChannelSelector(const ChannelSelectorType yChannelSelector)
69 {
70 m_yChannelSelector = yChannelSelector;
71 }
72
scale() const73 float FEDisplacementMap::scale() const
74 {
75 return m_scale;
76 }
77
setScale(float scale)78 void FEDisplacementMap::setScale(float scale)
79 {
80 m_scale = scale;
81 }
82
apply(Filter * filter)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
dump()132 void FEDisplacementMap::dump()
133 {
134 }
135
operator <<(TextStream & ts,ChannelSelectorType t)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
externalRepresentation(TextStream & ts) const154 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