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