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