• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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