Home | History | Annotate | Download | only in filters
      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 
     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
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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