12fc2651226baac27029e38c9d6ef883fa32084dbSteve Block/* 22fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> 32fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> 42fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> 52fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * Copyright (C) 2005 Eric Seidel <eric@webkit.org> 62fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * Copyright (C) 2010 Zoltan Herczeg <zherczeg@webkit.org> 72fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * Copyright (C) 2011 University of Szeged 82fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * Copyright (C) 2011 Renata Hodovan <reni@webkit.org> 92fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * 102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * Redistribution and use in source and binary forms, with or without 112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * modification, are permitted provided that the following conditions 122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * are met: 132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * 1. Redistributions of source code must retain the above copyright 142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * notice, this list of conditions and the following disclaimer. 152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * 2. Redistributions in binary form must reproduce the above copyright 162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * notice, this list of conditions and the following disclaimer in the 172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * documentation and/or other materials provided with the distribution. 182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * 192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY 202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR 232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block */ 312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "config.h" 332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#if ENABLE(FILTERS) 352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "SpotLightSource.h" 362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "TextStream.h" 382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 392fc2651226baac27029e38c9d6ef883fa32084dbSteve Blocknamespace WebCore { 402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// spot-light edge darkening depends on an absolute treshold 422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block// according to the SVG 1.1 SE light regression tests 432fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic const float antiAliasTreshold = 0.016f; 442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 452fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid SpotLightSource::initPaintingData(PaintingData& paintingData) 462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.privateColorVector = paintingData.colorVector; 482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.directionVector.setX(m_direction.x() - m_position.x()); 492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.directionVector.setY(m_direction.y() - m_position.y()); 502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.directionVector.setZ(m_direction.z() - m_position.z()); 512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.directionVector.normalize(); 522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (!m_limitingConeAngle) { 542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.coneCutOffLimit = 0.0f; 552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.coneFullLight = -antiAliasTreshold; 562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } else { 572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block float limitingConeAngle = m_limitingConeAngle; 582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (limitingConeAngle < 0.0f) 592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block limitingConeAngle = -limitingConeAngle; 602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (limitingConeAngle > 90.0f) 612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block limitingConeAngle = 90.0f; 622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.coneCutOffLimit = cosf(deg2rad(180.0f - limitingConeAngle)); 632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.coneFullLight = paintingData.coneCutOffLimit - antiAliasTreshold; 642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Optimization for common specularExponent values 672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (!m_specularExponent) 682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.specularExponent = 0; 692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block else if (m_specularExponent == 1.0f) 702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.specularExponent = 1; 712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block else // It is neither 0.0f nor 1.0f 722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.specularExponent = 2; 732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 752fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid SpotLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z) 762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.lightVector.setX(m_position.x() - x); 782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.lightVector.setY(m_position.y() - y); 792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.lightVector.setZ(m_position.z() - z); 802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.lightVectorLength = paintingData.lightVector.length(); 812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block float cosineOfAngle = (paintingData.lightVector * paintingData.directionVector) / paintingData.lightVectorLength; 832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (cosineOfAngle > paintingData.coneCutOffLimit) { 842fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // No light is produced, scanlines are not updated 852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.colorVector.setX(0.0f); 862fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.colorVector.setY(0.0f); 872fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.colorVector.setZ(0.0f); 882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return; 892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Set the color of the pixel 922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block float lightStrength; 932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block switch (paintingData.specularExponent) { 942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block case 0: 952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block lightStrength = 1.0f; // -cosineOfAngle ^ 0 == 1 962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block break; 972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block case 1: 982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block lightStrength = -cosineOfAngle; // -cosineOfAngle ^ 1 == -cosineOfAngle 992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block break; 1002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block default: 1012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block lightStrength = powf(-cosineOfAngle, m_specularExponent); 1022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block break; 1032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 1042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (cosineOfAngle > paintingData.coneFullLight) 1062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block lightStrength *= (paintingData.coneCutOffLimit - cosineOfAngle) / (paintingData.coneCutOffLimit - paintingData.coneFullLight); 1072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (lightStrength > 1.0f) 1092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block lightStrength = 1.0f; 1102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.colorVector.setX(paintingData.privateColorVector.x() * lightStrength); 1122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.colorVector.setY(paintingData.privateColorVector.y() * lightStrength); 1132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block paintingData.colorVector.setZ(paintingData.privateColorVector.z() * lightStrength); 1142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 1152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1162fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockbool SpotLightSource::setX(float x) 1172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 1182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (m_position.x() == x) 1192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return false; 1202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_position.setX(x); 1212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return true; 1222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 1232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1242fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockbool SpotLightSource::setY(float y) 1252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 1262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (m_position.y() == y) 1272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return false; 1282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_position.setY(y); 1292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return true; 1302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 1312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1322fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockbool SpotLightSource::setZ(float z) 1332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 1342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (m_position.z() == z) 1352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return false; 1362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_position.setZ(z); 1372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return true; 1382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 1392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1402fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockbool SpotLightSource::setPointsAtX(float pointsAtX) 1412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 1422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (m_direction.x() == pointsAtX) 1432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return false; 1442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_direction.setX(pointsAtX); 1452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return true; 1462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 1472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1482fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockbool SpotLightSource::setPointsAtY(float pointsAtY) 1492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 1502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (m_direction.y() == pointsAtY) 1512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return false; 1522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_direction.setY(pointsAtY); 1532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return true; 1542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 1552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1562fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockbool SpotLightSource::setPointsAtZ(float pointsAtZ) 1572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 1582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (m_direction.z() == pointsAtZ) 1592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return false; 1602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_direction.setZ(pointsAtZ); 1612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return true; 1622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 1632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1642fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockbool SpotLightSource::setSpecularExponent(float specularExponent) 1652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 1662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (m_specularExponent == specularExponent) 1672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return false; 1682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_specularExponent = specularExponent; 1692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return true; 1702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 1712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1722fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockbool SpotLightSource::setLimitingConeAngle(float limitingConeAngle) 1732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 1742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (m_limitingConeAngle == limitingConeAngle) 1752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return false; 1762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block m_limitingConeAngle = limitingConeAngle; 1772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return true; 1782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 1792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1802fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic TextStream& operator<<(TextStream& ts, const FloatPoint3D& p) 1812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 1822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ts << "x=" << p.x() << " y=" << p.y() << " z=" << p.z(); 1832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return ts; 1842fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 1852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1862fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockTextStream& SpotLightSource::externalRepresentation(TextStream& ts) const 1872fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 1882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ts << "[type=SPOT-LIGHT] "; 1892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ts << "[position=\"" << position() << "\"]"; 1902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ts << "[direction=\"" << direction() << "\"]"; 1912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ts << "[specularExponent=\"" << specularExponent() << "\"]"; 1922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ts << "[limitingConeAngle=\"" << limitingConeAngle() << "\"]"; 1932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return ts; 1942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 1952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}; // namespace WebCore 1972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#endif // ENABLE(FILTERS) 199