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