1 /*
2 * Copyright (C) 2010 University of Szeged
3 * Copyright (C) 2010 Zoltan Herczeg
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include "config.h"
28
29 #if ENABLE(FILTERS)
30 #include "FELighting.h"
31
32 #include "LightSource.h"
33 #include "PointLightSource.h"
34 #include "SpotLightSource.h"
35
36 #if CPU(ARM_NEON) && COMPILER(GCC)
37 #include "FELightingNEON.h"
38 #include <wtf/Vector.h>
39 #endif
40
41 namespace WebCore {
42
FELighting(Filter * filter,LightingType lightingType,const Color & lightingColor,float surfaceScale,float diffuseConstant,float specularConstant,float specularExponent,float kernelUnitLengthX,float kernelUnitLengthY,PassRefPtr<LightSource> lightSource)43 FELighting::FELighting(Filter* filter, LightingType lightingType, const Color& lightingColor, float surfaceScale,
44 float diffuseConstant, float specularConstant, float specularExponent,
45 float kernelUnitLengthX, float kernelUnitLengthY, PassRefPtr<LightSource> lightSource)
46 : FilterEffect(filter)
47 , m_lightingType(lightingType)
48 , m_lightSource(lightSource)
49 , m_lightingColor(lightingColor)
50 , m_surfaceScale(surfaceScale)
51 , m_diffuseConstant(diffuseConstant)
52 , m_specularConstant(specularConstant)
53 , m_specularExponent(specularExponent)
54 , m_kernelUnitLengthX(kernelUnitLengthX)
55 , m_kernelUnitLengthY(kernelUnitLengthY)
56 {
57 }
58
59 const static int cPixelSize = 4;
60 const static int cAlphaChannelOffset = 3;
61 const static unsigned char cOpaqueAlpha = static_cast<unsigned char>(0xff);
62 const static float cFactor1div2 = -1 / 2.f;
63 const static float cFactor1div3 = -1 / 3.f;
64 const static float cFactor1div4 = -1 / 4.f;
65 const static float cFactor2div3 = -2 / 3.f;
66
67 // << 1 is signed multiply by 2
topLeft(int offset,IntPoint & normalVector)68 inline void FELighting::LightingData::topLeft(int offset, IntPoint& normalVector)
69 {
70 int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
71 int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
72 offset += widthMultipliedByPixelSize;
73 int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
74 int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
75 normalVector.setX(-(center << 1) + (right << 1) - bottom + bottomRight);
76 normalVector.setY(-(center << 1) - right + (bottom << 1) + bottomRight);
77 }
78
topRow(int offset,IntPoint & normalVector)79 inline void FELighting::LightingData::topRow(int offset, IntPoint& normalVector)
80 {
81 int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
82 int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
83 int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
84 offset += widthMultipliedByPixelSize;
85 int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
86 int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
87 int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
88 normalVector.setX(-(left << 1) + (right << 1) - bottomLeft + bottomRight);
89 normalVector.setY(-left - (center << 1) - right + bottomLeft + (bottom << 1) + bottomRight);
90 }
91
topRight(int offset,IntPoint & normalVector)92 inline void FELighting::LightingData::topRight(int offset, IntPoint& normalVector)
93 {
94 int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
95 int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
96 offset += widthMultipliedByPixelSize;
97 int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
98 int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
99 normalVector.setX(-(left << 1) + (center << 1) - bottomLeft + bottom);
100 normalVector.setY(-left - (center << 1) + bottomLeft + (bottom << 1));
101 }
102
leftColumn(int offset,IntPoint & normalVector)103 inline void FELighting::LightingData::leftColumn(int offset, IntPoint& normalVector)
104 {
105 int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
106 int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
107 offset -= widthMultipliedByPixelSize;
108 int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
109 int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
110 offset += widthMultipliedByPixelSize << 1;
111 int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
112 int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
113 normalVector.setX(-top + topRight - (center << 1) + (right << 1) - bottom + bottomRight);
114 normalVector.setY(-(top << 1) - topRight + (bottom << 1) + bottomRight);
115 }
116
interior(int offset,IntPoint & normalVector)117 inline void FELighting::LightingData::interior(int offset, IntPoint& normalVector)
118 {
119 int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
120 int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
121 offset -= widthMultipliedByPixelSize;
122 int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
123 int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
124 int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
125 offset += widthMultipliedByPixelSize << 1;
126 int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
127 int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
128 int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
129 normalVector.setX(-topLeft + topRight - (left << 1) + (right << 1) - bottomLeft + bottomRight);
130 normalVector.setY(-topLeft - (top << 1) - topRight + bottomLeft + (bottom << 1) + bottomRight);
131 }
132
rightColumn(int offset,IntPoint & normalVector)133 inline void FELighting::LightingData::rightColumn(int offset, IntPoint& normalVector)
134 {
135 int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
136 int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
137 offset -= widthMultipliedByPixelSize;
138 int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
139 int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
140 offset += widthMultipliedByPixelSize << 1;
141 int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
142 int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
143 normalVector.setX(-topLeft + top - (left << 1) + (center << 1) - bottomLeft + bottom);
144 normalVector.setY(-topLeft - (top << 1) + bottomLeft + (bottom << 1));
145 }
146
bottomLeft(int offset,IntPoint & normalVector)147 inline void FELighting::LightingData::bottomLeft(int offset, IntPoint& normalVector)
148 {
149 int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
150 int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
151 offset -= widthMultipliedByPixelSize;
152 int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
153 int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
154 normalVector.setX(-top + topRight - (center << 1) + (right << 1));
155 normalVector.setY(-(top << 1) - topRight + (center << 1) + right);
156 }
157
bottomRow(int offset,IntPoint & normalVector)158 inline void FELighting::LightingData::bottomRow(int offset, IntPoint& normalVector)
159 {
160 int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
161 int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
162 int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
163 offset -= widthMultipliedByPixelSize;
164 int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
165 int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
166 int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
167 normalVector.setX(-topLeft + topRight - (left << 1) + (right << 1));
168 normalVector.setY(-topLeft - (top << 1) - topRight + left + (center << 1) + right);
169 }
170
bottomRight(int offset,IntPoint & normalVector)171 inline void FELighting::LightingData::bottomRight(int offset, IntPoint& normalVector)
172 {
173 int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
174 int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
175 offset -= widthMultipliedByPixelSize;
176 int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
177 int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
178 normalVector.setX(-topLeft + top - (left << 1) + (center << 1));
179 normalVector.setY(-topLeft - (top << 1) + left + (center << 1));
180 }
181
inlineSetPixel(int offset,LightingData & data,LightSource::PaintingData & paintingData,int lightX,int lightY,float factorX,float factorY,IntPoint & normal2DVector)182 inline void FELighting::inlineSetPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData,
183 int lightX, int lightY, float factorX, float factorY, IntPoint& normal2DVector)
184 {
185 m_lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->get(offset + cAlphaChannelOffset)) * data.surfaceScale);
186
187 float lightStrength;
188 if (!normal2DVector.x() && !normal2DVector.y()) {
189 // Normal vector is (0, 0, 1). This is a quite frequent case.
190 if (m_lightingType == FELighting::DiffuseLighting)
191 lightStrength = m_diffuseConstant * paintingData.lightVector.z() / paintingData.lightVectorLength;
192 else {
193 FloatPoint3D halfwayVector = paintingData.lightVector;
194 halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength);
195 float halfwayVectorLength = halfwayVector.length();
196 if (m_specularExponent == 1)
197 lightStrength = m_specularConstant * halfwayVector.z() / halfwayVectorLength;
198 else
199 lightStrength = m_specularConstant * powf(halfwayVector.z() / halfwayVectorLength, m_specularExponent);
200 }
201 } else {
202 FloatPoint3D normalVector;
203 normalVector.setX(factorX * static_cast<float>(normal2DVector.x()) * data.surfaceScale);
204 normalVector.setY(factorY * static_cast<float>(normal2DVector.y()) * data.surfaceScale);
205 normalVector.setZ(1);
206 float normalVectorLength = normalVector.length();
207
208 if (m_lightingType == FELighting::DiffuseLighting)
209 lightStrength = m_diffuseConstant * (normalVector * paintingData.lightVector) / (normalVectorLength * paintingData.lightVectorLength);
210 else {
211 FloatPoint3D halfwayVector = paintingData.lightVector;
212 halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength);
213 float halfwayVectorLength = halfwayVector.length();
214 if (m_specularExponent == 1)
215 lightStrength = m_specularConstant * (normalVector * halfwayVector) / (normalVectorLength * halfwayVectorLength);
216 else
217 lightStrength = m_specularConstant * powf((normalVector * halfwayVector) / (normalVectorLength * halfwayVectorLength), m_specularExponent);
218 }
219 }
220
221 if (lightStrength > 1)
222 lightStrength = 1;
223 if (lightStrength < 0)
224 lightStrength = 0;
225
226 data.pixels->set(offset, static_cast<unsigned char>(lightStrength * paintingData.colorVector.x()));
227 data.pixels->set(offset + 1, static_cast<unsigned char>(lightStrength * paintingData.colorVector.y()));
228 data.pixels->set(offset + 2, static_cast<unsigned char>(lightStrength * paintingData.colorVector.z()));
229 }
230
setPixel(int offset,LightingData & data,LightSource::PaintingData & paintingData,int lightX,int lightY,float factorX,float factorY,IntPoint & normalVector)231 void FELighting::setPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData,
232 int lightX, int lightY, float factorX, float factorY, IntPoint& normalVector)
233 {
234 inlineSetPixel(offset, data, paintingData, lightX, lightY, factorX, factorY, normalVector);
235 }
236
drawLighting(ByteArray * pixels,int width,int height)237 bool FELighting::drawLighting(ByteArray* pixels, int width, int height)
238 {
239 LightSource::PaintingData paintingData;
240 LightingData data;
241
242 if (!m_lightSource)
243 return false;
244
245 // FIXME: do something if width or height (or both) is 1 pixel.
246 // The W3 spec does not define this case. Now the filter just returns.
247 if (width <= 2 || height <= 2)
248 return false;
249
250 data.pixels = pixels;
251 data.surfaceScale = m_surfaceScale / 255.0f;
252 data.widthMultipliedByPixelSize = width * cPixelSize;
253 data.widthDecreasedByOne = width - 1;
254 data.heightDecreasedByOne = height - 1;
255 paintingData.colorVector = FloatPoint3D(m_lightingColor.red(), m_lightingColor.green(), m_lightingColor.blue());
256 m_lightSource->initPaintingData(paintingData);
257
258 // Top/Left corner
259 IntPoint normalVector;
260 int offset = 0;
261 data.topLeft(offset, normalVector);
262 setPixel(offset, data, paintingData, 0, 0, cFactor2div3, cFactor2div3, normalVector);
263
264 // Top/Right pixel
265 offset = data.widthMultipliedByPixelSize - cPixelSize;
266 data.topRight(offset, normalVector);
267 setPixel(offset, data, paintingData, data.widthDecreasedByOne, 0, cFactor2div3, cFactor2div3, normalVector);
268
269 // Bottom/Left pixel
270 offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize;
271 data.bottomLeft(offset, normalVector);
272 setPixel(offset, data, paintingData, 0, data.heightDecreasedByOne, cFactor2div3, cFactor2div3, normalVector);
273
274 // Bottom/Right pixel
275 offset = height * data.widthMultipliedByPixelSize - cPixelSize;
276 data.bottomRight(offset, normalVector);
277 setPixel(offset, data, paintingData, data.widthDecreasedByOne, data.heightDecreasedByOne, cFactor2div3, cFactor2div3, normalVector);
278
279 if (width >= 3) {
280 // Top row
281 offset = cPixelSize;
282 for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize) {
283 data.topRow(offset, normalVector);
284 inlineSetPixel(offset, data, paintingData, x, 0, cFactor1div3, cFactor1div2, normalVector);
285 }
286 // Bottom row
287 offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize + cPixelSize;
288 for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize) {
289 data.bottomRow(offset, normalVector);
290 inlineSetPixel(offset, data, paintingData, x, data.heightDecreasedByOne, cFactor1div3, cFactor1div2, normalVector);
291 }
292 }
293
294 if (height >= 3) {
295 // Left column
296 offset = data.widthMultipliedByPixelSize;
297 for (int y = 1; y < data.heightDecreasedByOne; ++y, offset += data.widthMultipliedByPixelSize) {
298 data.leftColumn(offset, normalVector);
299 inlineSetPixel(offset, data, paintingData, 0, y, cFactor1div2, cFactor1div3, normalVector);
300 }
301 // Right column
302 offset = (data.widthMultipliedByPixelSize << 1) - cPixelSize;
303 for (int y = 1; y < data.heightDecreasedByOne; ++y, offset += data.widthMultipliedByPixelSize) {
304 data.rightColumn(offset, normalVector);
305 inlineSetPixel(offset, data, paintingData, data.widthDecreasedByOne, y, cFactor1div2, cFactor1div3, normalVector);
306 }
307 }
308
309 if (width >= 3 && height >= 3) {
310 // Interior pixels
311 #if CPU(ARM_NEON) && COMPILER(GCC)
312 drawInteriorPixels(data, paintingData);
313 #else
314 for (int y = 1; y < data.heightDecreasedByOne; ++y) {
315 offset = y * data.widthMultipliedByPixelSize + cPixelSize;
316 for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize) {
317 data.interior(offset, normalVector);
318 inlineSetPixel(offset, data, paintingData, x, y, cFactor1div4, cFactor1div4, normalVector);
319 }
320 }
321 #endif
322 }
323
324 int lastPixel = data.widthMultipliedByPixelSize * height;
325 if (m_lightingType == DiffuseLighting) {
326 for (int i = cAlphaChannelOffset; i < lastPixel; i += cPixelSize)
327 data.pixels->set(i, cOpaqueAlpha);
328 } else {
329 for (int i = 0; i < lastPixel; i += cPixelSize) {
330 unsigned char a1 = data.pixels->get(i);
331 unsigned char a2 = data.pixels->get(i + 1);
332 unsigned char a3 = data.pixels->get(i + 2);
333 // alpha set to set to max(a1, a2, a3)
334 data.pixels->set(i + 3, a1 >= a2 ? (a1 >= a3 ? a1 : a3) : (a2 >= a3 ? a2 : a3));
335 }
336 }
337
338 return true;
339 }
340
apply()341 void FELighting::apply()
342 {
343 if (hasResult())
344 return;
345 FilterEffect* in = inputEffect(0);
346 in->apply();
347 if (!in->hasResult())
348 return;
349
350 ByteArray* srcPixelArray = createUnmultipliedImageResult();
351 if (!srcPixelArray)
352 return;
353
354 setIsAlphaImage(false);
355
356 IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
357 in->copyUnmultipliedImage(srcPixelArray, effectDrawingRect);
358
359 // FIXME: support kernelUnitLengths other than (1,1). The issue here is that the W3
360 // standard has no test case for them, and other browsers (like Firefox) has strange
361 // output for various kernelUnitLengths, and I am not sure they are reliable.
362 // Anyway, feConvolveMatrix should also use the implementation
363
364 IntSize absolutePaintSize = absolutePaintRect().size();
365 drawLighting(srcPixelArray, absolutePaintSize.width(), absolutePaintSize.height());
366 }
367
368 #if CPU(ARM_NEON) && COMPILER(GCC)
369
getPowerCoefficients(float exponent)370 static int getPowerCoefficients(float exponent)
371 {
372 // Calling a powf function from the assembly code would require to save
373 // and reload a lot of NEON registers. Since the base is in range [0..1]
374 // and only 8 bit precision is required, we use our own powf function.
375 // This is probably not the best, but it uses only a few registers and
376 // gives us enough precision (modifying the exponent field directly would
377 // also be possible).
378
379 // First, we limit the exponent to maximum of 64, which gives us enough
380 // precision. We split the exponent to an integer and fraction part,
381 // since a^x = (a^y)*(a^z) where x = y+z. The integer exponent of the
382 // power is estimated by square, and the fraction exponent of the power
383 // is estimated by square root assembly instructions.
384 int i, result;
385
386 if (exponent < 0)
387 exponent = 1 / (-exponent);
388
389 if (exponent > 63.99)
390 exponent = 63.99;
391
392 exponent /= 64;
393 result = 0;
394 for (i = 11; i >= 0; --i) {
395 exponent *= 2;
396 if (exponent >= 1) {
397 result |= 1 << i;
398 exponent -= 1;
399 }
400 }
401 return result;
402 }
403
drawInteriorPixels(LightingData & data,LightSource::PaintingData & paintingData)404 void FELighting::drawInteriorPixels(LightingData& data, LightSource::PaintingData& paintingData)
405 {
406 WTF_ALIGNED(FELightingFloatArgumentsForNeon, floatArguments, 16);
407
408 FELightingPaintingDataForNeon neonData = {
409 data.pixels->data(),
410 data.widthDecreasedByOne - 1,
411 data.heightDecreasedByOne - 1,
412 0,
413 0,
414 0,
415 &floatArguments,
416 feLightingConstantsForNeon()
417 };
418
419 // Set light source arguments.
420 floatArguments.constOne = 1;
421
422 floatArguments.colorRed = m_lightingColor.red();
423 floatArguments.colorGreen = m_lightingColor.green();
424 floatArguments.colorBlue = m_lightingColor.blue();
425 floatArguments.padding4 = 0;
426
427 if (m_lightSource->type() == LS_POINT) {
428 neonData.flags |= FLAG_POINT_LIGHT;
429 PointLightSource* pointLightSource = static_cast<PointLightSource*>(m_lightSource.get());
430 floatArguments.lightX = pointLightSource->position().x();
431 floatArguments.lightY = pointLightSource->position().y();
432 floatArguments.lightZ = pointLightSource->position().z();
433 floatArguments.padding2 = 0;
434 } else if (m_lightSource->type() == LS_SPOT) {
435 neonData.flags |= FLAG_SPOT_LIGHT;
436 SpotLightSource* spotLightSource = static_cast<SpotLightSource*>(m_lightSource.get());
437 floatArguments.lightX = spotLightSource->position().x();
438 floatArguments.lightY = spotLightSource->position().y();
439 floatArguments.lightZ = spotLightSource->position().z();
440 floatArguments.padding2 = 0;
441
442 floatArguments.directionX = paintingData.directionVector.x();
443 floatArguments.directionY = paintingData.directionVector.y();
444 floatArguments.directionZ = paintingData.directionVector.z();
445 floatArguments.padding3 = 0;
446
447 floatArguments.coneCutOffLimit = paintingData.coneCutOffLimit;
448 floatArguments.coneFullLight = paintingData.coneFullLight;
449 floatArguments.coneCutOffRange = paintingData.coneCutOffLimit - paintingData.coneFullLight;
450 neonData.coneExponent = getPowerCoefficients(spotLightSource->specularExponent());
451 if (spotLightSource->specularExponent() == 1)
452 neonData.flags |= FLAG_CONE_EXPONENT_IS_1;
453 } else {
454 ASSERT(m_lightSource.type == LS_DISTANT);
455 floatArguments.lightX = paintingData.lightVector.x();
456 floatArguments.lightY = paintingData.lightVector.y();
457 floatArguments.lightZ = paintingData.lightVector.z();
458 floatArguments.padding2 = 1;
459 }
460
461 // Set lighting arguments.
462 floatArguments.surfaceScale = data.surfaceScale;
463 floatArguments.minusSurfaceScaleDividedByFour = -data.surfaceScale / 4;
464 if (m_lightingType == FELighting::DiffuseLighting)
465 floatArguments.diffuseConstant = m_diffuseConstant;
466 else {
467 neonData.flags |= FLAG_SPECULAR_LIGHT;
468 floatArguments.diffuseConstant = m_specularConstant;
469 neonData.specularExponent = getPowerCoefficients(m_specularExponent);
470 if (m_specularExponent == 1)
471 neonData.flags |= FLAG_SPECULAR_EXPONENT_IS_1;
472 }
473 if (floatArguments.diffuseConstant == 1)
474 neonData.flags |= FLAG_DIFFUSE_CONST_IS_1;
475
476 neonDrawLighting(&neonData);
477 }
478 #endif // CPU(ARM_NEON) && COMPILER(GCC)
479
480 } // namespace WebCore
481
482 #endif // ENABLE(FILTERS)
483