• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "FEComponentTransfer.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 #include <wtf/MathExtras.h>
36 
37 namespace WebCore {
38 
39 typedef void (*TransferType)(unsigned char*, const ComponentTransferFunction&);
40 
FEComponentTransfer(Filter * filter,const ComponentTransferFunction & redFunc,const ComponentTransferFunction & greenFunc,const ComponentTransferFunction & blueFunc,const ComponentTransferFunction & alphaFunc)41 FEComponentTransfer::FEComponentTransfer(Filter* filter, const ComponentTransferFunction& redFunc, const ComponentTransferFunction& greenFunc,
42                                          const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc)
43     : FilterEffect(filter)
44     , m_redFunc(redFunc)
45     , m_greenFunc(greenFunc)
46     , m_blueFunc(blueFunc)
47     , m_alphaFunc(alphaFunc)
48 {
49 }
50 
create(Filter * filter,const ComponentTransferFunction & redFunc,const ComponentTransferFunction & greenFunc,const ComponentTransferFunction & blueFunc,const ComponentTransferFunction & alphaFunc)51 PassRefPtr<FEComponentTransfer> FEComponentTransfer::create(Filter* filter, const ComponentTransferFunction& redFunc,
52     const ComponentTransferFunction& greenFunc, const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc)
53 {
54     return adoptRef(new FEComponentTransfer(filter, redFunc, greenFunc, blueFunc, alphaFunc));
55 }
56 
redFunction() const57 ComponentTransferFunction FEComponentTransfer::redFunction() const
58 {
59     return m_redFunc;
60 }
61 
setRedFunction(const ComponentTransferFunction & func)62 void FEComponentTransfer::setRedFunction(const ComponentTransferFunction& func)
63 {
64     m_redFunc = func;
65 }
66 
greenFunction() const67 ComponentTransferFunction FEComponentTransfer::greenFunction() const
68 {
69     return m_greenFunc;
70 }
71 
setGreenFunction(const ComponentTransferFunction & func)72 void FEComponentTransfer::setGreenFunction(const ComponentTransferFunction& func)
73 {
74     m_greenFunc = func;
75 }
76 
blueFunction() const77 ComponentTransferFunction FEComponentTransfer::blueFunction() const
78 {
79     return m_blueFunc;
80 }
81 
setBlueFunction(const ComponentTransferFunction & func)82 void FEComponentTransfer::setBlueFunction(const ComponentTransferFunction& func)
83 {
84     m_blueFunc = func;
85 }
86 
alphaFunction() const87 ComponentTransferFunction FEComponentTransfer::alphaFunction() const
88 {
89     return m_alphaFunc;
90 }
91 
setAlphaFunction(const ComponentTransferFunction & func)92 void FEComponentTransfer::setAlphaFunction(const ComponentTransferFunction& func)
93 {
94     m_alphaFunc = func;
95 }
96 
identity(unsigned char *,const ComponentTransferFunction &)97 static void identity(unsigned char*, const ComponentTransferFunction&)
98 {
99 }
100 
table(unsigned char * values,const ComponentTransferFunction & transferFunction)101 static void table(unsigned char* values, const ComponentTransferFunction& transferFunction)
102 {
103     const Vector<float>& tableValues = transferFunction.tableValues;
104     unsigned n = tableValues.size();
105     if (n < 1)
106         return;
107     for (unsigned i = 0; i < 256; ++i) {
108         double c = i / 255.0;
109         unsigned k = static_cast<unsigned>(c * (n - 1));
110         double v1 = tableValues[k];
111         double v2 = tableValues[std::min((k + 1), (n - 1))];
112         double val = 255.0 * (v1 + (c * (n - 1) - k) * (v2 - v1));
113         val = std::max(0.0, std::min(255.0, val));
114         values[i] = static_cast<unsigned char>(val);
115     }
116 }
117 
discrete(unsigned char * values,const ComponentTransferFunction & transferFunction)118 static void discrete(unsigned char* values, const ComponentTransferFunction& transferFunction)
119 {
120     const Vector<float>& tableValues = transferFunction.tableValues;
121     unsigned n = tableValues.size();
122     if (n < 1)
123         return;
124     for (unsigned i = 0; i < 256; ++i) {
125         unsigned k = static_cast<unsigned>((i * n) / 255.0);
126         k = std::min(k, n - 1);
127         double val = 255 * tableValues[k];
128         val = std::max(0.0, std::min(255.0, val));
129         values[i] = static_cast<unsigned char>(val);
130     }
131 }
132 
linear(unsigned char * values,const ComponentTransferFunction & transferFunction)133 static void linear(unsigned char* values, const ComponentTransferFunction& transferFunction)
134 {
135     for (unsigned i = 0; i < 256; ++i) {
136         double val = transferFunction.slope * i + 255 * transferFunction.intercept;
137         val = std::max(0.0, std::min(255.0, val));
138         values[i] = static_cast<unsigned char>(val);
139     }
140 }
141 
gamma(unsigned char * values,const ComponentTransferFunction & transferFunction)142 static void gamma(unsigned char* values, const ComponentTransferFunction& transferFunction)
143 {
144     for (unsigned i = 0; i < 256; ++i) {
145         double exponent = transferFunction.exponent; // RCVT doesn't like passing a double and a float to pow, so promote this to double
146         double val = 255.0 * (transferFunction.amplitude * pow((i / 255.0), exponent) + transferFunction.offset);
147         val = std::max(0.0, std::min(255.0, val));
148         values[i] = static_cast<unsigned char>(val);
149     }
150 }
151 
apply()152 void FEComponentTransfer::apply()
153 {
154     if (hasResult())
155         return;
156     FilterEffect* in = inputEffect(0);
157     in->apply();
158     if (!in->hasResult())
159         return;
160 
161     ByteArray* pixelArray = createUnmultipliedImageResult();
162     if (!pixelArray)
163         return;
164 
165     unsigned char rValues[256], gValues[256], bValues[256], aValues[256];
166     for (unsigned i = 0; i < 256; ++i)
167         rValues[i] = gValues[i] = bValues[i] = aValues[i] = i;
168     unsigned char* tables[] = { rValues, gValues, bValues, aValues };
169     ComponentTransferFunction transferFunction[] = {m_redFunc, m_greenFunc, m_blueFunc, m_alphaFunc};
170     TransferType callEffect[] = {identity, identity, table, discrete, linear, gamma};
171 
172     for (unsigned channel = 0; channel < 4; channel++)
173         (*callEffect[transferFunction[channel].type])(tables[channel], transferFunction[channel]);
174 
175     IntRect drawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
176     in->copyUnmultipliedImage(pixelArray, drawingRect);
177 
178     unsigned pixelArrayLength = pixelArray->length();
179     for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) {
180         for (unsigned channel = 0; channel < 4; ++channel) {
181             unsigned char c = pixelArray->get(pixelOffset + channel);
182             pixelArray->set(pixelOffset + channel, tables[channel][c]);
183         }
184     }
185 }
186 
dump()187 void FEComponentTransfer::dump()
188 {
189 }
190 
operator <<(TextStream & ts,const ComponentTransferType & type)191 static TextStream& operator<<(TextStream& ts, const ComponentTransferType& type)
192 {
193     switch (type) {
194     case FECOMPONENTTRANSFER_TYPE_UNKNOWN:
195         ts << "UNKNOWN";
196         break;
197     case FECOMPONENTTRANSFER_TYPE_IDENTITY:
198         ts << "IDENTITY";
199         break;
200     case FECOMPONENTTRANSFER_TYPE_TABLE:
201         ts << "TABLE";
202         break;
203     case FECOMPONENTTRANSFER_TYPE_DISCRETE:
204         ts << "DISCRETE";
205         break;
206     case FECOMPONENTTRANSFER_TYPE_LINEAR:
207         ts << "LINEAR";
208         break;
209     case FECOMPONENTTRANSFER_TYPE_GAMMA:
210         ts << "GAMMA";
211         break;
212     }
213     return ts;
214 }
215 
operator <<(TextStream & ts,const ComponentTransferFunction & function)216 static TextStream& operator<<(TextStream& ts, const ComponentTransferFunction& function)
217 {
218     ts << "type=\"" << function.type
219        << "\" slope=\"" << function.slope
220        << "\" intercept=\"" << function.intercept
221        << "\" amplitude=\"" << function.amplitude
222        << "\" exponent=\"" << function.exponent
223        << "\" offset=\"" << function.offset << "\"";
224     return ts;
225 }
226 
externalRepresentation(TextStream & ts,int indent) const227 TextStream& FEComponentTransfer::externalRepresentation(TextStream& ts, int indent) const
228 {
229     writeIndent(ts, indent);
230     ts << "[feComponentTransfer";
231     FilterEffect::externalRepresentation(ts);
232     ts << " \n";
233     writeIndent(ts, indent + 2);
234     ts << "{red: " << m_redFunc << "}\n";
235     writeIndent(ts, indent + 2);
236     ts << "{green: " << m_greenFunc << "}\n";
237     writeIndent(ts, indent + 2);
238     ts << "{blue: " << m_blueFunc << "}\n";
239     writeIndent(ts, indent + 2);
240     ts << "{alpha: " << m_alphaFunc << "}]\n";
241     inputEffect(0)->externalRepresentation(ts, indent + 1);
242     return ts;
243 }
244 
245 } // namespace WebCore
246 
247 #endif // ENABLE(FILTERS)
248