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 #include "core/platform/graphics/filters/SpotLightSource.h"
     35 
     36 #include "core/platform/text/TextStream.h"
     37 
     38 namespace WebCore {
     39 
     40 // spot-light edge darkening depends on an absolute treshold
     41 // according to the SVG 1.1 SE light regression tests
     42 static const float antiAliasTreshold = 0.016f;
     43 
     44 void SpotLightSource::initPaintingData(PaintingData& paintingData)
     45 {
     46     paintingData.privateColorVector = paintingData.colorVector;
     47     paintingData.directionVector.setX(m_direction.x() - m_position.x());
     48     paintingData.directionVector.setY(m_direction.y() - m_position.y());
     49     paintingData.directionVector.setZ(m_direction.z() - m_position.z());
     50     paintingData.directionVector.normalize();
     51 
     52     if (!m_limitingConeAngle) {
     53         paintingData.coneCutOffLimit = 0.0f;
     54         paintingData.coneFullLight = -antiAliasTreshold;
     55     } else {
     56         float limitingConeAngle = m_limitingConeAngle;
     57         if (limitingConeAngle < 0.0f)
     58             limitingConeAngle = -limitingConeAngle;
     59         if (limitingConeAngle > 90.0f)
     60             limitingConeAngle = 90.0f;
     61         paintingData.coneCutOffLimit = cosf(deg2rad(180.0f - limitingConeAngle));
     62         paintingData.coneFullLight = paintingData.coneCutOffLimit - antiAliasTreshold;
     63     }
     64 
     65     // Optimization for common specularExponent values
     66     if (!m_specularExponent)
     67         paintingData.specularExponent = 0;
     68     else if (m_specularExponent == 1.0f)
     69         paintingData.specularExponent = 1;
     70     else // It is neither 0.0f nor 1.0f
     71         paintingData.specularExponent = 2;
     72 }
     73 
     74 void SpotLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z)
     75 {
     76     paintingData.lightVector.setX(m_position.x() - x);
     77     paintingData.lightVector.setY(m_position.y() - y);
     78     paintingData.lightVector.setZ(m_position.z() - z);
     79     paintingData.lightVectorLength = paintingData.lightVector.length();
     80 
     81     float cosineOfAngle = (paintingData.lightVector * paintingData.directionVector) / paintingData.lightVectorLength;
     82     if (cosineOfAngle > paintingData.coneCutOffLimit) {
     83         // No light is produced, scanlines are not updated
     84         paintingData.colorVector.setX(0.0f);
     85         paintingData.colorVector.setY(0.0f);
     86         paintingData.colorVector.setZ(0.0f);
     87         return;
     88     }
     89 
     90     // Set the color of the pixel
     91     float lightStrength;
     92     switch (paintingData.specularExponent) {
     93     case 0:
     94         lightStrength = 1.0f; // -cosineOfAngle ^ 0 == 1
     95         break;
     96     case 1:
     97         lightStrength = -cosineOfAngle; // -cosineOfAngle ^ 1 == -cosineOfAngle
     98         break;
     99     default:
    100         lightStrength = powf(-cosineOfAngle, m_specularExponent);
    101         break;
    102     }
    103 
    104     if (cosineOfAngle > paintingData.coneFullLight)
    105         lightStrength *= (paintingData.coneCutOffLimit - cosineOfAngle) / (paintingData.coneCutOffLimit - paintingData.coneFullLight);
    106 
    107     if (lightStrength > 1.0f)
    108         lightStrength = 1.0f;
    109 
    110     paintingData.colorVector.setX(paintingData.privateColorVector.x() * lightStrength);
    111     paintingData.colorVector.setY(paintingData.privateColorVector.y() * lightStrength);
    112     paintingData.colorVector.setZ(paintingData.privateColorVector.z() * lightStrength);
    113 }
    114 
    115 bool SpotLightSource::setX(float x)
    116 {
    117     if (m_position.x() == x)
    118         return false;
    119     m_position.setX(x);
    120     return true;
    121 }
    122 
    123 bool SpotLightSource::setY(float y)
    124 {
    125     if (m_position.y() == y)
    126         return false;
    127     m_position.setY(y);
    128     return true;
    129 }
    130 
    131 bool SpotLightSource::setZ(float z)
    132 {
    133     if (m_position.z() == z)
    134         return false;
    135     m_position.setZ(z);
    136     return true;
    137 }
    138 
    139 bool SpotLightSource::setPointsAtX(float pointsAtX)
    140 {
    141     if (m_direction.x() == pointsAtX)
    142         return false;
    143     m_direction.setX(pointsAtX);
    144     return true;
    145 }
    146 
    147 bool SpotLightSource::setPointsAtY(float pointsAtY)
    148 {
    149     if (m_direction.y() == pointsAtY)
    150         return false;
    151     m_direction.setY(pointsAtY);
    152     return true;
    153 }
    154 
    155 bool SpotLightSource::setPointsAtZ(float pointsAtZ)
    156 {
    157     if (m_direction.z() == pointsAtZ)
    158         return false;
    159     m_direction.setZ(pointsAtZ);
    160     return true;
    161 }
    162 
    163 bool SpotLightSource::setSpecularExponent(float specularExponent)
    164 {
    165     if (m_specularExponent == specularExponent)
    166         return false;
    167     m_specularExponent = specularExponent;
    168     return true;
    169 }
    170 
    171 bool SpotLightSource::setLimitingConeAngle(float limitingConeAngle)
    172 {
    173     if (m_limitingConeAngle == limitingConeAngle)
    174         return false;
    175     m_limitingConeAngle = limitingConeAngle;
    176     return true;
    177 }
    178 
    179 static TextStream& operator<<(TextStream& ts, const FloatPoint3D& p)
    180 {
    181     ts << "x=" << p.x() << " y=" << p.y() << " z=" << p.z();
    182     return ts;
    183 }
    184 
    185 TextStream& SpotLightSource::externalRepresentation(TextStream& ts) const
    186 {
    187     ts << "[type=SPOT-LIGHT] ";
    188     ts << "[position=\"" << position() << "\"]";
    189     ts << "[direction=\"" << direction() << "\"]";
    190     ts << "[specularExponent=\"" << specularExponent() << "\"]";
    191     ts << "[limitingConeAngle=\"" << limitingConeAngle() << "\"]";
    192     return ts;
    193 }
    194 
    195 }; // namespace WebCore
    196