Home | History | Annotate | Download | only in filters
      1 /*
      2  * Copyright (C) 2008 Alex Mathews <possessedpenguinbob (at) gmail.com>
      3  * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann (at) kde.org>
      4  * Copyright (C) 2004, 2005 Rob Buis <buis (at) kde.org>
      5  * Copyright (C) 2005 Eric Seidel <eric (at) webkit.org>
      6  * Copyright (C) 2010 Zoltan Herczeg <zherczeg (at) webkit.org>
      7  * Copyright (C) 2011 University of Szeged
      8  * Copyright (C) 2011 Renata Hodovan <reni (at) webkit.org>
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY
     20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL UNIVERSITY OF SZEGED OR
     23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     27  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include "config.h"
     33 
     34 #if ENABLE(FILTERS)
     35 #include "SpotLightSource.h"
     36 
     37 #include "TextStream.h"
     38 
     39 namespace WebCore {
     40 
     41 // spot-light edge darkening depends on an absolute treshold
     42 // according to the SVG 1.1 SE light regression tests
     43 static const float antiAliasTreshold = 0.016f;
     44 
     45 void SpotLightSource::initPaintingData(PaintingData& paintingData)
     46 {
     47     paintingData.privateColorVector = paintingData.colorVector;
     48     paintingData.directionVector.setX(m_direction.x() - m_position.x());
     49     paintingData.directionVector.setY(m_direction.y() - m_position.y());
     50     paintingData.directionVector.setZ(m_direction.z() - m_position.z());
     51     paintingData.directionVector.normalize();
     52 
     53     if (!m_limitingConeAngle) {
     54         paintingData.coneCutOffLimit = 0.0f;
     55         paintingData.coneFullLight = -antiAliasTreshold;
     56     } else {
     57         float limitingConeAngle = m_limitingConeAngle;
     58         if (limitingConeAngle < 0.0f)
     59             limitingConeAngle = -limitingConeAngle;
     60         if (limitingConeAngle > 90.0f)
     61             limitingConeAngle = 90.0f;
     62         paintingData.coneCutOffLimit = cosf(deg2rad(180.0f - limitingConeAngle));
     63         paintingData.coneFullLight = paintingData.coneCutOffLimit - antiAliasTreshold;
     64     }
     65 
     66     // Optimization for common specularExponent values
     67     if (!m_specularExponent)
     68         paintingData.specularExponent = 0;
     69     else if (m_specularExponent == 1.0f)
     70         paintingData.specularExponent = 1;
     71     else // It is neither 0.0f nor 1.0f
     72         paintingData.specularExponent = 2;
     73 }
     74 
     75 void SpotLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z)
     76 {
     77     paintingData.lightVector.setX(m_position.x() - x);
     78     paintingData.lightVector.setY(m_position.y() - y);
     79     paintingData.lightVector.setZ(m_position.z() - z);
     80     paintingData.lightVectorLength = paintingData.lightVector.length();
     81 
     82     float cosineOfAngle = (paintingData.lightVector * paintingData.directionVector) / paintingData.lightVectorLength;
     83     if (cosineOfAngle > paintingData.coneCutOffLimit) {
     84         // No light is produced, scanlines are not updated
     85         paintingData.colorVector.setX(0.0f);
     86         paintingData.colorVector.setY(0.0f);
     87         paintingData.colorVector.setZ(0.0f);
     88         return;
     89     }
     90 
     91     // Set the color of the pixel
     92     float lightStrength;
     93     switch (paintingData.specularExponent) {
     94     case 0:
     95         lightStrength = 1.0f; // -cosineOfAngle ^ 0 == 1
     96         break;
     97     case 1:
     98         lightStrength = -cosineOfAngle; // -cosineOfAngle ^ 1 == -cosineOfAngle
     99         break;
    100     default:
    101         lightStrength = powf(-cosineOfAngle, m_specularExponent);
    102         break;
    103     }
    104 
    105     if (cosineOfAngle > paintingData.coneFullLight)
    106         lightStrength *= (paintingData.coneCutOffLimit - cosineOfAngle) / (paintingData.coneCutOffLimit - paintingData.coneFullLight);
    107 
    108     if (lightStrength > 1.0f)
    109         lightStrength = 1.0f;
    110 
    111     paintingData.colorVector.setX(paintingData.privateColorVector.x() * lightStrength);
    112     paintingData.colorVector.setY(paintingData.privateColorVector.y() * lightStrength);
    113     paintingData.colorVector.setZ(paintingData.privateColorVector.z() * lightStrength);
    114 }
    115 
    116 bool SpotLightSource::setX(float x)
    117 {
    118     if (m_position.x() == x)
    119         return false;
    120     m_position.setX(x);
    121     return true;
    122 }
    123 
    124 bool SpotLightSource::setY(float y)
    125 {
    126     if (m_position.y() == y)
    127         return false;
    128     m_position.setY(y);
    129     return true;
    130 }
    131 
    132 bool SpotLightSource::setZ(float z)
    133 {
    134     if (m_position.z() == z)
    135         return false;
    136     m_position.setZ(z);
    137     return true;
    138 }
    139 
    140 bool SpotLightSource::setPointsAtX(float pointsAtX)
    141 {
    142     if (m_direction.x() == pointsAtX)
    143         return false;
    144     m_direction.setX(pointsAtX);
    145     return true;
    146 }
    147 
    148 bool SpotLightSource::setPointsAtY(float pointsAtY)
    149 {
    150     if (m_direction.y() == pointsAtY)
    151         return false;
    152     m_direction.setY(pointsAtY);
    153     return true;
    154 }
    155 
    156 bool SpotLightSource::setPointsAtZ(float pointsAtZ)
    157 {
    158     if (m_direction.z() == pointsAtZ)
    159         return false;
    160     m_direction.setZ(pointsAtZ);
    161     return true;
    162 }
    163 
    164 bool SpotLightSource::setSpecularExponent(float specularExponent)
    165 {
    166     if (m_specularExponent == specularExponent)
    167         return false;
    168     m_specularExponent = specularExponent;
    169     return true;
    170 }
    171 
    172 bool SpotLightSource::setLimitingConeAngle(float limitingConeAngle)
    173 {
    174     if (m_limitingConeAngle == limitingConeAngle)
    175         return false;
    176     m_limitingConeAngle = limitingConeAngle;
    177     return true;
    178 }
    179 
    180 static TextStream& operator<<(TextStream& ts, const FloatPoint3D& p)
    181 {
    182     ts << "x=" << p.x() << " y=" << p.y() << " z=" << p.z();
    183     return ts;
    184 }
    185 
    186 TextStream& SpotLightSource::externalRepresentation(TextStream& ts) const
    187 {
    188     ts << "[type=SPOT-LIGHT] ";
    189     ts << "[position=\"" << position() << "\"]";
    190     ts << "[direction=\"" << direction() << "\"]";
    191     ts << "[specularExponent=\"" << specularExponent() << "\"]";
    192     ts << "[limitingConeAngle=\"" << limitingConeAngle() << "\"]";
    193     return ts;
    194 }
    195 
    196 }; // namespace WebCore
    197 
    198 #endif // ENABLE(FILTERS)
    199