diff options
author | Kristian Monsen <kristianm@google.com> | 2010-05-21 16:53:46 +0100 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2010-05-25 10:24:15 +0100 |
commit | 6c2af9490927c3c5959b5cb07461b646f8b32f6c (patch) | |
tree | f7111b9b22befab472616c1d50ec94eb50f1ec8c /WebCore/svg/graphics | |
parent | a149172322a9067c14e8b474a53e63649aa17cad (diff) | |
download | external_webkit-6c2af9490927c3c5959b5cb07461b646f8b32f6c.zip external_webkit-6c2af9490927c3c5959b5cb07461b646f8b32f6c.tar.gz external_webkit-6c2af9490927c3c5959b5cb07461b646f8b32f6c.tar.bz2 |
Merge WebKit at r59636: Initial merge by git
Change-Id: I59b289c4e6b18425f06ce41cc9d34c522515de91
Diffstat (limited to 'WebCore/svg/graphics')
29 files changed, 815 insertions, 324 deletions
diff --git a/WebCore/svg/graphics/filters/SVGDistantLightSource.h b/WebCore/svg/graphics/filters/SVGDistantLightSource.h index db9b59d..97853db 100644 --- a/WebCore/svg/graphics/filters/SVGDistantLightSource.h +++ b/WebCore/svg/graphics/filters/SVGDistantLightSource.h @@ -28,29 +28,32 @@ namespace WebCore { - class DistantLightSource : public LightSource { - public: - static PassRefPtr<DistantLightSource> create(float azimuth, float elevation) - { - return adoptRef(new DistantLightSource(azimuth, elevation)); - } - - float azimuth() const { return m_azimuth; } - float elevation() const { return m_elevation; } - - virtual TextStream& externalRepresentation(TextStream&) const; - - private: - DistantLightSource(float azimuth, float elevation) - : LightSource(LS_DISTANT) - , m_azimuth(azimuth) - , m_elevation(elevation) - { - } - - float m_azimuth; - float m_elevation; - }; +class DistantLightSource : public LightSource { +public: + static PassRefPtr<DistantLightSource> create(float azimuth, float elevation) + { + return adoptRef(new DistantLightSource(azimuth, elevation)); + } + + float azimuth() const { return m_azimuth; } + float elevation() const { return m_elevation; } + + virtual void initPaintingData(PaintingData&); + virtual void updatePaintingData(PaintingData&, int x, int y, float z); + + virtual TextStream& externalRepresentation(TextStream&) const; + +private: + DistantLightSource(float azimuth, float elevation) + : LightSource(LS_DISTANT) + , m_azimuth(azimuth) + , m_elevation(elevation) + { + } + + float m_azimuth; + float m_elevation; +}; } // namespace WebCore diff --git a/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.cpp b/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.cpp index 5197215..916b2f9 100644 --- a/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.cpp +++ b/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.cpp @@ -142,34 +142,41 @@ void FEConvolveMatrix::dump() { } -static TextStream& operator<<(TextStream& ts, EdgeModeType t) +static TextStream& operator<<(TextStream& ts, const EdgeModeType& type) { - switch (t) + switch (type) { - case EDGEMODE_UNKNOWN: - ts << "UNKNOWN";break; - case EDGEMODE_DUPLICATE: - ts << "DUPLICATE";break; - case EDGEMODE_WRAP: - ts << "WRAP"; break; - case EDGEMODE_NONE: - ts << "NONE"; break; + case EDGEMODE_UNKNOWN: + ts << "UNKNOWN"; + break; + case EDGEMODE_DUPLICATE: + ts << "DUPLICATE"; + break; + case EDGEMODE_WRAP: + ts << "WRAP"; + break; + case EDGEMODE_NONE: + ts << "NONE"; + break; } return ts; } -TextStream& FEConvolveMatrix::externalRepresentation(TextStream& ts) const +TextStream& FEConvolveMatrix::externalRepresentation(TextStream& ts, int indent) const { - ts << "[type=CONVOLVE-MATRIX] "; + writeIndent(ts, indent); + ts << "[feConvolveMatrix"; FilterEffect::externalRepresentation(ts); - ts << " [order " << m_kernelSize << "]" - << " [kernel matrix=" << m_kernelMatrix << "]" - << " [divisor=" << m_divisor << "]" - << " [bias=" << m_bias << "]" - << " [target " << m_targetOffset << "]" - << " [edge mode=" << m_edgeMode << "]" - << " [kernel unit length " << m_kernelUnitLength << "]" - << " [preserve alpha=" << m_preserveAlpha << "]"; + ts << " order=\"" << m_kernelSize << "\" " + << "kernelMatrix=\"" << m_kernelMatrix << "\" " + << "divisor=\"" << m_divisor << "\" " + << "bias=\"" << m_bias << "\" " + << "target=\"" << m_targetOffset << "\" " + << "edgeMode=\"" << m_edgeMode << "\" " + << "kernelUnitLength=\"" << m_kernelUnitLength << "\" " + << "preserveAlpha=\"" << m_preserveAlpha << "\"]\n"; + m_in->externalRepresentation(ts, indent + 1); + m_in2->externalRepresentation(ts, indent + 1); return ts; } diff --git a/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.h b/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.h index f850412..8e3a9bd 100644 --- a/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.h +++ b/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.h @@ -71,7 +71,7 @@ namespace WebCore { virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return calculateUnionOfChildEffectSubregions(filter, m_in.get(), m_in2.get()); } void apply(Filter*); void dump(); - TextStream& externalRepresentation(TextStream& ts) const; + TextStream& externalRepresentation(TextStream&, int indent) const; private: FEConvolveMatrix(FilterEffect*, FilterEffect*, const FloatSize&, const float&, const float&, diff --git a/WebCore/svg/graphics/filters/SVGFEDiffuseLighting.cpp b/WebCore/svg/graphics/filters/SVGFEDiffuseLighting.cpp index 93921df..f8d0b4e 100644 --- a/WebCore/svg/graphics/filters/SVGFEDiffuseLighting.cpp +++ b/WebCore/svg/graphics/filters/SVGFEDiffuseLighting.cpp @@ -22,29 +22,22 @@ #include "config.h" #if ENABLE(SVG) && ENABLE(FILTERS) -#include "SVGLightSource.h" #include "SVGFEDiffuseLighting.h" + +#include "SVGLightSource.h" #include "SVGRenderTreeAsText.h" -#include "Filter.h" namespace WebCore { -FEDiffuseLighting::FEDiffuseLighting(FilterEffect* in , const Color& lightingColor, const float& surfaceScale, - const float& diffuseConstant, const float& kernelUnitLengthX, const float& kernelUnitLengthY, PassRefPtr<LightSource> lightSource) - : FilterEffect() - , m_in(in) - , m_lightingColor(lightingColor) - , m_surfaceScale(surfaceScale) - , m_diffuseConstant(diffuseConstant) - , m_kernelUnitLengthX(kernelUnitLengthX) - , m_kernelUnitLengthY(kernelUnitLengthY) - , m_lightSource(lightSource) +FEDiffuseLighting::FEDiffuseLighting(FilterEffect* in, const Color& lightingColor, float surfaceScale, + float diffuseConstant, float kernelUnitLengthX, float kernelUnitLengthY, PassRefPtr<LightSource> lightSource) + : FELighting(DiffuseLighting, in, lightingColor, surfaceScale, diffuseConstant, 0.0f, 0.0f, kernelUnitLengthX, kernelUnitLengthY, lightSource) { } PassRefPtr<FEDiffuseLighting> FEDiffuseLighting::create(FilterEffect* in , const Color& lightingColor, - const float& surfaceScale, const float& diffuseConstant, const float& kernelUnitLengthX, - const float& kernelUnitLengthY, PassRefPtr<LightSource> lightSource) + float surfaceScale, float diffuseConstant, float kernelUnitLengthX, + float kernelUnitLengthY, PassRefPtr<LightSource> lightSource) { return adoptRef(new FEDiffuseLighting(in, lightingColor, surfaceScale, diffuseConstant, kernelUnitLengthX, kernelUnitLengthY, lightSource)); } @@ -113,21 +106,19 @@ void FEDiffuseLighting::setLightSource(PassRefPtr<LightSource> lightSource) m_lightSource = lightSource; } -void FEDiffuseLighting::apply(Filter*) -{ -} - void FEDiffuseLighting::dump() { } -TextStream& FEDiffuseLighting::externalRepresentation(TextStream& ts) const +TextStream& FEDiffuseLighting::externalRepresentation(TextStream& ts, int indent) const { - ts << "[type=DIFFUSE-LIGHTING] "; + writeIndent(ts, indent); + ts << "[feDiffuseLighting"; FilterEffect::externalRepresentation(ts); - ts << " [surface scale=" << m_surfaceScale << "]" - << " [diffuse constant=" << m_diffuseConstant << "]" - << " [kernel unit length " << m_kernelUnitLengthX << ", " << m_kernelUnitLengthY << "]"; + ts << " surfaceScale=\"" << m_surfaceScale << "\" " + << "diffuseConstant=\"" << m_diffuseConstant << "\" " + << "kernelUnitLength=\"" << m_kernelUnitLengthX << ", " << m_kernelUnitLengthY << "\"]\n"; + m_in->externalRepresentation(ts, indent + 1); return ts; } diff --git a/WebCore/svg/graphics/filters/SVGFEDiffuseLighting.h b/WebCore/svg/graphics/filters/SVGFEDiffuseLighting.h index bf7f28e..3fccb19 100644 --- a/WebCore/svg/graphics/filters/SVGFEDiffuseLighting.h +++ b/WebCore/svg/graphics/filters/SVGFEDiffuseLighting.h @@ -23,55 +23,43 @@ #define SVGFEDiffuseLighting_h #if ENABLE(SVG) && ENABLE(FILTERS) -#include "Color.h" -#include "FilterEffect.h" -#include "Filter.h" +#include "SVGFELighting.h" namespace WebCore { - class LightSource; - - class FEDiffuseLighting : public FilterEffect { - public: - static PassRefPtr<FEDiffuseLighting> create(FilterEffect*, const Color&, const float&, const float&, - const float&, const float&, PassRefPtr<LightSource>); - virtual ~FEDiffuseLighting(); - - Color lightingColor() const; - void setLightingColor(const Color&); - - float surfaceScale() const; - void setSurfaceScale(float); - - float diffuseConstant() const; - void setDiffuseConstant(float); - - float kernelUnitLengthX() const; - void setKernelUnitLengthX(float); - - float kernelUnitLengthY() const; - void setKernelUnitLengthY(float); - - const LightSource* lightSource() const; - void setLightSource(PassRefPtr<LightSource>); - - virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return calculateUnionOfChildEffectSubregions(filter, m_in.get()); } - void apply(Filter*); - void dump(); - TextStream& externalRepresentation(TextStream& ts) const; - - private: - FEDiffuseLighting(FilterEffect*, const Color&, const float&, const float&, - const float&, const float&, PassRefPtr<LightSource>); - - RefPtr<FilterEffect> m_in; - Color m_lightingColor; - float m_surfaceScale; - float m_diffuseConstant; - float m_kernelUnitLengthX; - float m_kernelUnitLengthY; - RefPtr<LightSource> m_lightSource; - }; +class LightSource; + +class FEDiffuseLighting : public FELighting { +public: + static PassRefPtr<FEDiffuseLighting> create(FilterEffect*, const Color&, float, float, + float, float, PassRefPtr<LightSource>); + virtual ~FEDiffuseLighting(); + + Color lightingColor() const; + void setLightingColor(const Color&); + + float surfaceScale() const; + void setSurfaceScale(float); + + float diffuseConstant() const; + void setDiffuseConstant(float); + + float kernelUnitLengthX() const; + void setKernelUnitLengthX(float); + + float kernelUnitLengthY() const; + void setKernelUnitLengthY(float); + + const LightSource* lightSource() const; + void setLightSource(PassRefPtr<LightSource>); + + void dump(); + TextStream& externalRepresentation(TextStream&, int indent) const; + +private: + FEDiffuseLighting(FilterEffect*, const Color&, float, float, + float, float, PassRefPtr<LightSource>); +}; } // namespace WebCore diff --git a/WebCore/svg/graphics/filters/SVGFEDisplacementMap.cpp b/WebCore/svg/graphics/filters/SVGFEDisplacementMap.cpp index 4610b7d..9374eda 100644 --- a/WebCore/svg/graphics/filters/SVGFEDisplacementMap.cpp +++ b/WebCore/svg/graphics/filters/SVGFEDisplacementMap.cpp @@ -133,31 +133,38 @@ void FEDisplacementMap::dump() { } -static TextStream& operator<<(TextStream& ts, ChannelSelectorType t) +static TextStream& operator<<(TextStream& ts, const ChannelSelectorType& type) { - switch (t) - { - case CHANNEL_UNKNOWN: - ts << "UNKNOWN"; break; - case CHANNEL_R: - ts << "RED"; break; - case CHANNEL_G: - ts << "GREEN"; break; - case CHANNEL_B: - ts << "BLUE"; break; - case CHANNEL_A: - ts << "ALPHA"; break; + switch (type) { + case CHANNEL_UNKNOWN: + ts << "UNKNOWN"; + break; + case CHANNEL_R: + ts << "RED"; + break; + case CHANNEL_G: + ts << "GREEN"; + break; + case CHANNEL_B: + ts << "BLUE"; + break; + case CHANNEL_A: + ts << "ALPHA"; + break; } return ts; } -TextStream& FEDisplacementMap::externalRepresentation(TextStream& ts) const +TextStream& FEDisplacementMap::externalRepresentation(TextStream& ts, int indent) const { - ts << "[type=DISPLACEMENT-MAP] "; + writeIndent(ts, indent); + ts << "[feDisplacementMap"; FilterEffect::externalRepresentation(ts); - ts << "[scale=" << m_scale << "]" - << " [x channel selector=" << m_xChannelSelector << "]" - << " [y channel selector=" << m_yChannelSelector << "]"; + ts << " scale=\"" << m_scale << "\" " + << "xChannelSelector=\"" << m_xChannelSelector << "\" " + << "yChannelSelector=\"" << m_yChannelSelector << "\"]\n"; + m_in->externalRepresentation(ts, indent + 1); + m_in2->externalRepresentation(ts, indent + 1); return ts; } diff --git a/WebCore/svg/graphics/filters/SVGFEDisplacementMap.h b/WebCore/svg/graphics/filters/SVGFEDisplacementMap.h index 007f6ba..139bd2a 100644 --- a/WebCore/svg/graphics/filters/SVGFEDisplacementMap.h +++ b/WebCore/svg/graphics/filters/SVGFEDisplacementMap.h @@ -54,7 +54,7 @@ namespace WebCore { virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return calculateUnionOfChildEffectSubregions(filter, m_in.get(), m_in2.get()); } void apply(Filter*); void dump(); - TextStream& externalRepresentation(TextStream& ts) const; + TextStream& externalRepresentation(TextStream&, int indent) const; private: FEDisplacementMap(FilterEffect*, FilterEffect*, ChannelSelectorType, diff --git a/WebCore/svg/graphics/filters/SVGFEFlood.cpp b/WebCore/svg/graphics/filters/SVGFEFlood.cpp index 648bf54..d65c382 100644 --- a/WebCore/svg/graphics/filters/SVGFEFlood.cpp +++ b/WebCore/svg/graphics/filters/SVGFEFlood.cpp @@ -77,12 +77,13 @@ void FEFlood::dump() { } -TextStream& FEFlood::externalRepresentation(TextStream& ts) const +TextStream& FEFlood::externalRepresentation(TextStream& ts, int indent) const { - ts << "[type=FLOOD] "; + writeIndent(ts, indent); + ts << "[feFlood"; FilterEffect::externalRepresentation(ts); - ts << " [color=" << floodColor() << "]" - << " [opacity=" << floodOpacity() << "]"; + ts << " flood-color=\"" << floodColor() << "\" " + << "flood-opacity=\"" << floodOpacity() << "\"]\n"; return ts; } diff --git a/WebCore/svg/graphics/filters/SVGFEFlood.h b/WebCore/svg/graphics/filters/SVGFEFlood.h index 91795dd..3db906b 100644 --- a/WebCore/svg/graphics/filters/SVGFEFlood.h +++ b/WebCore/svg/graphics/filters/SVGFEFlood.h @@ -41,7 +41,7 @@ namespace WebCore { void apply(Filter*); void dump(); - TextStream& externalRepresentation(TextStream& ts) const; + TextStream& externalRepresentation(TextStream&, int indent) const; private: FEFlood(const Color&, const float&); diff --git a/WebCore/svg/graphics/filters/SVGFEImage.cpp b/WebCore/svg/graphics/filters/SVGFEImage.cpp index 950203a..0614116 100644 --- a/WebCore/svg/graphics/filters/SVGFEImage.cpp +++ b/WebCore/svg/graphics/filters/SVGFEImage.cpp @@ -66,10 +66,14 @@ void FEImage::dump() { } -TextStream& FEImage::externalRepresentation(TextStream& ts) const +TextStream& FEImage::externalRepresentation(TextStream& ts, int indent) const { - ts << "[type=IMAGE] "; + ASSERT(m_image); + IntSize imageSize = m_image->size(); + writeIndent(ts, indent); + ts << "[feImage"; FilterEffect::externalRepresentation(ts); + ts << " image-size=\"" << imageSize.width() << "x" << imageSize.height() << "\"]\n"; // FIXME: should this dump also object returned by SVGFEImage::image() ? return ts; } diff --git a/WebCore/svg/graphics/filters/SVGFEImage.h b/WebCore/svg/graphics/filters/SVGFEImage.h index 01e9522..3702d2b 100644 --- a/WebCore/svg/graphics/filters/SVGFEImage.h +++ b/WebCore/svg/graphics/filters/SVGFEImage.h @@ -35,7 +35,7 @@ namespace WebCore { void apply(Filter*); void dump(); - TextStream& externalRepresentation(TextStream& ts) const; + TextStream& externalRepresentation(TextStream&, int indent) const; private: FEImage(RefPtr<Image>, SVGPreserveAspectRatio); diff --git a/WebCore/svg/graphics/filters/SVGFELighting.cpp b/WebCore/svg/graphics/filters/SVGFELighting.cpp new file mode 100644 index 0000000..980e936 --- /dev/null +++ b/WebCore/svg/graphics/filters/SVGFELighting.cpp @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2010 University of Szeged + * Copyright (C) 2010 Zoltan Herczeg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(SVG) && ENABLE(FILTERS) +#include "SVGFELighting.h" + +#include "CanvasPixelArray.h" +#include "ImageData.h" +#include "SVGLightSource.h" + +namespace WebCore { + +FELighting::FELighting(LightingType lightingType, FilterEffect* in, const Color& lightingColor, float surfaceScale, + float diffuseConstant, float specularConstant, float specularExponent, + float kernelUnitLengthX, float kernelUnitLengthY, PassRefPtr<LightSource> lightSource) + : FilterEffect() + , m_lightingType(lightingType) + , m_in(in) + , m_lightSource(lightSource) + , m_lightingColor(lightingColor) + , m_surfaceScale(surfaceScale) + , m_diffuseConstant(diffuseConstant) + , m_specularConstant(specularConstant) + , m_specularExponent(specularExponent) + , m_kernelUnitLengthX(kernelUnitLengthX) + , m_kernelUnitLengthY(kernelUnitLengthY) +{ +} + +const static int cPixelSize = 4; +const static int cAlphaChannelOffset = 3; +const static unsigned char cOpaqueAlpha = static_cast<unsigned char>(0xff); + +ALWAYS_INLINE int FELighting::LightingData::upLeftPixelValue() +{ + return static_cast<int>(pixels->get(offset - widthMultipliedByPixelSize - cPixelSize + cAlphaChannelOffset)); +} + +ALWAYS_INLINE int FELighting::LightingData::upPixelValue() +{ + return static_cast<int>(pixels->get(offset - widthMultipliedByPixelSize + cAlphaChannelOffset)); +} + +ALWAYS_INLINE int FELighting::LightingData::upRightPixelValue() +{ + return static_cast<int>(pixels->get(offset - widthMultipliedByPixelSize + cPixelSize + cAlphaChannelOffset)); +} + +ALWAYS_INLINE int FELighting::LightingData::leftPixelValue() +{ + return static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); +} + +ALWAYS_INLINE int FELighting::LightingData::centerPixelValue() +{ + return static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); +} + +ALWAYS_INLINE int FELighting::LightingData::rightPixelValue() +{ + return static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); +} + +ALWAYS_INLINE int FELighting::LightingData::downLeftPixelValue() +{ + return static_cast<int>(pixels->get(offset + widthMultipliedByPixelSize - cPixelSize + cAlphaChannelOffset)); +} + +ALWAYS_INLINE int FELighting::LightingData::downPixelValue() +{ + return static_cast<int>(pixels->get(offset + widthMultipliedByPixelSize + cAlphaChannelOffset)); +} + +ALWAYS_INLINE int FELighting::LightingData::downRightPixelValue() +{ + return static_cast<int>(pixels->get(offset + widthMultipliedByPixelSize + cPixelSize + cAlphaChannelOffset)); +} + +ALWAYS_INLINE void FELighting::setPixel(LightingData& data, LightSource::PaintingData& paintingData, + int lightX, int lightY, float factorX, int normalX, float factorY, int normalY) +{ + m_lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->get(data.offset + 3)) * data.surfaceScale); + + data.normalVector.setX(factorX * static_cast<float>(normalX) * data.surfaceScale); + data.normalVector.setY(factorY * static_cast<float>(normalY) * data.surfaceScale); + data.normalVector.setZ(1.0f); + data.normalVector.normalize(); + + if (m_lightingType == FELighting::DiffuseLighting) + data.lightStrength = m_diffuseConstant * (data.normalVector * paintingData.lightVector); + else { + FloatPoint3D halfwayVector = paintingData.lightVector; + halfwayVector.setZ(halfwayVector.z() + 1.0f); + halfwayVector.normalize(); + if (m_specularExponent == 1.0f) + data.lightStrength = m_specularConstant * (data.normalVector * halfwayVector); + else + data.lightStrength = m_specularConstant * powf(data.normalVector * halfwayVector, m_specularExponent); + } + + if (data.lightStrength > 1.0f) + data.lightStrength = 1.0f; + if (data.lightStrength < 0.0f) + data.lightStrength = 0.0f; + + data.pixels->set(data.offset, static_cast<unsigned char>(data.lightStrength * paintingData.colorVector.x())); + data.pixels->set(data.offset + 1, static_cast<unsigned char>(data.lightStrength * paintingData.colorVector.y())); + data.pixels->set(data.offset + 2, static_cast<unsigned char>(data.lightStrength * paintingData.colorVector.z())); +} + +bool FELighting::drawLighting(CanvasPixelArray* pixels, int width, int height) +{ + LightSource::PaintingData paintingData; + LightingData data; + + if (!m_lightSource) + return false; + + // FIXME: do something if width or height (or both) is 1 pixel. + // The W3 spec does not define this case. Now the filter just returns. + if (width <= 2 || height <= 2) + return false; + + data.pixels = pixels; + data.surfaceScale = m_surfaceScale / 255.0f; + data.widthMultipliedByPixelSize = width * cPixelSize; + data.widthDecreasedByOne = width - 1; + data.heightDecreasedByOne = height - 1; + paintingData.colorVector = FloatPoint3D(m_lightingColor.red(), m_lightingColor.green(), m_lightingColor.blue()); + m_lightSource->initPaintingData(paintingData); + + // Top/Left corner + data.offset = 0; + setPixel(data, paintingData, 0, 0, + -2.0f / 3.0f, -2 * data.centerPixelValue() + 2 * data.rightPixelValue() - data.downPixelValue() + data.downRightPixelValue(), + -2.0f / 3.0f, -2 * data.centerPixelValue() - data.rightPixelValue() + 2 * data.downPixelValue() + data.downRightPixelValue()); + + // Top/Right pixel + data.offset = data.widthMultipliedByPixelSize - cPixelSize; + setPixel(data, paintingData, data.widthDecreasedByOne, 0, + -2.0f / 3.0f, -2 * data.leftPixelValue() + 2 * data.centerPixelValue() - data.downLeftPixelValue() + data.downPixelValue(), + -2.0f / 3.0f, -data.leftPixelValue() - 2 * data.centerPixelValue() + data.downLeftPixelValue() + 2 * data.downPixelValue()); + + // Bottom/Left pixel + data.offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize; + setPixel(data, paintingData, 0, data.heightDecreasedByOne, + -2.0f / 3.0f, -data.upPixelValue() + data.upRightPixelValue() - 2 * data.centerPixelValue() + 2 * data.rightPixelValue(), + -2.0f / 3.0f, -2 * data.upPixelValue() - data.upRightPixelValue() + 2 * data.centerPixelValue() + data.rightPixelValue()); + + // Bottom/Right pixel + data.offset = height * data.widthMultipliedByPixelSize - cPixelSize; + setPixel(data, paintingData, data.widthDecreasedByOne, data.heightDecreasedByOne, + -2.0f / 3.0f, -data.upLeftPixelValue() + data.upPixelValue() - 2 * data.leftPixelValue() + 2 * data.centerPixelValue(), + -2.0f / 3.0f, -data.upLeftPixelValue() - 2 * data.upPixelValue() + data.leftPixelValue() + 2 * data.centerPixelValue()); + + if (width >= 3) { + // Top line + data.offset = cPixelSize; + for (int x = 1; x < data.widthDecreasedByOne; ++x, data.offset += cPixelSize) { + setPixel(data, paintingData, x, 0, + -1.0f / 3.0f, -2 * data.leftPixelValue() + 2 * data.rightPixelValue() - data.downLeftPixelValue() + data.downRightPixelValue(), + -1.0f / 2.0f, -data.leftPixelValue() - 2 * data.centerPixelValue() - data.rightPixelValue() + data.downLeftPixelValue() + 2 * data.downPixelValue() + data.downRightPixelValue()); + } + // Bottom line + data.offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize + cPixelSize; + for (int x = 1; x < data.widthDecreasedByOne; ++x, data.offset += cPixelSize) { + setPixel(data, paintingData, x, data.heightDecreasedByOne, + -1.0f / 3.0f, -data.upLeftPixelValue() + data.upRightPixelValue() - 2 * data.leftPixelValue() + 2 * data.rightPixelValue(), + -1.0f / 2.0f, -data.upLeftPixelValue() - 2 * data.upPixelValue() - data.upRightPixelValue() + data.leftPixelValue() + 2 * data.centerPixelValue() + data.rightPixelValue()); + } + } + + if (height >= 3) { + // Left line + data.offset = data.widthMultipliedByPixelSize; + for (int y = 1; y < data.heightDecreasedByOne; ++y, data.offset += data.widthMultipliedByPixelSize) { + setPixel(data, paintingData, 0, y, + -1.0f / 2.0f, -data.upPixelValue() + data.upRightPixelValue() - 2 * data.centerPixelValue() + 2 * data.rightPixelValue() - data.downPixelValue() + data.downRightPixelValue(), + -1.0f / 3.0f, -2 * data.upPixelValue() - data.upRightPixelValue() + 2 * data.downPixelValue() + data.downRightPixelValue()); + } + // Right line + data.offset = data.widthMultipliedByPixelSize + data.widthMultipliedByPixelSize - cPixelSize; + for (int y = 1; y < data.heightDecreasedByOne; ++y, data.offset += data.widthMultipliedByPixelSize) { + setPixel(data, paintingData, data.widthDecreasedByOne, y, + -1.0f / 2.0f, -data.upLeftPixelValue() + data.upPixelValue() -2 * data.leftPixelValue() + 2 * data.centerPixelValue() - data.downLeftPixelValue() + data.downPixelValue(), + -1.0f / 3.0f, -data.upLeftPixelValue() - 2 * data.upPixelValue() + data.downLeftPixelValue() + 2 * data.downPixelValue()); + } + } + + if (width >= 3 && height >= 3) { + // Interior pixels + for (int y = 1; y < data.heightDecreasedByOne; ++y) { + data.offset = y * data.widthMultipliedByPixelSize + cPixelSize; + for (int x = 1; x < data.widthDecreasedByOne; ++x, data.offset += cPixelSize) { + setPixel(data, paintingData, x, y, + -1.0f / 4.0f, -data.upLeftPixelValue() + data.upRightPixelValue() - 2 * data.leftPixelValue() + 2 * data.rightPixelValue() - data.downLeftPixelValue() + data.downRightPixelValue(), + -1.0f / 4.0f, -data.upLeftPixelValue() - 2 * data.upPixelValue() - data.upRightPixelValue() + data.downLeftPixelValue() + 2 * data.downPixelValue() + data.downRightPixelValue()); + } + } + } + + int totalSize = data.widthMultipliedByPixelSize * height; + if (m_lightingType == DiffuseLighting) { + for (int i = 3; i < totalSize; i += 4) + data.pixels->set(i, cOpaqueAlpha); + } else { + for (int i = 0; i < totalSize; i += 4) { + unsigned char a1 = data.pixels->get(i); + unsigned char a2 = data.pixels->get(i + 1); + unsigned char a3 = data.pixels->get(i + 2); + // alpha set to set to max(a1, a2, a3) + data.pixels->set(i + 3, a1 >= a2 ? (a1 >= a3 ? a1 : a3) : (a2 >= a3 ? a2 : a3)); + } + } + + return true; +} + +void FELighting::apply(Filter* filter) +{ + m_in->apply(filter); + if (!m_in->resultImage()) + return; + + if (!getEffectContext()) + return; + + setIsAlphaImage(false); + + IntRect effectDrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion()); + + RefPtr<ImageData> srcImageData(m_in->resultImage()->getUnmultipliedImageData(effectDrawingRect)); + CanvasPixelArray* srcPixelArray(srcImageData->data()); + + // FIXME: support kernelUnitLengths other than (1,1). The issue here is that the W3 + // standard has no test case for them, and other browsers (like Firefox) has strange + // output for various kernelUnitLengths, and I am not sure they are reliable. + // Anyway, feConvolveMatrix should also use the implementation + + if (drawLighting(srcPixelArray, effectDrawingRect.width(), effectDrawingRect.height())) + resultImage()->putUnmultipliedImageData(srcImageData.get(), IntRect(IntPoint(), effectDrawingRect.size()), effectDrawingRect.location()); +} + +} // namespace WebCore + +#endif // ENABLE(SVG) && ENABLE(FILTERS) diff --git a/WebCore/svg/graphics/filters/SVGFELighting.h b/WebCore/svg/graphics/filters/SVGFELighting.h new file mode 100644 index 0000000..731871f --- /dev/null +++ b/WebCore/svg/graphics/filters/SVGFELighting.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2010 University of Szeged + * Copyright (C) 2010 Zoltan Herczeg + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SVGFELighting_h +#define SVGFELighting_h + +#if ENABLE(SVG) && ENABLE(FILTERS) +#include "Color.h" +#include "Filter.h" +#include "FilterEffect.h" +#include "SVGLightSource.h" +#include <wtf/AlwaysInline.h> + +// Common base class for FEDiffuseLighting and FESpecularLighting + +namespace WebCore { + +class CanvasPixelArray; + +class FELighting : public FilterEffect { +public: + virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return calculateUnionOfChildEffectSubregions(filter, m_in.get()); } + void apply(Filter*); + +protected: + enum LightingType { + DiffuseLighting, + SpecularLighting + }; + + struct LightingData { + FloatPoint3D normalVector; + CanvasPixelArray* pixels; + float lightStrength; + float surfaceScale; + int offset; + int widthMultipliedByPixelSize; + int widthDecreasedByOne; + int heightDecreasedByOne; + + ALWAYS_INLINE int upLeftPixelValue(); + ALWAYS_INLINE int upPixelValue(); + ALWAYS_INLINE int upRightPixelValue(); + ALWAYS_INLINE int leftPixelValue(); + ALWAYS_INLINE int centerPixelValue(); + ALWAYS_INLINE int rightPixelValue(); + ALWAYS_INLINE int downLeftPixelValue(); + ALWAYS_INLINE int downPixelValue(); + ALWAYS_INLINE int downRightPixelValue(); + }; + + FELighting(LightingType, FilterEffect*, const Color&, float, float, float, + float, float, float, PassRefPtr<LightSource>); + + bool drawLighting(CanvasPixelArray*, int, int); + ALWAYS_INLINE void setPixel(LightingData&, LightSource::PaintingData&, + int lightX, int lightY, float factorX, int normalX, float factorY, int normalY); + + LightingType m_lightingType; + RefPtr<FilterEffect> m_in; + RefPtr<LightSource> m_lightSource; + + Color m_lightingColor; + float m_surfaceScale; + float m_diffuseConstant; + float m_specularConstant; + float m_specularExponent; + float m_kernelUnitLengthX; + float m_kernelUnitLengthY; +}; + +} // namespace WebCore + +#endif // ENABLE(SVG) && ENABLE(FILTERS) + +#endif // SVGFELighting_h diff --git a/WebCore/svg/graphics/filters/SVGFEMerge.cpp b/WebCore/svg/graphics/filters/SVGFEMerge.cpp index 6ea0fb9..c6f312f 100644 --- a/WebCore/svg/graphics/filters/SVGFEMerge.cpp +++ b/WebCore/svg/graphics/filters/SVGFEMerge.cpp @@ -87,20 +87,17 @@ void FEMerge::dump() { } -TextStream& FEMerge::externalRepresentation(TextStream& ts) const +TextStream& FEMerge::externalRepresentation(TextStream& ts, int indent) const { - ts << "[type=MERGE] "; + writeIndent(ts, indent); + ts << "[feMerge"; FilterEffect::externalRepresentation(ts); - ts << "[merge inputs=["; - unsigned x = 0; - unsigned size = m_mergeInputs.size(); - while (x < size) { - ts << m_mergeInputs[x]; - x++; - if (x < m_mergeInputs.size()) - ts << ", "; + ts << " mergeNodes=\"" << m_mergeInputs.size() << "\"]\n"; + if (!m_mergeInputs.isEmpty()) { + const Vector<RefPtr<FilterEffect> >::const_iterator end = m_mergeInputs.end(); + for (Vector<RefPtr<FilterEffect> >::const_iterator it = m_mergeInputs.begin(); it != end; ++it) + (*it)->externalRepresentation(ts, indent + 1); } - ts << "]]"; return ts; } diff --git a/WebCore/svg/graphics/filters/SVGFEMerge.h b/WebCore/svg/graphics/filters/SVGFEMerge.h index 7653be3..77b311f 100644 --- a/WebCore/svg/graphics/filters/SVGFEMerge.h +++ b/WebCore/svg/graphics/filters/SVGFEMerge.h @@ -39,7 +39,7 @@ namespace WebCore { virtual FloatRect uniteChildEffectSubregions(Filter*); void apply(Filter*); void dump(); - TextStream& externalRepresentation(TextStream& ts) const; + TextStream& externalRepresentation(TextStream&, int indent) const; private: FEMerge(const Vector<RefPtr<FilterEffect> >&); diff --git a/WebCore/svg/graphics/filters/SVGFEMorphology.cpp b/WebCore/svg/graphics/filters/SVGFEMorphology.cpp index 5204a46..1c5ea27 100644 --- a/WebCore/svg/graphics/filters/SVGFEMorphology.cpp +++ b/WebCore/svg/graphics/filters/SVGFEMorphology.cpp @@ -157,26 +157,30 @@ void FEMorphology::dump() { } -static TextStream& operator<<(TextStream& ts, MorphologyOperatorType t) +static TextStream& operator<<(TextStream& ts, const MorphologyOperatorType& type) { - switch (t) - { - case FEMORPHOLOGY_OPERATOR_UNKNOWN: - ts << "UNKNOWN"; break; - case FEMORPHOLOGY_OPERATOR_ERODE: - ts << "ERODE"; break; - case FEMORPHOLOGY_OPERATOR_DILATE: - ts << "DILATE"; break; + switch (type) { + case FEMORPHOLOGY_OPERATOR_UNKNOWN: + ts << "UNKNOWN"; + break; + case FEMORPHOLOGY_OPERATOR_ERODE: + ts << "ERODE"; + break; + case FEMORPHOLOGY_OPERATOR_DILATE: + ts << "DILATE"; + break; } return ts; } -TextStream& FEMorphology::externalRepresentation(TextStream& ts) const +TextStream& FEMorphology::externalRepresentation(TextStream& ts, int indent) const { - ts << "[type=MORPHOLOGY] "; + writeIndent(ts, indent); + ts << "[feMorphology"; FilterEffect::externalRepresentation(ts); - ts << " [operator type=" << morphologyOperator() << "]" - << " [radius x=" << radiusX() << " y=" << radiusY() << "]"; + ts << " operator=\"" << morphologyOperator() << "\" " + << "radius=\"" << radiusX() << ", " << radiusY() << "\"]\n"; + m_in->externalRepresentation(ts, indent + 1); return ts; } diff --git a/WebCore/svg/graphics/filters/SVGFEMorphology.h b/WebCore/svg/graphics/filters/SVGFEMorphology.h index 6a321c8..c0b2f95 100644 --- a/WebCore/svg/graphics/filters/SVGFEMorphology.h +++ b/WebCore/svg/graphics/filters/SVGFEMorphology.h @@ -49,7 +49,7 @@ namespace WebCore { virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return calculateUnionOfChildEffectSubregions(filter, m_in.get()); } void apply(Filter*); void dump(); - TextStream& externalRepresentation(TextStream& ts) const; + TextStream& externalRepresentation(TextStream&, int indent) const; private: FEMorphology(FilterEffect*, MorphologyOperatorType, float radiusX, float radiusY); diff --git a/WebCore/svg/graphics/filters/SVGFEOffset.cpp b/WebCore/svg/graphics/filters/SVGFEOffset.cpp index 0066c3e..5386f1c 100644 --- a/WebCore/svg/graphics/filters/SVGFEOffset.cpp +++ b/WebCore/svg/graphics/filters/SVGFEOffset.cpp @@ -98,11 +98,13 @@ void FEOffset::dump() { } -TextStream& FEOffset::externalRepresentation(TextStream& ts) const +TextStream& FEOffset::externalRepresentation(TextStream& ts, int indent) const { - ts << "[type=OFFSET] "; + writeIndent(ts, indent); + ts << "[feOffset"; FilterEffect::externalRepresentation(ts); - ts << " [dx=" << dx() << " dy=" << dy() << "]"; + ts << " dx=\"" << dx() << "\" dy=\"" << dy() << "\"]\n"; + m_in->externalRepresentation(ts, indent + 1); return ts; } diff --git a/WebCore/svg/graphics/filters/SVGFEOffset.h b/WebCore/svg/graphics/filters/SVGFEOffset.h index 8435db1..a6ded47 100644 --- a/WebCore/svg/graphics/filters/SVGFEOffset.h +++ b/WebCore/svg/graphics/filters/SVGFEOffset.h @@ -41,7 +41,7 @@ namespace WebCore { virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return calculateUnionOfChildEffectSubregions(filter, m_in.get()); } void apply(Filter*); void dump(); - TextStream& externalRepresentation(TextStream& ts) const; + TextStream& externalRepresentation(TextStream&, int indent) const; private: FEOffset(FilterEffect*, const float&, const float&); diff --git a/WebCore/svg/graphics/filters/SVGFESpecularLighting.cpp b/WebCore/svg/graphics/filters/SVGFESpecularLighting.cpp index 0b43aba..fbf9d44 100644 --- a/WebCore/svg/graphics/filters/SVGFESpecularLighting.cpp +++ b/WebCore/svg/graphics/filters/SVGFESpecularLighting.cpp @@ -23,29 +23,22 @@ #if ENABLE(SVG) && ENABLE(FILTERS) #include "SVGFESpecularLighting.h" + +#include "SVGLightSource.h" #include "SVGRenderTreeAsText.h" -#include "Filter.h" namespace WebCore { -FESpecularLighting::FESpecularLighting(FilterEffect* in, const Color& lightingColor, const float& surfaceScale, - const float& specularConstant, const float& specularExponent, const float& kernelUnitLengthX, - const float& kernelUnitLengthY, PassRefPtr<LightSource> lightSource) - : FilterEffect() - , m_in(in) - , m_lightingColor(lightingColor) - , m_surfaceScale(surfaceScale) - , m_specularConstant(specularConstant) - , m_specularExponent(specularExponent) - , m_kernelUnitLengthX(kernelUnitLengthX) - , m_kernelUnitLengthY(kernelUnitLengthY) - , m_lightSource(lightSource) +FESpecularLighting::FESpecularLighting(FilterEffect* in, const Color& lightingColor, float surfaceScale, + float specularConstant, float specularExponent, float kernelUnitLengthX, + float kernelUnitLengthY, PassRefPtr<LightSource> lightSource) + : FELighting(SpecularLighting, in, lightingColor, surfaceScale, 0.0f, specularConstant, specularExponent, kernelUnitLengthX, kernelUnitLengthY, lightSource) { } PassRefPtr<FESpecularLighting> FESpecularLighting::create(FilterEffect* in, const Color& lightingColor, - const float& surfaceScale, const float& specularConstant, const float& specularExponent, - const float& kernelUnitLengthX, const float& kernelUnitLengthY, PassRefPtr<LightSource> lightSource) + float surfaceScale, float specularConstant, float specularExponent, + float kernelUnitLengthX, float kernelUnitLengthY, PassRefPtr<LightSource> lightSource) { return adoptRef(new FESpecularLighting(in, lightingColor, surfaceScale, specularConstant, specularExponent, kernelUnitLengthX, kernelUnitLengthY, lightSource)); @@ -125,21 +118,19 @@ void FESpecularLighting::setLightSource(PassRefPtr<LightSource> lightSource) m_lightSource = lightSource; } -void FESpecularLighting::apply(Filter*) -{ -} - void FESpecularLighting::dump() { } -TextStream& FESpecularLighting::externalRepresentation(TextStream& ts) const +TextStream& FESpecularLighting::externalRepresentation(TextStream& ts, int indent) const { - ts << "[type=SPECULAR-LIGHTING] "; + writeIndent(ts, indent); + ts << "[feSpecularLighting"; FilterEffect::externalRepresentation(ts); - ts << " [surface scale=" << m_surfaceScale << "]" - << " [specual constant=" << m_specularConstant << "]" - << " [specular exponent=" << m_specularExponent << "]"; + ts << " surfaceScale=\"" << m_surfaceScale << "\" " + << "specualConstant=\"" << m_specularConstant << "\" " + << "specularExponent=\"" << m_specularExponent << "\"]\n"; + m_in->externalRepresentation(ts, indent + 1); return ts; } diff --git a/WebCore/svg/graphics/filters/SVGFESpecularLighting.h b/WebCore/svg/graphics/filters/SVGFESpecularLighting.h index f4947fd..366056e 100644 --- a/WebCore/svg/graphics/filters/SVGFESpecularLighting.h +++ b/WebCore/svg/graphics/filters/SVGFESpecularLighting.h @@ -23,58 +23,44 @@ #define SVGFESpecularLighting_h #if ENABLE(SVG) && ENABLE(FILTERS) -#include "Color.h" -#include "FilterEffect.h" -#include "SVGLightSource.h" -#include "Filter.h" +#include "SVGFELighting.h" namespace WebCore { - class FESpecularLighting : public FilterEffect { - public: - static PassRefPtr<FESpecularLighting> create(FilterEffect*, const Color&, const float&, const float&, - const float&, const float&, const float&, PassRefPtr<LightSource>); - virtual ~FESpecularLighting(); +class FESpecularLighting : public FELighting { +public: + static PassRefPtr<FESpecularLighting> create(FilterEffect*, const Color&, float, float, + float, float, float, PassRefPtr<LightSource>); + virtual ~FESpecularLighting(); - Color lightingColor() const; - void setLightingColor(const Color&); + Color lightingColor() const; + void setLightingColor(const Color&); - float surfaceScale() const; - void setSurfaceScale(float); + float surfaceScale() const; + void setSurfaceScale(float); - float specularConstant() const; - void setSpecularConstant(float); + float specularConstant() const; + void setSpecularConstant(float); - float specularExponent() const; - void setSpecularExponent(float); + float specularExponent() const; + void setSpecularExponent(float); - float kernelUnitLengthX() const; - void setKernelUnitLengthX(float); + float kernelUnitLengthX() const; + void setKernelUnitLengthX(float); - float kernelUnitLengthY() const; - void setKernelUnitLengthY(float); + float kernelUnitLengthY() const; + void setKernelUnitLengthY(float); - const LightSource* lightSource() const; - void setLightSource(PassRefPtr<LightSource>); + const LightSource* lightSource() const; + void setLightSource(PassRefPtr<LightSource>); - virtual FloatRect uniteEffectRect(Filter* filter) { return calculateUnionOfChildEffectSubregions(filter, m_in.get()); } - void apply(Filter*); - void dump(); - TextStream& externalRepresentation(TextStream& ts) const; + void dump(); + TextStream& externalRepresentation(TextStream&, int indent) const; - private: - FESpecularLighting(FilterEffect*, const Color&, const float&, const float&, const float&, - const float&, const float&, PassRefPtr<LightSource>); - - RefPtr<FilterEffect> m_in; - Color m_lightingColor; - float m_surfaceScale; - float m_specularConstant; - float m_specularExponent; - float m_kernelUnitLengthX; - float m_kernelUnitLengthY; - RefPtr<LightSource> m_lightSource; - }; +private: + FESpecularLighting(FilterEffect*, const Color&, float, float, float, + float, float, PassRefPtr<LightSource>); +}; } // namespace WebCore diff --git a/WebCore/svg/graphics/filters/SVGFETile.cpp b/WebCore/svg/graphics/filters/SVGFETile.cpp index 5bc2129..1b0a59b 100644 --- a/WebCore/svg/graphics/filters/SVGFETile.cpp +++ b/WebCore/svg/graphics/filters/SVGFETile.cpp @@ -87,10 +87,14 @@ void FETile::dump() { } -TextStream& FETile::externalRepresentation(TextStream& ts) const +TextStream& FETile::externalRepresentation(TextStream& ts, int indent) const { - ts << "[type=TILE]"; + writeIndent(ts, indent); + ts << "[feTile"; FilterEffect::externalRepresentation(ts); + ts << "]\n"; + m_in->externalRepresentation(ts, indent + 1); + return ts; } diff --git a/WebCore/svg/graphics/filters/SVGFETile.h b/WebCore/svg/graphics/filters/SVGFETile.h index c845085..e11e4ab 100644 --- a/WebCore/svg/graphics/filters/SVGFETile.h +++ b/WebCore/svg/graphics/filters/SVGFETile.h @@ -35,7 +35,7 @@ namespace WebCore { virtual FloatRect uniteChildEffectSubregions(Filter*); void apply(Filter*); void dump(); - TextStream& externalRepresentation(TextStream& ts) const; + TextStream& externalRepresentation(TextStream&, int indent) const; private: FETile(FilterEffect*); diff --git a/WebCore/svg/graphics/filters/SVGFETurbulence.cpp b/WebCore/svg/graphics/filters/SVGFETurbulence.cpp index 542c576..db4b0bb 100644 --- a/WebCore/svg/graphics/filters/SVGFETurbulence.cpp +++ b/WebCore/svg/graphics/filters/SVGFETurbulence.cpp @@ -114,30 +114,32 @@ void FETurbulence::dump() { } -static TextStream& operator<<(TextStream& ts, TurbulanceType t) -{ - switch (t) - { - case FETURBULENCE_TYPE_UNKNOWN: - ts << "UNKNOWN"; break; - case FETURBULENCE_TYPE_TURBULENCE: - ts << "TURBULANCE"; break; - case FETURBULENCE_TYPE_FRACTALNOISE: - ts << "NOISE"; break; +static TextStream& operator<<(TextStream& ts, const TurbulanceType& type) +{ + switch (type) { + case FETURBULENCE_TYPE_UNKNOWN: + ts << "UNKNOWN"; + break; + case FETURBULENCE_TYPE_TURBULENCE: + ts << "TURBULANCE"; + break; + case FETURBULENCE_TYPE_FRACTALNOISE: + ts << "NOISE"; + break; } return ts; } -TextStream& FETurbulence::externalRepresentation(TextStream& ts) const +TextStream& FETurbulence::externalRepresentation(TextStream& ts, int indent) const { - ts << "[type=TURBULENCE] "; + writeIndent(ts, indent); + ts << "[feTurbulence"; FilterEffect::externalRepresentation(ts); - ts << " [turbulence type=" << type() << "]" - << " [base frequency x=" << baseFrequencyX() << " y=" << baseFrequencyY() << "]" - << " [seed=" << seed() << "]" - << " [num octaves=" << numOctaves() << "]" - << " [stitch tiles=" << stitchTiles() << "]"; - + ts << " type=\"" << type() << "\" " + << "baseFrequency=\"" << baseFrequencyX() << ", " << baseFrequencyY() << "\" " + << "seed=\"" << seed() << "\" " + << "numOctaves=\"" << numOctaves() << "\" " + << "stitchTiles=\"" << stitchTiles() << "\"]\n"; return ts; } diff --git a/WebCore/svg/graphics/filters/SVGFETurbulence.h b/WebCore/svg/graphics/filters/SVGFETurbulence.h index e7f40f6..bed0637 100644 --- a/WebCore/svg/graphics/filters/SVGFETurbulence.h +++ b/WebCore/svg/graphics/filters/SVGFETurbulence.h @@ -59,7 +59,7 @@ namespace WebCore { void apply(Filter*); void dump(); - TextStream& externalRepresentation(TextStream& ts) const; + TextStream& externalRepresentation(TextStream&, int indent) const; private: FETurbulence(TurbulanceType, const float&, const float&, const int&, const float&, diff --git a/WebCore/svg/graphics/filters/SVGLightSource.cpp b/WebCore/svg/graphics/filters/SVGLightSource.cpp index 9176b4c..2a04af6 100644 --- a/WebCore/svg/graphics/filters/SVGLightSource.cpp +++ b/WebCore/svg/graphics/filters/SVGLightSource.cpp @@ -2,6 +2,7 @@ Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> 2004, 2005 Rob Buis <buis@kde.org> 2005 Eric Seidel <eric@webkit.org> + 2010 Zoltan Herczeg <zherczeg@webkit.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -22,13 +23,115 @@ #include "config.h" #if ENABLE(SVG) && ENABLE(FILTERS) +#include "SVGLightSource.h" + +#include "SVGDistantLightSource.h" #include "SVGPointLightSource.h" #include "SVGRenderTreeAsText.h" #include "SVGSpotLightSource.h" -#include "SVGDistantLightSource.h" +#include <wtf/MathExtras.h> namespace WebCore { +void PointLightSource::initPaintingData(PaintingData&) +{ +} + +void PointLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z) +{ + paintingData.lightVector.setX(m_position.x() - x); + paintingData.lightVector.setY(m_position.y() - y); + paintingData.lightVector.setZ(m_position.z() - z); + paintingData.lightVector.normalize(); +} + +void SpotLightSource::initPaintingData(PaintingData& paintingData) +{ + paintingData.privateColorVector = paintingData.colorVector; + paintingData.directionVector.setX(m_direction.x() - m_position.x()); + paintingData.directionVector.setY(m_direction.y() - m_position.y()); + paintingData.directionVector.setZ(m_direction.z() - m_position.z()); + paintingData.directionVector.normalize(); + + if (!m_limitingConeAngle) { + paintingData.coneCutOffLimit = 0.0f; + paintingData.coneFullLight = cosf(deg2rad(92.0f)); + } else { + float limitingConeAngle = m_limitingConeAngle; + if (limitingConeAngle < 0.0f) + limitingConeAngle = 0.0f; + else if (limitingConeAngle > 90.0f) + limitingConeAngle = 90.0f; + paintingData.coneCutOffLimit = cosf(deg2rad(180.0f - limitingConeAngle)); + limitingConeAngle -= 2.0f; + if (limitingConeAngle < 0.0f) + limitingConeAngle = 0.0f; + paintingData.coneFullLight = cosf(deg2rad(180.0f - limitingConeAngle)); + } + + // Optimization for common specularExponent values + if (!m_specularExponent) + paintingData.specularExponent = 0; + else if (m_specularExponent == 1.0f) + paintingData.specularExponent = 1; + else // It is neither 0.0f nor 1.0f + paintingData.specularExponent = 2; +} + +void SpotLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z) +{ + paintingData.lightVector.setX(m_position.x() - x); + paintingData.lightVector.setY(m_position.y() - y); + paintingData.lightVector.setZ(m_position.z() - z); + paintingData.lightVector.normalize(); + + float cosineOfAngle = paintingData.lightVector * paintingData.directionVector; + if (cosineOfAngle > paintingData.coneCutOffLimit) { + // No light is produced, scanlines are not updated + paintingData.colorVector.setX(0.0f); + paintingData.colorVector.setY(0.0f); + paintingData.colorVector.setZ(0.0f); + return; + } + + // Set the color of the pixel + float lightStrength; + switch (paintingData.specularExponent) { + case 0: + lightStrength = 1.0f; // -cosineOfAngle ^ 0 == 1 + break; + case 1: + lightStrength = -cosineOfAngle; // -cosineOfAngle ^ 1 == -cosineOfAngle + break; + default: + lightStrength = powf(-cosineOfAngle, m_specularExponent); + break; + } + + if (cosineOfAngle > paintingData.coneFullLight) + lightStrength *= (paintingData.coneCutOffLimit - cosineOfAngle) / (paintingData.coneCutOffLimit - paintingData.coneFullLight); + + if (lightStrength > 1.0f) + lightStrength = 1.0f; + + paintingData.colorVector.setX(paintingData.privateColorVector.x() * lightStrength); + paintingData.colorVector.setY(paintingData.privateColorVector.y() * lightStrength); + paintingData.colorVector.setZ(paintingData.privateColorVector.z() * lightStrength); +} + +void DistantLightSource::initPaintingData(PaintingData& paintingData) +{ + float azimuth = deg2rad(m_azimuth); + float elevation = deg2rad(m_elevation); + paintingData.lightVector.setX(cosf(azimuth) * cosf(elevation)); + paintingData.lightVector.setY(sinf(azimuth) * cosf(elevation)); + paintingData.lightVector.setZ(sinf(elevation)); +} + +void DistantLightSource::updatePaintingData(PaintingData&, int, int, float) +{ +} + static TextStream& operator<<(TextStream& ts, const FloatPoint3D& p) { ts << "x=" << p.x() << " y=" << p.y() << " z=" << p.z(); diff --git a/WebCore/svg/graphics/filters/SVGLightSource.h b/WebCore/svg/graphics/filters/SVGLightSource.h index 6f0075c..d97366c 100644 --- a/WebCore/svg/graphics/filters/SVGLightSource.h +++ b/WebCore/svg/graphics/filters/SVGLightSource.h @@ -3,6 +3,7 @@ 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> 2004, 2005 Rob Buis <buis@kde.org> 2005 Eric Seidel <eric@webkit.org> + 2010 Zoltan Herczeg <zherczeg@webkit.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -24,33 +25,57 @@ #define SVGLightSource_h #if ENABLE(SVG) && ENABLE(FILTERS) +#include "FloatPoint3D.h" #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> namespace WebCore { - enum LightType { - LS_DISTANT, - LS_POINT, - LS_SPOT +enum LightType { + LS_DISTANT, + LS_POINT, + LS_SPOT +}; + +class TextStream; + +class LightSource : public RefCounted<LightSource> { +public: + + // Light vectors must be calculated for every pixel during + // painting. It is expensive to pass all these arguments to + // a frequently called function, especially because not all + // light sources require all of them. Instead, we just pass + // a reference to the following structure + struct PaintingData { + // SVGFELighting also use them + FloatPoint3D lightVector; + FloatPoint3D colorVector; + // Private members + FloatPoint3D directionVector; + FloatPoint3D privateColorVector; + float coneCutOffLimit; + float coneFullLight; + int specularExponent; }; - class TextStream; + LightSource(LightType type) + : m_type(type) + { } - class LightSource : public RefCounted<LightSource> { - public: - LightSource(LightType type) - : m_type(type) - { } + virtual ~LightSource() { } - virtual ~LightSource() { } + LightType type() const { return m_type; } + virtual TextStream& externalRepresentation(TextStream&) const = 0; - LightType type() const { return m_type; } - virtual TextStream& externalRepresentation(TextStream&) const = 0; + virtual void initPaintingData(PaintingData&) = 0; + // z is a float number, since it is the alpha value scaled by a user + // specified "surfaceScale" constant, which type is <number> in the SVG standard + virtual void updatePaintingData(PaintingData&, int x, int y, float z) = 0; - private: - LightType m_type; - }; +private: + LightType m_type; +}; } // namespace WebCore diff --git a/WebCore/svg/graphics/filters/SVGPointLightSource.h b/WebCore/svg/graphics/filters/SVGPointLightSource.h index 1e966cc..0c55ebf 100644 --- a/WebCore/svg/graphics/filters/SVGPointLightSource.h +++ b/WebCore/svg/graphics/filters/SVGPointLightSource.h @@ -24,31 +24,33 @@ #define SVGPointLightSource_h #if ENABLE(SVG) && ENABLE(FILTERS) -#include "FloatPoint3D.h" #include "SVGLightSource.h" namespace WebCore { - class PointLightSource : public LightSource { - public: - static PassRefPtr<PointLightSource> create(const FloatPoint3D& position) - { - return adoptRef(new PointLightSource(position)); - } +class PointLightSource : public LightSource { +public: + static PassRefPtr<PointLightSource> create(const FloatPoint3D& position) + { + return adoptRef(new PointLightSource(position)); + } - const FloatPoint3D& position() const { return m_position; } + const FloatPoint3D& position() const { return m_position; } - virtual TextStream& externalRepresentation(TextStream&) const; + virtual void initPaintingData(PaintingData&); + virtual void updatePaintingData(PaintingData&, int x, int y, float z); - private: - PointLightSource(const FloatPoint3D& position) - : LightSource(LS_POINT) - , m_position(position) - { - } + virtual TextStream& externalRepresentation(TextStream&) const; - FloatPoint3D m_position; - }; +private: + PointLightSource(const FloatPoint3D& position) + : LightSource(LS_POINT) + , m_position(position) + { + } + + FloatPoint3D m_position; +}; } // namespace WebCore diff --git a/WebCore/svg/graphics/filters/SVGSpotLightSource.h b/WebCore/svg/graphics/filters/SVGSpotLightSource.h index 05280d2..2542947 100644 --- a/WebCore/svg/graphics/filters/SVGSpotLightSource.h +++ b/WebCore/svg/graphics/filters/SVGSpotLightSource.h @@ -24,44 +24,46 @@ #define SVGSpotLightSource_h #if ENABLE(SVG) && ENABLE(FILTERS) -#include "FloatPoint3D.h" #include "SVGLightSource.h" namespace WebCore { - class SpotLightSource : public LightSource { - public: - static PassRefPtr<SpotLightSource> create(const FloatPoint3D& position, const FloatPoint3D& direction, - float specularExponent, float limitingConeAngle) - { - return adoptRef(new SpotLightSource(position, direction, specularExponent, limitingConeAngle)); - } - - const FloatPoint3D& position() const { return m_position; } - const FloatPoint3D& direction() const { return m_direction; } - - float specularExponent() const { return m_specularExponent; } - float limitingConeAngle() const { return m_limitingConeAngle; } - - virtual TextStream& externalRepresentation(TextStream&) const; - - private: - SpotLightSource(const FloatPoint3D& position, const FloatPoint3D& direction, - float specularExponent, float limitingConeAngle) - : LightSource(LS_SPOT) - , m_position(position) - , m_direction(direction) - , m_specularExponent(specularExponent) - , m_limitingConeAngle(limitingConeAngle) - { - } - - FloatPoint3D m_position; - FloatPoint3D m_direction; - - float m_specularExponent; - float m_limitingConeAngle; - }; +class SpotLightSource : public LightSource { +public: + static PassRefPtr<SpotLightSource> create(const FloatPoint3D& position, + const FloatPoint3D& direction, float specularExponent, float limitingConeAngle) + { + return adoptRef(new SpotLightSource(position, direction, specularExponent, limitingConeAngle)); + } + + const FloatPoint3D& position() const { return m_position; } + const FloatPoint3D& direction() const { return m_direction; } + + float specularExponent() const { return m_specularExponent; } + float limitingConeAngle() const { return m_limitingConeAngle; } + + virtual void initPaintingData(PaintingData&); + virtual void updatePaintingData(PaintingData&, int x, int y, float z); + + virtual TextStream& externalRepresentation(TextStream&) const; + +private: + SpotLightSource(const FloatPoint3D& position, const FloatPoint3D& direction, + float specularExponent, float limitingConeAngle) + : LightSource(LS_SPOT) + , m_position(position) + , m_direction(direction) + , m_specularExponent(specularExponent) + , m_limitingConeAngle(limitingConeAngle) + { + } + + FloatPoint3D m_position; + FloatPoint3D m_direction; + + float m_specularExponent; + float m_limitingConeAngle; +}; } // namespace WebCore |