1/* 2 * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> 3 * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> 4 * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> 5 * Copyright (C) 2005 Eric Seidel <eric@webkit.org> 6 * Copyright (C) 2010 Zoltan Herczeg <zherczeg@webkit.org> 7 * Copyright (C) 2011 University of Szeged 8 * Copyright (C) 2011 Renata Hodovan <reni@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 39namespace WebCore { 40 41// spot-light edge darkening depends on an absolute treshold 42// according to the SVG 1.1 SE light regression tests 43static const float antiAliasTreshold = 0.016f; 44 45void 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 75void 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 116bool SpotLightSource::setX(float x) 117{ 118 if (m_position.x() == x) 119 return false; 120 m_position.setX(x); 121 return true; 122} 123 124bool SpotLightSource::setY(float y) 125{ 126 if (m_position.y() == y) 127 return false; 128 m_position.setY(y); 129 return true; 130} 131 132bool SpotLightSource::setZ(float z) 133{ 134 if (m_position.z() == z) 135 return false; 136 m_position.setZ(z); 137 return true; 138} 139 140bool SpotLightSource::setPointsAtX(float pointsAtX) 141{ 142 if (m_direction.x() == pointsAtX) 143 return false; 144 m_direction.setX(pointsAtX); 145 return true; 146} 147 148bool SpotLightSource::setPointsAtY(float pointsAtY) 149{ 150 if (m_direction.y() == pointsAtY) 151 return false; 152 m_direction.setY(pointsAtY); 153 return true; 154} 155 156bool SpotLightSource::setPointsAtZ(float pointsAtZ) 157{ 158 if (m_direction.z() == pointsAtZ) 159 return false; 160 m_direction.setZ(pointsAtZ); 161 return true; 162} 163 164bool SpotLightSource::setSpecularExponent(float specularExponent) 165{ 166 if (m_specularExponent == specularExponent) 167 return false; 168 m_specularExponent = specularExponent; 169 return true; 170} 171 172bool SpotLightSource::setLimitingConeAngle(float limitingConeAngle) 173{ 174 if (m_limitingConeAngle == limitingConeAngle) 175 return false; 176 m_limitingConeAngle = limitingConeAngle; 177 return true; 178} 179 180static TextStream& operator<<(TextStream& ts, const FloatPoint3D& p) 181{ 182 ts << "x=" << p.x() << " y=" << p.y() << " z=" << p.z(); 183 return ts; 184} 185 186TextStream& 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