diff options
author | Steve Block <steveblock@google.com> | 2011-05-06 11:45:16 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-05-12 13:44:10 +0100 |
commit | cad810f21b803229eb11403f9209855525a25d57 (patch) | |
tree | 29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/platform/graphics/filters | |
parent | 121b0cf4517156d0ac5111caf9830c51b69bae8f (diff) | |
download | external_webkit-cad810f21b803229eb11403f9209855525a25d57.zip external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2 |
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/platform/graphics/filters')
44 files changed, 5833 insertions, 0 deletions
diff --git a/Source/WebCore/platform/graphics/filters/DistantLightSource.h b/Source/WebCore/platform/graphics/filters/DistantLightSource.h new file mode 100644 index 0000000..d5d474f --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/DistantLightSource.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef DistantLightSource_h +#define DistantLightSource_h + +#if ENABLE(FILTERS) +#include "LightSource.h" + +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 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 + +#endif // ENABLE(FILTERS) + +#endif // DistantLightSource_h diff --git a/Source/WebCore/platform/graphics/filters/FEBlend.cpp b/Source/WebCore/platform/graphics/filters/FEBlend.cpp new file mode 100644 index 0000000..7eeb128 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEBlend.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEBlend.h" + +#include "Filter.h" +#include "FloatPoint.h" +#include "GraphicsContext.h" + +#include <wtf/ByteArray.h> + +typedef unsigned char (*BlendType)(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB); + +namespace WebCore { + +FEBlend::FEBlend(Filter* filter, BlendModeType mode) + : FilterEffect(filter) + , m_mode(mode) +{ +} + +PassRefPtr<FEBlend> FEBlend::create(Filter* filter, BlendModeType mode) +{ + return adoptRef(new FEBlend(filter, mode)); +} + +BlendModeType FEBlend::blendMode() const +{ + return m_mode; +} + +void FEBlend::setBlendMode(BlendModeType mode) +{ + m_mode = mode; +} + +static unsigned char unknown(unsigned char, unsigned char, unsigned char, unsigned char) +{ + return 0; +} + +static unsigned char normal(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char) +{ + return (((255 - alphaA) * colorB + colorA * 255) / 255); +} + +static unsigned char multiply(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB) +{ + return (((255 - alphaA) * colorB + (255 - alphaB + colorB) * colorA) / 255); +} + +static unsigned char screen(unsigned char colorA, unsigned char colorB, unsigned char, unsigned char) +{ + return (((colorB + colorA) * 255 - colorA * colorB) / 255); +} + +static unsigned char darken(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB) +{ + return ((std::min((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255)) / 255); +} + +static unsigned char lighten(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB) +{ + return ((std::max((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255)) / 255); +} + +void FEBlend::apply() +{ + if (hasResult()) + return; + FilterEffect* in = inputEffect(0); + FilterEffect* in2 = inputEffect(1); + in->apply(); + in2->apply(); + if (!in->hasResult() || !in2->hasResult()) + return; + + if (m_mode <= FEBLEND_MODE_UNKNOWN || m_mode > FEBLEND_MODE_LIGHTEN) + return; + + ByteArray* dstPixelArray = createPremultipliedImageResult(); + if (!dstPixelArray) + return; + + IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); + RefPtr<ByteArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect); + + IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect()); + RefPtr<ByteArray> srcPixelArrayB = in2->asPremultipliedImage(effectBDrawingRect); + + // Keep synchronized with BlendModeType + static const BlendType callEffect[] = {unknown, normal, multiply, screen, darken, lighten}; + + unsigned pixelArrayLength = srcPixelArrayA->length(); + ASSERT(pixelArrayLength == srcPixelArrayB->length()); + for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) { + unsigned char alphaA = srcPixelArrayA->get(pixelOffset + 3); + unsigned char alphaB = srcPixelArrayB->get(pixelOffset + 3); + for (unsigned channel = 0; channel < 3; ++channel) { + unsigned char colorA = srcPixelArrayA->get(pixelOffset + channel); + unsigned char colorB = srcPixelArrayB->get(pixelOffset + channel); + + unsigned char result = (*callEffect[m_mode])(colorA, colorB, alphaA, alphaB); + dstPixelArray->set(pixelOffset + channel, result); + } + unsigned char alphaR = 255 - ((255 - alphaA) * (255 - alphaB)) / 255; + dstPixelArray->set(pixelOffset + 3, alphaR); + } +} + +void FEBlend::dump() +{ +} + +static TextStream& operator<<(TextStream& ts, const BlendModeType& type) +{ + switch (type) { + case FEBLEND_MODE_UNKNOWN: + ts << "UNKNOWN"; + break; + case FEBLEND_MODE_NORMAL: + ts << "NORMAL"; + break; + case FEBLEND_MODE_MULTIPLY: + ts << "MULTIPLY"; + break; + case FEBLEND_MODE_SCREEN: + ts << "SCREEN"; + break; + case FEBLEND_MODE_DARKEN: + ts << "DARKEN"; + break; + case FEBLEND_MODE_LIGHTEN: + ts << "LIGHTEN"; + break; + } + return ts; +} + +TextStream& FEBlend::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feBlend"; + FilterEffect::externalRepresentation(ts); + ts << " mode=\"" << m_mode << "\"]\n"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + inputEffect(1)->externalRepresentation(ts, indent + 1); + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/FEBlend.h b/Source/WebCore/platform/graphics/filters/FEBlend.h new file mode 100644 index 0000000..4c59578 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEBlend.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FEBlend_h +#define FEBlend_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" + +#include "Filter.h" + +namespace WebCore { + +enum BlendModeType { + FEBLEND_MODE_UNKNOWN = 0, + FEBLEND_MODE_NORMAL = 1, + FEBLEND_MODE_MULTIPLY = 2, + FEBLEND_MODE_SCREEN = 3, + FEBLEND_MODE_DARKEN = 4, + FEBLEND_MODE_LIGHTEN = 5 +}; + +class FEBlend : public FilterEffect { +public: + static PassRefPtr<FEBlend> create(Filter*, BlendModeType); + + BlendModeType blendMode() const; + void setBlendMode(BlendModeType); + + virtual void apply(); + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEBlend(Filter*, BlendModeType); + + BlendModeType m_mode; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEBlend_h diff --git a/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp b/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp new file mode 100644 index 0000000..e0b15d1 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEColorMatrix.h" + +#include "Filter.h" +#include "GraphicsContext.h" + +#include <wtf/ByteArray.h> +#include <wtf/MathExtras.h> + +namespace WebCore { + +FEColorMatrix::FEColorMatrix(Filter* filter, ColorMatrixType type, const Vector<float>& values) + : FilterEffect(filter) + , m_type(type) + , m_values(values) +{ +} + +PassRefPtr<FEColorMatrix> FEColorMatrix::create(Filter* filter, ColorMatrixType type, const Vector<float>& values) +{ + return adoptRef(new FEColorMatrix(filter, type, values)); +} + +ColorMatrixType FEColorMatrix::type() const +{ + return m_type; +} + +void FEColorMatrix::setType(ColorMatrixType type) +{ + m_type = type; +} + +const Vector<float>& FEColorMatrix::values() const +{ + return m_values; +} + +void FEColorMatrix::setValues(const Vector<float> &values) +{ + m_values = values; +} + +inline void matrix(double& red, double& green, double& blue, double& alpha, const Vector<float>& values) +{ + double r = values[0] * red + values[1] * green + values[2] * blue + values[3] * alpha + values[4] * 255; + double g = values[5] * red + values[6] * green + values[7] * blue + values[8] * alpha + values[9] * 255; + double b = values[10] * red + values[11] * green + values[12] * blue + values[13] * alpha + values[14] * 255; + double a = values[15] * red + values[16] * green + values[17] * blue + values[18] * alpha + values[19] * 255; + + red = r; + green = g; + blue = b; + alpha = a; +} + +inline void saturate(double& red, double& green, double& blue, const float& s) +{ + double r = (0.213 + 0.787 * s) * red + (0.715 - 0.715 * s) * green + (0.072 - 0.072 * s) * blue; + double g = (0.213 - 0.213 * s) * red + (0.715 + 0.285 * s) * green + (0.072 - 0.072 * s) * blue; + double b = (0.213 - 0.213 * s) * red + (0.715 - 0.715 * s) * green + (0.072 + 0.928 * s) * blue; + + red = r; + green = g; + blue = b; +} + +inline void huerotate(double& red, double& green, double& blue, const float& hue) +{ + double cosHue = cos(hue * piDouble / 180); + double sinHue = sin(hue * piDouble / 180); + double r = red * (0.213 + cosHue * 0.787 - sinHue * 0.213) + + green * (0.715 - cosHue * 0.715 - sinHue * 0.715) + + blue * (0.072 - cosHue * 0.072 + sinHue * 0.928); + double g = red * (0.213 - cosHue * 0.213 + sinHue * 0.143) + + green * (0.715 + cosHue * 0.285 + sinHue * 0.140) + + blue * (0.072 - cosHue * 0.072 - sinHue * 0.283); + double b = red * (0.213 - cosHue * 0.213 - sinHue * 0.787) + + green * (0.715 - cosHue * 0.715 + sinHue * 0.715) + + blue * (0.072 + cosHue * 0.928 + sinHue * 0.072); + + red = r; + green = g; + blue = b; +} + +inline void luminance(double& red, double& green, double& blue, double& alpha) +{ + alpha = 0.2125 * red + 0.7154 * green + 0.0721 * blue; + red = 0; + green = 0; + blue = 0; +} + +template<ColorMatrixType filterType> +void effectType(ByteArray* pixelArray, const Vector<float>& values) +{ + unsigned pixelArrayLength = pixelArray->length(); + for (unsigned pixelByteOffset = 0; pixelByteOffset < pixelArrayLength; pixelByteOffset += 4) { + double red = pixelArray->get(pixelByteOffset); + double green = pixelArray->get(pixelByteOffset + 1); + double blue = pixelArray->get(pixelByteOffset + 2); + double alpha = pixelArray->get(pixelByteOffset + 3); + + switch (filterType) { + case FECOLORMATRIX_TYPE_MATRIX: + matrix(red, green, blue, alpha, values); + break; + case FECOLORMATRIX_TYPE_SATURATE: + saturate(red, green, blue, values[0]); + break; + case FECOLORMATRIX_TYPE_HUEROTATE: + huerotate(red, green, blue, values[0]); + break; + case FECOLORMATRIX_TYPE_LUMINANCETOALPHA: + luminance(red, green, blue, alpha); + break; + } + + pixelArray->set(pixelByteOffset, red); + pixelArray->set(pixelByteOffset + 1, green); + pixelArray->set(pixelByteOffset + 2, blue); + pixelArray->set(pixelByteOffset + 3, alpha); + } +} + +void FEColorMatrix::apply() +{ + if (hasResult()) + return; + FilterEffect* in = inputEffect(0); + in->apply(); + if (!in->hasResult()) + return; + + ImageBuffer* resultImage = createImageBufferResult(); + if (!resultImage) + return; + + resultImage->context()->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect())); + + IntRect imageRect(IntPoint(), absolutePaintRect().size()); + RefPtr<ByteArray> pixelArray = resultImage->getUnmultipliedImageData(imageRect); + + switch (m_type) { + case FECOLORMATRIX_TYPE_UNKNOWN: + break; + case FECOLORMATRIX_TYPE_MATRIX: + effectType<FECOLORMATRIX_TYPE_MATRIX>(pixelArray.get(), m_values); + break; + case FECOLORMATRIX_TYPE_SATURATE: + effectType<FECOLORMATRIX_TYPE_SATURATE>(pixelArray.get(), m_values); + break; + case FECOLORMATRIX_TYPE_HUEROTATE: + effectType<FECOLORMATRIX_TYPE_HUEROTATE>(pixelArray.get(), m_values); + break; + case FECOLORMATRIX_TYPE_LUMINANCETOALPHA: + effectType<FECOLORMATRIX_TYPE_LUMINANCETOALPHA>(pixelArray.get(), m_values); + setIsAlphaImage(true); + break; + } + + resultImage->putUnmultipliedImageData(pixelArray.get(), imageRect.size(), imageRect, IntPoint()); +} + +void FEColorMatrix::dump() +{ +} + +static TextStream& operator<<(TextStream& ts, const ColorMatrixType& type) +{ + switch (type) { + case FECOLORMATRIX_TYPE_UNKNOWN: + ts << "UNKNOWN"; + break; + case FECOLORMATRIX_TYPE_MATRIX: + ts << "MATRIX"; + break; + case FECOLORMATRIX_TYPE_SATURATE: + ts << "SATURATE"; + break; + case FECOLORMATRIX_TYPE_HUEROTATE: + ts << "HUEROTATE"; + break; + case FECOLORMATRIX_TYPE_LUMINANCETOALPHA: + ts << "LUMINANCETOALPHA"; + break; + } + return ts; +} + +TextStream& FEColorMatrix::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feColorMatrix"; + FilterEffect::externalRepresentation(ts); + ts << " type=\"" << m_type << "\""; + if (!m_values.isEmpty()) { + ts << " values=\""; + Vector<float>::const_iterator ptr = m_values.begin(); + const Vector<float>::const_iterator end = m_values.end(); + while (ptr < end) { + ts << *ptr; + ++ptr; + if (ptr < end) + ts << " "; + } + ts << "\""; + } + ts << "]\n"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/FEColorMatrix.h b/Source/WebCore/platform/graphics/filters/FEColorMatrix.h new file mode 100644 index 0000000..a3ced7e --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEColorMatrix.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FEColorMatrix_h +#define FEColorMatrix_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" + +#include "Filter.h" +#include <wtf/Vector.h> + +namespace WebCore { + +enum ColorMatrixType { + FECOLORMATRIX_TYPE_UNKNOWN = 0, + FECOLORMATRIX_TYPE_MATRIX = 1, + FECOLORMATRIX_TYPE_SATURATE = 2, + FECOLORMATRIX_TYPE_HUEROTATE = 3, + FECOLORMATRIX_TYPE_LUMINANCETOALPHA = 4 +}; + +class FEColorMatrix : public FilterEffect { +public: + static PassRefPtr<FEColorMatrix> create(Filter*, ColorMatrixType, const Vector<float>&); + + ColorMatrixType type() const; + void setType(ColorMatrixType); + + const Vector<float>& values() const; + void setValues(const Vector<float>&); + + virtual void apply(); + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEColorMatrix(Filter*, ColorMatrixType, const Vector<float>&); + + ColorMatrixType m_type; + Vector<float> m_values; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEColorMatrix_h diff --git a/Source/WebCore/platform/graphics/filters/FEComponentTransfer.cpp b/Source/WebCore/platform/graphics/filters/FEComponentTransfer.cpp new file mode 100644 index 0000000..ca8e5d3 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEComponentTransfer.cpp @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEComponentTransfer.h" + +#include "Filter.h" +#include "GraphicsContext.h" + +#include <wtf/ByteArray.h> +#include <wtf/MathExtras.h> + +namespace WebCore { + +typedef void (*TransferType)(unsigned char*, const ComponentTransferFunction&); + +FEComponentTransfer::FEComponentTransfer(Filter* filter, const ComponentTransferFunction& redFunc, const ComponentTransferFunction& greenFunc, + const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc) + : FilterEffect(filter) + , m_redFunc(redFunc) + , m_greenFunc(greenFunc) + , m_blueFunc(blueFunc) + , m_alphaFunc(alphaFunc) +{ +} + +PassRefPtr<FEComponentTransfer> FEComponentTransfer::create(Filter* filter, const ComponentTransferFunction& redFunc, + const ComponentTransferFunction& greenFunc, const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc) +{ + return adoptRef(new FEComponentTransfer(filter, redFunc, greenFunc, blueFunc, alphaFunc)); +} + +ComponentTransferFunction FEComponentTransfer::redFunction() const +{ + return m_redFunc; +} + +void FEComponentTransfer::setRedFunction(const ComponentTransferFunction& func) +{ + m_redFunc = func; +} + +ComponentTransferFunction FEComponentTransfer::greenFunction() const +{ + return m_greenFunc; +} + +void FEComponentTransfer::setGreenFunction(const ComponentTransferFunction& func) +{ + m_greenFunc = func; +} + +ComponentTransferFunction FEComponentTransfer::blueFunction() const +{ + return m_blueFunc; +} + +void FEComponentTransfer::setBlueFunction(const ComponentTransferFunction& func) +{ + m_blueFunc = func; +} + +ComponentTransferFunction FEComponentTransfer::alphaFunction() const +{ + return m_alphaFunc; +} + +void FEComponentTransfer::setAlphaFunction(const ComponentTransferFunction& func) +{ + m_alphaFunc = func; +} + +static void identity(unsigned char*, const ComponentTransferFunction&) +{ +} + +static void table(unsigned char* values, const ComponentTransferFunction& transferFunction) +{ + const Vector<float>& tableValues = transferFunction.tableValues; + unsigned n = tableValues.size(); + if (n < 1) + return; + for (unsigned i = 0; i < 256; ++i) { + double c = i / 255.0; + unsigned k = static_cast<unsigned>(c * (n - 1)); + double v1 = tableValues[k]; + double v2 = tableValues[std::min((k + 1), (n - 1))]; + double val = 255.0 * (v1 + (c * (n - 1) - k) * (v2 - v1)); + val = std::max(0.0, std::min(255.0, val)); + values[i] = static_cast<unsigned char>(val); + } +} + +static void discrete(unsigned char* values, const ComponentTransferFunction& transferFunction) +{ + const Vector<float>& tableValues = transferFunction.tableValues; + unsigned n = tableValues.size(); + if (n < 1) + return; + for (unsigned i = 0; i < 256; ++i) { + unsigned k = static_cast<unsigned>((i * n) / 255.0); + k = std::min(k, n - 1); + double val = 255 * tableValues[k]; + val = std::max(0.0, std::min(255.0, val)); + values[i] = static_cast<unsigned char>(val); + } +} + +static void linear(unsigned char* values, const ComponentTransferFunction& transferFunction) +{ + for (unsigned i = 0; i < 256; ++i) { + double val = transferFunction.slope * i + 255 * transferFunction.intercept; + val = std::max(0.0, std::min(255.0, val)); + values[i] = static_cast<unsigned char>(val); + } +} + +static void gamma(unsigned char* values, const ComponentTransferFunction& transferFunction) +{ + for (unsigned i = 0; i < 256; ++i) { + double exponent = transferFunction.exponent; // RCVT doesn't like passing a double and a float to pow, so promote this to double + double val = 255.0 * (transferFunction.amplitude * pow((i / 255.0), exponent) + transferFunction.offset); + val = std::max(0.0, std::min(255.0, val)); + values[i] = static_cast<unsigned char>(val); + } +} + +void FEComponentTransfer::apply() +{ + if (hasResult()) + return; + FilterEffect* in = inputEffect(0); + in->apply(); + if (!in->hasResult()) + return; + + ByteArray* pixelArray = createUnmultipliedImageResult(); + if (!pixelArray) + return; + + unsigned char rValues[256], gValues[256], bValues[256], aValues[256]; + for (unsigned i = 0; i < 256; ++i) + rValues[i] = gValues[i] = bValues[i] = aValues[i] = i; + unsigned char* tables[] = { rValues, gValues, bValues, aValues }; + ComponentTransferFunction transferFunction[] = {m_redFunc, m_greenFunc, m_blueFunc, m_alphaFunc}; + TransferType callEffect[] = {identity, identity, table, discrete, linear, gamma}; + + for (unsigned channel = 0; channel < 4; channel++) + (*callEffect[transferFunction[channel].type])(tables[channel], transferFunction[channel]); + + IntRect drawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); + in->copyUnmultipliedImage(pixelArray, drawingRect); + + unsigned pixelArrayLength = pixelArray->length(); + for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) { + for (unsigned channel = 0; channel < 4; ++channel) { + unsigned char c = pixelArray->get(pixelOffset + channel); + pixelArray->set(pixelOffset + channel, tables[channel][c]); + } + } +} + +void FEComponentTransfer::dump() +{ +} + +static TextStream& operator<<(TextStream& ts, const ComponentTransferType& type) +{ + switch (type) { + case FECOMPONENTTRANSFER_TYPE_UNKNOWN: + ts << "UNKNOWN"; + break; + case FECOMPONENTTRANSFER_TYPE_IDENTITY: + ts << "IDENTITY"; + break; + case FECOMPONENTTRANSFER_TYPE_TABLE: + ts << "TABLE"; + break; + case FECOMPONENTTRANSFER_TYPE_DISCRETE: + ts << "DISCRETE"; + break; + case FECOMPONENTTRANSFER_TYPE_LINEAR: + ts << "LINEAR"; + break; + case FECOMPONENTTRANSFER_TYPE_GAMMA: + ts << "GAMMA"; + break; + } + return ts; +} + +static TextStream& operator<<(TextStream& ts, const ComponentTransferFunction& function) +{ + ts << "type=\"" << function.type + << "\" slope=\"" << function.slope + << "\" intercept=\"" << function.intercept + << "\" amplitude=\"" << function.amplitude + << "\" exponent=\"" << function.exponent + << "\" offset=\"" << function.offset << "\""; + return ts; +} + +TextStream& FEComponentTransfer::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feComponentTransfer"; + FilterEffect::externalRepresentation(ts); + ts << " \n"; + writeIndent(ts, indent + 2); + ts << "{red: " << m_redFunc << "}\n"; + writeIndent(ts, indent + 2); + ts << "{green: " << m_greenFunc << "}\n"; + writeIndent(ts, indent + 2); + ts << "{blue: " << m_blueFunc << "}\n"; + writeIndent(ts, indent + 2); + ts << "{alpha: " << m_alphaFunc << "}]\n"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/FEComponentTransfer.h b/Source/WebCore/platform/graphics/filters/FEComponentTransfer.h new file mode 100644 index 0000000..bbe3ebb --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEComponentTransfer.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FEComponentTransfer_h +#define FEComponentTransfer_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" + +#include "Filter.h" +#include <wtf/Vector.h> + +namespace WebCore { + +enum ComponentTransferType { + FECOMPONENTTRANSFER_TYPE_UNKNOWN = 0, + FECOMPONENTTRANSFER_TYPE_IDENTITY = 1, + FECOMPONENTTRANSFER_TYPE_TABLE = 2, + FECOMPONENTTRANSFER_TYPE_DISCRETE = 3, + FECOMPONENTTRANSFER_TYPE_LINEAR = 4, + FECOMPONENTTRANSFER_TYPE_GAMMA = 5 +}; + +struct ComponentTransferFunction { + ComponentTransferFunction() + : type(FECOMPONENTTRANSFER_TYPE_UNKNOWN) + , slope(0) + , intercept(0) + , amplitude(0) + , exponent(0) + , offset(0) + { + } + + ComponentTransferType type; + + float slope; + float intercept; + float amplitude; + float exponent; + float offset; + + Vector<float> tableValues; +}; + +class FEComponentTransfer : public FilterEffect { +public: + static PassRefPtr<FEComponentTransfer> create(Filter*, const ComponentTransferFunction& redFunc, const ComponentTransferFunction& greenFunc, + const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc); + + ComponentTransferFunction redFunction() const; + void setRedFunction(const ComponentTransferFunction&); + + ComponentTransferFunction greenFunction() const; + void setGreenFunction(const ComponentTransferFunction&); + + ComponentTransferFunction blueFunction() const; + void setBlueFunction(const ComponentTransferFunction&); + + ComponentTransferFunction alphaFunction() const; + void setAlphaFunction(const ComponentTransferFunction&); + + virtual void apply(); + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEComponentTransfer(Filter*, const ComponentTransferFunction& redFunc, const ComponentTransferFunction& greenFunc, + const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc); + + ComponentTransferFunction m_redFunc; + ComponentTransferFunction m_greenFunc; + ComponentTransferFunction m_blueFunc; + ComponentTransferFunction m_alphaFunc; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEComponentTransfer_h diff --git a/Source/WebCore/platform/graphics/filters/FEComposite.cpp b/Source/WebCore/platform/graphics/filters/FEComposite.cpp new file mode 100644 index 0000000..80cb2b2 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEComposite.cpp @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEComposite.h" + +#include "Filter.h" +#include "GraphicsContext.h" + +#include <wtf/ByteArray.h> + +namespace WebCore { + +FEComposite::FEComposite(Filter* filter, const CompositeOperationType& type, float k1, float k2, float k3, float k4) + : FilterEffect(filter) + , m_type(type) + , m_k1(k1) + , m_k2(k2) + , m_k3(k3) + , m_k4(k4) +{ +} + +PassRefPtr<FEComposite> FEComposite::create(Filter* filter, const CompositeOperationType& type, float k1, float k2, float k3, float k4) +{ + return adoptRef(new FEComposite(filter, type, k1, k2, k3, k4)); +} + +CompositeOperationType FEComposite::operation() const +{ + return m_type; +} + +void FEComposite::setOperation(CompositeOperationType type) +{ + m_type = type; +} + +float FEComposite::k1() const +{ + return m_k1; +} + +void FEComposite::setK1(float k1) +{ + m_k1 = k1; +} + +float FEComposite::k2() const +{ + return m_k2; +} + +void FEComposite::setK2(float k2) +{ + m_k2 = k2; +} + +float FEComposite::k3() const +{ + return m_k3; +} + +void FEComposite::setK3(float k3) +{ + m_k3 = k3; +} + +float FEComposite::k4() const +{ + return m_k4; +} + +void FEComposite::setK4(float k4) +{ + m_k4 = k4; +} + +template <int b1, int b2, int b3, int b4> +inline void computeArithmeticPixels(unsigned char* source, unsigned char* destination, int pixelArrayLength, + float k1, float k2, float k3, float k4) +{ + float scaledK4; + float scaledK1; + if (b1) + scaledK1 = k1 / 255.f; + if (b4) + scaledK4 = k4 * 255.f; + + while (--pixelArrayLength >= 0) { + unsigned char i1 = *source; + unsigned char i2 = *destination; + float result = 0; + if (b1) + result += scaledK1 * i1 * i2; + if (b2) + result += k2 * i1; + if (b3) + result += k3 * i2; + if (b4) + result += scaledK4; + + if (result <= 0) + *destination = 0; + else if (result >= 255) + *destination = 255; + else + *destination = result; + ++source; + ++destination; + } +} + +inline void arithmetic(ByteArray* srcPixelArrayA, ByteArray* srcPixelArrayB, + float k1, float k2, float k3, float k4) +{ + int pixelArrayLength = srcPixelArrayA->length(); + ASSERT(pixelArrayLength == static_cast<int>(srcPixelArrayB->length())); + unsigned char* source = srcPixelArrayA->data(); + unsigned char* destination = srcPixelArrayB->data(); + + if (!k4) { + if (!k1) { + computeArithmeticPixels<0, 1, 1, 0>(source, destination, pixelArrayLength, k1, k2, k3, k4); + return; + } + + computeArithmeticPixels<1, 1, 1, 0>(source, destination, pixelArrayLength, k1, k2, k3, k4); + return; + } + + if (!k1) { + computeArithmeticPixels<0, 1, 1, 1>(source, destination, pixelArrayLength, k1, k2, k3, k4); + return; + } + computeArithmeticPixels<1, 1, 1, 1>(source, destination, pixelArrayLength, k1, k2, k3, k4); +} + +void FEComposite::determineAbsolutePaintRect() +{ + switch (m_type) { + case FECOMPOSITE_OPERATOR_IN: + case FECOMPOSITE_OPERATOR_ATOP: + // For In and Atop the first effect just influences the result of + // the second effect. So just use the absolute paint rect of the second effect here. + setAbsolutePaintRect(inputEffect(1)->absolutePaintRect()); + return; + case FECOMPOSITE_OPERATOR_ARITHMETIC: + // Arithmetic may influnce the compele filter primitive region. So we can't + // optimize the paint region here. + setAbsolutePaintRect(maxEffectRect()); + return; + default: + // Take the union of both input effects. + FilterEffect::determineAbsolutePaintRect(); + return; + } +} + +void FEComposite::apply() +{ + if (hasResult()) + return; + FilterEffect* in = inputEffect(0); + FilterEffect* in2 = inputEffect(1); + in->apply(); + in2->apply(); + if (!in->hasResult() || !in2->hasResult()) + return; + + if (m_type == FECOMPOSITE_OPERATOR_ARITHMETIC) { + ByteArray* dstPixelArray = createPremultipliedImageResult(); + if (!dstPixelArray) + return; + + IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); + RefPtr<ByteArray> srcPixelArray = in->asPremultipliedImage(effectADrawingRect); + + IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect()); + in2->copyPremultipliedImage(dstPixelArray, effectBDrawingRect); + + arithmetic(srcPixelArray.get(), dstPixelArray, m_k1, m_k2, m_k3, m_k4); + return; + } + + ImageBuffer* resultImage = createImageBufferResult(); + if (!resultImage) + return; + GraphicsContext* filterContext = resultImage->context(); + + FloatRect srcRect = FloatRect(0, 0, -1, -1); + switch (m_type) { + case FECOMPOSITE_OPERATOR_OVER: + filterContext->drawImageBuffer(in2->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect())); + filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect())); + break; + case FECOMPOSITE_OPERATOR_IN: + filterContext->save(); + filterContext->clipToImageBuffer(in2->asImageBuffer(), drawingRegionOfInputImage(in2->absolutePaintRect())); + filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect())); + filterContext->restore(); + break; + case FECOMPOSITE_OPERATOR_OUT: + filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect())); + filterContext->drawImageBuffer(in2->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()), srcRect, CompositeDestinationOut); + break; + case FECOMPOSITE_OPERATOR_ATOP: + filterContext->drawImageBuffer(in2->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect())); + filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()), srcRect, CompositeSourceAtop); + break; + case FECOMPOSITE_OPERATOR_XOR: + filterContext->drawImageBuffer(in2->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect())); + filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()), srcRect, CompositeXOR); + break; + default: + break; + } +} + +void FEComposite::dump() +{ +} + +static TextStream& operator<<(TextStream& ts, const CompositeOperationType& type) +{ + switch (type) { + case FECOMPOSITE_OPERATOR_UNKNOWN: + ts << "UNKNOWN"; + break; + case FECOMPOSITE_OPERATOR_OVER: + ts << "OVER"; + break; + case FECOMPOSITE_OPERATOR_IN: + ts << "IN"; + break; + case FECOMPOSITE_OPERATOR_OUT: + ts << "OUT"; + break; + case FECOMPOSITE_OPERATOR_ATOP: + ts << "ATOP"; + break; + case FECOMPOSITE_OPERATOR_XOR: + ts << "XOR"; + break; + case FECOMPOSITE_OPERATOR_ARITHMETIC: + ts << "ARITHMETIC"; + break; + } + return ts; +} + +TextStream& FEComposite::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feComposite"; + FilterEffect::externalRepresentation(ts); + ts << " operation=\"" << m_type << "\""; + if (m_type == FECOMPOSITE_OPERATOR_ARITHMETIC) + ts << " k1=\"" << m_k1 << "\" k2=\"" << m_k2 << "\" k3=\"" << m_k3 << "\" k4=\"" << m_k4 << "\""; + ts << "]\n"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + inputEffect(1)->externalRepresentation(ts, indent + 1); + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/FEComposite.h b/Source/WebCore/platform/graphics/filters/FEComposite.h new file mode 100644 index 0000000..b846902 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEComposite.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FEComposite_h +#define FEComposite_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" + +#include "PlatformString.h" +#include "Filter.h" + +namespace WebCore { + +enum CompositeOperationType { + FECOMPOSITE_OPERATOR_UNKNOWN = 0, + FECOMPOSITE_OPERATOR_OVER = 1, + FECOMPOSITE_OPERATOR_IN = 2, + FECOMPOSITE_OPERATOR_OUT = 3, + FECOMPOSITE_OPERATOR_ATOP = 4, + FECOMPOSITE_OPERATOR_XOR = 5, + FECOMPOSITE_OPERATOR_ARITHMETIC = 6 +}; + +class FEComposite : public FilterEffect { +public: + static PassRefPtr<FEComposite> create(Filter*, const CompositeOperationType&, float, float, float, float); + + CompositeOperationType operation() const; + void setOperation(CompositeOperationType); + + float k1() const; + void setK1(float); + + float k2() const; + void setK2(float); + + float k3() const; + void setK3(float); + + float k4() const; + void setK4(float); + + virtual void apply(); + virtual void dump(); + + virtual void determineAbsolutePaintRect(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEComposite(Filter*, const CompositeOperationType&, float, float, float, float); + + CompositeOperationType m_type; + float m_k1; + float m_k2; + float m_k3; + float m_k4; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEComposite_h diff --git a/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp b/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp new file mode 100644 index 0000000..b8f8aea --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp @@ -0,0 +1,471 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) 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 + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEConvolveMatrix.h" + +#include "Filter.h" + +#include <wtf/ByteArray.h> + +namespace WebCore { + +FEConvolveMatrix::FEConvolveMatrix(Filter* filter, const IntSize& kernelSize, + float divisor, float bias, const IntPoint& targetOffset, EdgeModeType edgeMode, + const FloatPoint& kernelUnitLength, bool preserveAlpha, const Vector<float>& kernelMatrix) + : FilterEffect(filter) + , m_kernelSize(kernelSize) + , m_divisor(divisor) + , m_bias(bias) + , m_targetOffset(targetOffset) + , m_edgeMode(edgeMode) + , m_kernelUnitLength(kernelUnitLength) + , m_preserveAlpha(preserveAlpha) + , m_kernelMatrix(kernelMatrix) +{ +} + +PassRefPtr<FEConvolveMatrix> FEConvolveMatrix::create(Filter* filter, const IntSize& kernelSize, + float divisor, float bias, const IntPoint& targetOffset, EdgeModeType edgeMode, + const FloatPoint& kernelUnitLength, bool preserveAlpha, const Vector<float>& kernelMatrix) +{ + return adoptRef(new FEConvolveMatrix(filter, kernelSize, divisor, bias, targetOffset, edgeMode, kernelUnitLength, + preserveAlpha, kernelMatrix)); +} + + +IntSize FEConvolveMatrix::kernelSize() const +{ + return m_kernelSize; +} + +void FEConvolveMatrix::setKernelSize(IntSize kernelSize) +{ + m_kernelSize = kernelSize; +} + +const Vector<float>& FEConvolveMatrix::kernel() const +{ + return m_kernelMatrix; +} + +void FEConvolveMatrix::setKernel(const Vector<float>& kernel) +{ + m_kernelMatrix = kernel; +} + +float FEConvolveMatrix::divisor() const +{ + return m_divisor; +} + +void FEConvolveMatrix::setDivisor(float divisor) +{ + m_divisor = divisor; +} + +float FEConvolveMatrix::bias() const +{ + return m_bias; +} + +void FEConvolveMatrix::setBias(float bias) +{ + m_bias = bias; +} + +IntPoint FEConvolveMatrix::targetOffset() const +{ + return m_targetOffset; +} + +void FEConvolveMatrix::setTargetOffset(IntPoint targetOffset) +{ + m_targetOffset = targetOffset; +} + +EdgeModeType FEConvolveMatrix::edgeMode() const +{ + return m_edgeMode; +} + +void FEConvolveMatrix::setEdgeMode(EdgeModeType edgeMode) +{ + m_edgeMode = edgeMode; +} + +FloatPoint FEConvolveMatrix::kernelUnitLength() const +{ + return m_kernelUnitLength; +} + +void FEConvolveMatrix::setKernelUnitLength(FloatPoint kernelUnitLength) +{ + m_kernelUnitLength = kernelUnitLength; +} + +bool FEConvolveMatrix::preserveAlpha() const +{ + return m_preserveAlpha; +} + +void FEConvolveMatrix::setPreserveAlpha(bool preserveAlpha) +{ + m_preserveAlpha = preserveAlpha; +} + +/* + ----------------------------------- + ConvolveMatrix implementation + ----------------------------------- + + The image rectangle is split in the following way: + + +---------------------+ + | A | + +---------------------+ + | | | | + | B | C | D | + | | | | + +---------------------+ + | E | + +---------------------+ + + Where region C contains those pixels, whose values + can be calculated without crossing the edge of the rectangle. + + Example: + Image size: width: 10, height: 10 + + Order (kernel matrix size): width: 3, height 4 + Target: x:1, y:3 + + The following figure shows the target inside the kernel matrix: + + ... + ... + ... + .X. + + The regions in this case are the following: + Note: (x1, y1) top-left and (x2, y2) is the bottom-right corner + Note: row x2 and column y2 is not part of the region + only those (x, y) pixels, where x1 <= x < x2 and y1 <= y < y2 + + Region A: x1: 0, y1: 0, x2: 10, y2: 3 + Region B: x1: 0, y1: 3, x2: 1, y2: 10 + Region C: x1: 1, y1: 3, x2: 9, y2: 10 + Region D: x1: 9, y1: 3, x2: 10, y2: 10 + Region E: x1: 0, y1: 10, x2: 10, y2: 10 (empty region) + + Since region C (often) contains most of the pixels, we implemented + a fast algoritm to calculate these values, called fastSetInteriorPixels. + For other regions, fastSetOuterPixels is used, which calls getPixelValue, + to handle pixels outside of the image. In a rare situations, when + kernel matrix is bigger than the image, all pixels are calculated by this + function. + + Although these two functions have lot in common, I decided not to make + common a template for them, since there are key differences as well, + and would make it really hard to understand. +*/ + +static ALWAYS_INLINE unsigned char clampRGBAValue(float channel, unsigned char max = 255) +{ + if (channel <= 0) + return 0; + if (channel >= max) + return max; + return channel; +} + +template<bool preserveAlphaValues> +ALWAYS_INLINE void setDestinationPixels(ByteArray* image, int& pixel, float* totals, float divisor, float bias, ByteArray* src) +{ + unsigned char maxAlpha = preserveAlphaValues ? 255 : clampRGBAValue(totals[3] / divisor + bias); + for (int i = 0; i < 3; ++i) + image->set(pixel++, clampRGBAValue(totals[i] / divisor + bias, maxAlpha)); + + if (preserveAlphaValues) { + image->set(pixel, src->get(pixel)); + ++pixel; + } else + image->set(pixel++, maxAlpha); +} + +// Only for region C +template<bool preserveAlphaValues> +ALWAYS_INLINE void FEConvolveMatrix::fastSetInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom) +{ + // edge mode does not affect these pixels + int pixel = (m_targetOffset.y() * paintingData.width + m_targetOffset.x()) * 4; + int startKernelPixel = 0; + int kernelIncrease = clipRight * 4; + int xIncrease = (m_kernelSize.width() - 1) * 4; + // Contains the sum of rgb(a) components + float totals[3 + (preserveAlphaValues ? 0 : 1)]; + + // m_divisor cannot be 0, SVGFEConvolveMatrixElement ensures this + ASSERT(m_divisor); + + for (int y = clipBottom + 1; y > 0; --y) { + for (int x = clipRight + 1; x > 0; --x) { + int kernelValue = m_kernelMatrix.size() - 1; + int kernelPixel = startKernelPixel; + int width = m_kernelSize.width(); + + totals[0] = 0; + totals[1] = 0; + totals[2] = 0; + if (!preserveAlphaValues) + totals[3] = 0; + + while (kernelValue >= 0) { + totals[0] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(kernelPixel++)); + totals[1] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(kernelPixel++)); + totals[2] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(kernelPixel++)); + if (!preserveAlphaValues) + totals[3] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(kernelPixel)); + ++kernelPixel; + --kernelValue; + if (!--width) { + kernelPixel += kernelIncrease; + width = m_kernelSize.width(); + } + } + + setDestinationPixels<preserveAlphaValues>(paintingData.dstPixelArray, pixel, totals, m_divisor, paintingData.bias, paintingData.srcPixelArray); + startKernelPixel += 4; + } + pixel += xIncrease; + startKernelPixel += xIncrease; + } +} + +ALWAYS_INLINE int FEConvolveMatrix::getPixelValue(PaintingData& paintingData, int x, int y) +{ + if (x >= 0 && x < paintingData.width && x >= 0 && y < paintingData.height) + return (y * paintingData.width + x) << 2; + + switch (m_edgeMode) { + default: // EDGEMODE_NONE + return -1; + case EDGEMODE_DUPLICATE: + if (x < 0) + x = 0; + else if (x >= paintingData.width) + x = paintingData.width - 1; + if (y < 0) + y = 0; + else if (y >= paintingData.height) + y = paintingData.height - 1; + return (y * paintingData.width + x) << 2; + case EDGEMODE_WRAP: + while (x < 0) + x += paintingData.width; + x %= paintingData.width; + while (y < 0) + y += paintingData.height; + y %= paintingData.height; + return (y * paintingData.width + x) << 2; + } +} + +// For other regions than C +template<bool preserveAlphaValues> +void FEConvolveMatrix::fastSetOuterPixels(PaintingData& paintingData, int x1, int y1, int x2, int y2) +{ + int pixel = (y1 * paintingData.width + x1) * 4; + int height = y2 - y1; + int width = x2 - x1; + int beginKernelPixelX = x1 - m_targetOffset.x(); + int startKernelPixelX = beginKernelPixelX; + int startKernelPixelY = y1 - m_targetOffset.y(); + int xIncrease = (paintingData.width - width) * 4; + // Contains the sum of rgb(a) components + float totals[3 + (preserveAlphaValues ? 0 : 1)]; + + // m_divisor cannot be 0, SVGFEConvolveMatrixElement ensures this + ASSERT(m_divisor); + + for (int y = height; y > 0; --y) { + for (int x = width; x > 0; --x) { + int kernelValue = m_kernelMatrix.size() - 1; + int kernelPixelX = startKernelPixelX; + int kernelPixelY = startKernelPixelY; + int width = m_kernelSize.width(); + + totals[0] = 0; + totals[1] = 0; + totals[2] = 0; + if (!preserveAlphaValues) + totals[3] = 0; + + while (kernelValue >= 0) { + int pixelIndex = getPixelValue(paintingData, kernelPixelX, kernelPixelY); + if (pixelIndex >= 0) { + totals[0] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(pixelIndex)); + totals[1] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(pixelIndex + 1)); + totals[2] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(pixelIndex + 2)); + } + if (!preserveAlphaValues && pixelIndex >= 0) + totals[3] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(pixelIndex + 3)); + ++kernelPixelX; + --kernelValue; + if (!--width) { + kernelPixelX = startKernelPixelX; + ++kernelPixelY; + width = m_kernelSize.width(); + } + } + + setDestinationPixels<preserveAlphaValues>(paintingData.dstPixelArray, pixel, totals, m_divisor, paintingData.bias, paintingData.srcPixelArray); + ++startKernelPixelX; + } + pixel += xIncrease; + startKernelPixelX = beginKernelPixelX; + ++startKernelPixelY; + } +} + +ALWAYS_INLINE void FEConvolveMatrix::setInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom) +{ + // Must be implemented here, since it refers another ALWAYS_INLINE + // function, which defined in this C++ source file as well + if (m_preserveAlpha) + fastSetInteriorPixels<true>(paintingData, clipRight, clipBottom); + else + fastSetInteriorPixels<false>(paintingData, clipRight, clipBottom); +} + +ALWAYS_INLINE void FEConvolveMatrix::setOuterPixels(PaintingData& paintingData, int x1, int y1, int x2, int y2) +{ + // Although this function can be moved to the header, it is implemented here + // because setInteriorPixels is also implemented here + if (m_preserveAlpha) + fastSetOuterPixels<true>(paintingData, x1, y1, x2, y2); + else + fastSetOuterPixels<false>(paintingData, x1, y1, x2, y2); +} + +void FEConvolveMatrix::apply() +{ + if (hasResult()) + return; + FilterEffect* in = inputEffect(0); + in->apply(); + if (!in->hasResult()) + return; + + ByteArray* resultImage; + if (m_preserveAlpha) + resultImage = createUnmultipliedImageResult(); + else + resultImage = createPremultipliedImageResult(); + if (!resultImage) + return; + + IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); + + RefPtr<ByteArray> srcPixelArray; + if (m_preserveAlpha) + srcPixelArray = in->asUnmultipliedImage(effectDrawingRect); + else + srcPixelArray = in->asPremultipliedImage(effectDrawingRect); + + IntSize paintSize = absolutePaintRect().size(); + PaintingData paintingData; + paintingData.srcPixelArray = srcPixelArray.get(); + paintingData.dstPixelArray = resultImage; + paintingData.width = paintSize.width(); + paintingData.height = paintSize.height(); + paintingData.bias = m_bias * 255; + + // Drawing fully covered pixels + int clipRight = paintSize.width() - m_kernelSize.width(); + int clipBottom = paintSize.height() - m_kernelSize.height(); + + if (clipRight >= 0 && clipBottom >= 0) { + setInteriorPixels(paintingData, clipRight, clipBottom); + + clipRight += m_targetOffset.x() + 1; + clipBottom += m_targetOffset.y() + 1; + if (m_targetOffset.y() > 0) + setOuterPixels(paintingData, 0, 0, paintSize.width(), m_targetOffset.y()); + if (clipBottom < paintSize.height()) + setOuterPixels(paintingData, 0, clipBottom, paintSize.width(), paintSize.height()); + if (m_targetOffset.x() > 0) + setOuterPixels(paintingData, 0, m_targetOffset.y(), m_targetOffset.x(), clipBottom); + if (clipRight < paintSize.width()) + setOuterPixels(paintingData, clipRight, m_targetOffset.y(), paintSize.width(), clipBottom); + } else { + // Rare situation, not optimizied for speed + setOuterPixels(paintingData, 0, 0, paintSize.width(), paintSize.height()); + } +} + +void FEConvolveMatrix::dump() +{ +} + +static TextStream& operator<<(TextStream& ts, const EdgeModeType& type) +{ + 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; + } + return ts; +} + +TextStream& FEConvolveMatrix::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feConvolveMatrix"; + FilterEffect::externalRepresentation(ts); + 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"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + return ts; +} + +}; // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.h b/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.h new file mode 100644 index 0000000..05d1199 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 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 + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FEConvolveMatrix_h +#define FEConvolveMatrix_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" +#include "FloatPoint.h" +#include "FloatSize.h" +#include "Filter.h" +#include <wtf/AlwaysInline.h> +#include <wtf/Vector.h> + +namespace WebCore { + +enum EdgeModeType { + EDGEMODE_UNKNOWN = 0, + EDGEMODE_DUPLICATE = 1, + EDGEMODE_WRAP = 2, + EDGEMODE_NONE = 3 +}; + +class CanvasPixelArray; + +class FEConvolveMatrix : public FilterEffect { +public: + static PassRefPtr<FEConvolveMatrix> create(Filter*, const IntSize&, + float, float, const IntPoint&, EdgeModeType, const FloatPoint&, + bool, const Vector<float>&); + + IntSize kernelSize() const; + void setKernelSize(IntSize); + + const Vector<float>& kernel() const; + void setKernel(const Vector<float>&); + + float divisor() const; + void setDivisor(float); + + float bias() const; + void setBias(float); + + IntPoint targetOffset() const; + void setTargetOffset(IntPoint); + + EdgeModeType edgeMode() const; + void setEdgeMode(EdgeModeType); + + FloatPoint kernelUnitLength() const; + void setKernelUnitLength(FloatPoint); + + bool preserveAlpha() const; + void setPreserveAlpha(bool); + + virtual void apply(); + virtual void dump(); + + virtual void determineAbsolutePaintRect() { setAbsolutePaintRect(maxEffectRect()); } + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEConvolveMatrix(Filter*, const IntSize&, float, float, + const IntPoint&, EdgeModeType, const FloatPoint&, bool, const Vector<float>&); + + struct PaintingData { + ByteArray* srcPixelArray; + ByteArray* dstPixelArray; + int width; + int height; + float bias; + }; + + template<bool preserveAlphaValues> + ALWAYS_INLINE void fastSetInteriorPixels(PaintingData&, int clipRight, int clipBottom); + + ALWAYS_INLINE int getPixelValue(PaintingData&, int x, int y); + + template<bool preserveAlphaValues> + void fastSetOuterPixels(PaintingData&, int x1, int y1, int x2, int y2); + + // Wrapper functions + ALWAYS_INLINE void setInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom); + ALWAYS_INLINE void setOuterPixels(PaintingData& paintingData, int x1, int y1, int x2, int y2); + + IntSize m_kernelSize; + float m_divisor; + float m_bias; + IntPoint m_targetOffset; + EdgeModeType m_edgeMode; + FloatPoint m_kernelUnitLength; + bool m_preserveAlpha; + Vector<float> m_kernelMatrix; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEConvolveMatrix_h diff --git a/Source/WebCore/platform/graphics/filters/FEDiffuseLighting.cpp b/Source/WebCore/platform/graphics/filters/FEDiffuseLighting.cpp new file mode 100644 index 0000000..14d57f4 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEDiffuseLighting.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEDiffuseLighting.h" + +#include "LightSource.h" + +namespace WebCore { + +FEDiffuseLighting::FEDiffuseLighting(Filter* filter, const Color& lightingColor, float surfaceScale, + float diffuseConstant, float kernelUnitLengthX, float kernelUnitLengthY, PassRefPtr<LightSource> lightSource) + : FELighting(filter, DiffuseLighting, lightingColor, surfaceScale, diffuseConstant, 0, 0, kernelUnitLengthX, kernelUnitLengthY, lightSource) +{ +} + +PassRefPtr<FEDiffuseLighting> FEDiffuseLighting::create(Filter* filter, const Color& lightingColor, + float surfaceScale, float diffuseConstant, float kernelUnitLengthX, + float kernelUnitLengthY, PassRefPtr<LightSource> lightSource) +{ + return adoptRef(new FEDiffuseLighting(filter, lightingColor, surfaceScale, diffuseConstant, kernelUnitLengthX, kernelUnitLengthY, lightSource)); +} + +FEDiffuseLighting::~FEDiffuseLighting() +{ +} + +Color FEDiffuseLighting::lightingColor() const +{ + return m_lightingColor; +} + +void FEDiffuseLighting::setLightingColor(const Color& lightingColor) +{ + m_lightingColor = lightingColor; +} + +float FEDiffuseLighting::surfaceScale() const +{ + return m_surfaceScale; +} + +void FEDiffuseLighting::setSurfaceScale(float surfaceScale) +{ + m_surfaceScale = surfaceScale; +} + +float FEDiffuseLighting::diffuseConstant() const +{ + return m_diffuseConstant; +} + +void FEDiffuseLighting::setDiffuseConstant(float diffuseConstant) +{ + m_diffuseConstant = diffuseConstant; +} + +float FEDiffuseLighting::kernelUnitLengthX() const +{ + return m_kernelUnitLengthX; +} + +void FEDiffuseLighting::setKernelUnitLengthX(float kernelUnitLengthX) +{ + m_kernelUnitLengthX = kernelUnitLengthX; +} + +float FEDiffuseLighting::kernelUnitLengthY() const +{ + return m_kernelUnitLengthY; +} + +void FEDiffuseLighting::setKernelUnitLengthY(float kernelUnitLengthY) +{ + m_kernelUnitLengthY = kernelUnitLengthY; +} + +const LightSource* FEDiffuseLighting::lightSource() const +{ + return m_lightSource.get(); +} + +void FEDiffuseLighting::setLightSource(PassRefPtr<LightSource> lightSource) +{ + m_lightSource = lightSource; +} + +void FEDiffuseLighting::dump() +{ +} + +TextStream& FEDiffuseLighting::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feDiffuseLighting"; + FilterEffect::externalRepresentation(ts); + ts << " surfaceScale=\"" << m_surfaceScale << "\" " + << "diffuseConstant=\"" << m_diffuseConstant << "\" " + << "kernelUnitLength=\"" << m_kernelUnitLengthX << ", " << m_kernelUnitLengthY << "\"]\n"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/FEDiffuseLighting.h b/Source/WebCore/platform/graphics/filters/FEDiffuseLighting.h new file mode 100644 index 0000000..b58b47a --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEDiffuseLighting.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FEDiffuseLighting_h +#define FEDiffuseLighting_h + +#if ENABLE(FILTERS) +#include "FELighting.h" + +namespace WebCore { + +class LightSource; + +class FEDiffuseLighting : public FELighting { +public: + static PassRefPtr<FEDiffuseLighting> create(Filter*, 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>); + + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEDiffuseLighting(Filter*, const Color&, float, float, float, float, PassRefPtr<LightSource>); +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEDiffuseLighting_h diff --git a/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp b/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp new file mode 100644 index 0000000..b5151bf --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEDisplacementMap.h" + +#include "Filter.h" +#include "GraphicsContext.h" + +#include <wtf/ByteArray.h> + +namespace WebCore { + +FEDisplacementMap::FEDisplacementMap(Filter* filter, ChannelSelectorType xChannelSelector, ChannelSelectorType yChannelSelector, float scale) + : FilterEffect(filter) + , m_xChannelSelector(xChannelSelector) + , m_yChannelSelector(yChannelSelector) + , m_scale(scale) +{ +} + +PassRefPtr<FEDisplacementMap> FEDisplacementMap::create(Filter* filter, ChannelSelectorType xChannelSelector, + ChannelSelectorType yChannelSelector, float scale) +{ + return adoptRef(new FEDisplacementMap(filter, xChannelSelector, yChannelSelector, scale)); +} + +ChannelSelectorType FEDisplacementMap::xChannelSelector() const +{ + return m_xChannelSelector; +} + +void FEDisplacementMap::setXChannelSelector(const ChannelSelectorType xChannelSelector) +{ + m_xChannelSelector = xChannelSelector; +} + +ChannelSelectorType FEDisplacementMap::yChannelSelector() const +{ + return m_yChannelSelector; +} + +void FEDisplacementMap::setYChannelSelector(const ChannelSelectorType yChannelSelector) +{ + m_yChannelSelector = yChannelSelector; +} + +float FEDisplacementMap::scale() const +{ + return m_scale; +} + +void FEDisplacementMap::setScale(float scale) +{ + m_scale = scale; +} + +void FEDisplacementMap::apply() +{ + if (hasResult()) + return; + FilterEffect* in = inputEffect(0); + FilterEffect* in2 = inputEffect(1); + in->apply(); + in2->apply(); + if (!in->hasResult() || !in2->hasResult()) + return; + + if (m_xChannelSelector == CHANNEL_UNKNOWN || m_yChannelSelector == CHANNEL_UNKNOWN) + return; + + ByteArray* dstPixelArray = createPremultipliedImageResult(); + if (!dstPixelArray) + return; + + IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); + RefPtr<ByteArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect); + + IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect()); + RefPtr<ByteArray> srcPixelArrayB = in2->asUnmultipliedImage(effectBDrawingRect); + + ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length()); + + Filter* filter = this->filter(); + IntSize paintSize = absolutePaintRect().size(); + float scaleX = filter->applyHorizontalScale(m_scale / 255); + float scaleY = filter->applyVerticalScale(m_scale / 255); + float scaleAdjustmentX = filter->applyHorizontalScale(0.5f - 0.5f * m_scale); + float scaleAdjustmentY = filter->applyVerticalScale(0.5f - 0.5f * m_scale); + int stride = paintSize.width() * 4; + for (int y = 0; y < paintSize.height(); ++y) { + int line = y * stride; + for (int x = 0; x < paintSize.width(); ++x) { + int dstIndex = line + x * 4; + int srcX = x + static_cast<int>(scaleX * srcPixelArrayB->get(dstIndex + m_xChannelSelector - 1) + scaleAdjustmentX); + int srcY = y + static_cast<int>(scaleY * srcPixelArrayB->get(dstIndex + m_yChannelSelector - 1) + scaleAdjustmentY); + for (unsigned channel = 0; channel < 4; ++channel) { + if (srcX < 0 || srcX >= paintSize.width() || srcY < 0 || srcY >= paintSize.height()) + dstPixelArray->set(dstIndex + channel, static_cast<unsigned char>(0)); + else { + unsigned char pixelValue = srcPixelArrayA->get(srcY * stride + srcX * 4 + channel); + dstPixelArray->set(dstIndex + channel, pixelValue); + } + } + } + } +} + +void FEDisplacementMap::dump() +{ +} + +static TextStream& operator<<(TextStream& ts, const ChannelSelectorType& type) +{ + 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, int indent) const +{ + writeIndent(ts, indent); + ts << "[feDisplacementMap"; + FilterEffect::externalRepresentation(ts); + ts << " scale=\"" << m_scale << "\" " + << "xChannelSelector=\"" << m_xChannelSelector << "\" " + << "yChannelSelector=\"" << m_yChannelSelector << "\"]\n"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + inputEffect(1)->externalRepresentation(ts, indent + 1); + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/FEDisplacementMap.h b/Source/WebCore/platform/graphics/filters/FEDisplacementMap.h new file mode 100644 index 0000000..ffb8f0e --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEDisplacementMap.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FEDisplacementMap_h +#define FEDisplacementMap_h + +#if ENABLE(FILTERS) +#include "PlatformString.h" +#include "FilterEffect.h" +#include "Filter.h" + +namespace WebCore { + +enum ChannelSelectorType { + CHANNEL_UNKNOWN = 0, + CHANNEL_R = 1, + CHANNEL_G = 2, + CHANNEL_B = 3, + CHANNEL_A = 4 +}; + +class FEDisplacementMap : public FilterEffect { +public: + static PassRefPtr<FEDisplacementMap> create(Filter*, ChannelSelectorType xChannelSelector, ChannelSelectorType yChannelSelector, float); + + ChannelSelectorType xChannelSelector() const; + void setXChannelSelector(const ChannelSelectorType); + + ChannelSelectorType yChannelSelector() const; + void setYChannelSelector(const ChannelSelectorType); + + float scale() const; + void setScale(float scale); + + virtual void apply(); + virtual void dump(); + + virtual void determineAbsolutePaintRect() { setAbsolutePaintRect(maxEffectRect()); } + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEDisplacementMap(Filter*, ChannelSelectorType xChannelSelector, ChannelSelectorType yChannelSelector, float); + + ChannelSelectorType m_xChannelSelector; + ChannelSelectorType m_yChannelSelector; + float m_scale; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEDisplacementMap_h diff --git a/Source/WebCore/platform/graphics/filters/FEFlood.cpp b/Source/WebCore/platform/graphics/filters/FEFlood.cpp new file mode 100644 index 0000000..8bfdef8 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEFlood.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEFlood.h" + +#include "Filter.h" +#include "GraphicsContext.h" + +namespace WebCore { + +FEFlood::FEFlood(Filter* filter, const Color& floodColor, float floodOpacity) + : FilterEffect(filter) + , m_floodColor(floodColor) + , m_floodOpacity(floodOpacity) +{ +} + +PassRefPtr<FEFlood> FEFlood::create(Filter* filter, const Color& floodColor, float floodOpacity) +{ + return adoptRef(new FEFlood(filter, floodColor, floodOpacity)); +} + +Color FEFlood::floodColor() const +{ + return m_floodColor; +} + +void FEFlood::setFloodColor(const Color& color) +{ + m_floodColor = color; +} + +float FEFlood::floodOpacity() const +{ + return m_floodOpacity; +} + +void FEFlood::setFloodOpacity(float floodOpacity) +{ + m_floodOpacity = floodOpacity; +} + +void FEFlood::apply() +{ + if (hasResult()) + return; + ImageBuffer* resultImage = createImageBufferResult(); + if (!resultImage) + return; + + Color color = colorWithOverrideAlpha(floodColor().rgb(), floodOpacity()); + resultImage->context()->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()), color, ColorSpaceDeviceRGB); +} + +void FEFlood::dump() +{ +} + +TextStream& FEFlood::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feFlood"; + FilterEffect::externalRepresentation(ts); + ts << " flood-color=\"" << floodColor().name() << "\" " + << "flood-opacity=\"" << floodOpacity() << "\"]\n"; + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/FEFlood.h b/Source/WebCore/platform/graphics/filters/FEFlood.h new file mode 100644 index 0000000..2e8824f --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEFlood.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FEFlood_h +#define FEFlood_h + +#if ENABLE(FILTERS) +#include "Color.h" +#include "Filter.h" +#include "FilterEffect.h" + +namespace WebCore { + +class FEFlood : public FilterEffect { +public: + static PassRefPtr<FEFlood> create(Filter* filter, const Color&, float); + + Color floodColor() const; + void setFloodColor(const Color &); + + float floodOpacity() const; + void setFloodOpacity(float); + + virtual void apply(); + virtual void dump(); + + virtual void determineAbsolutePaintRect() { setAbsolutePaintRect(maxEffectRect()); } + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEFlood(Filter*, const Color&, float); + + Color m_floodColor; + float m_floodOpacity; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEFlood_h diff --git a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp new file mode 100644 index 0000000..37b5992 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) 2010 Igalia, S.L. + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEGaussianBlur.h" + +#include "Filter.h" +#include "GraphicsContext.h" + +#include <wtf/ByteArray.h> +#include <wtf/MathExtras.h> + +using std::max; + +static const float gGaussianKernelFactor = 3 / 4.f * sqrtf(2 * piFloat); +static const unsigned gMaxKernelSize = 1000; + +namespace WebCore { + +FEGaussianBlur::FEGaussianBlur(Filter* filter, float x, float y) + : FilterEffect(filter) + , m_stdX(x) + , m_stdY(y) +{ +} + +PassRefPtr<FEGaussianBlur> FEGaussianBlur::create(Filter* filter, float x, float y) +{ + return adoptRef(new FEGaussianBlur(filter, x, y)); +} + +float FEGaussianBlur::stdDeviationX() const +{ + return m_stdX; +} + +void FEGaussianBlur::setStdDeviationX(float x) +{ + m_stdX = x; +} + +float FEGaussianBlur::stdDeviationY() const +{ + return m_stdY; +} + +void FEGaussianBlur::setStdDeviationY(float y) +{ + m_stdY = y; +} + +inline void boxBlur(ByteArray* srcPixelArray, ByteArray* dstPixelArray, + unsigned dx, int dxLeft, int dxRight, int stride, int strideLine, int effectWidth, int effectHeight, bool alphaImage) +{ + for (int y = 0; y < effectHeight; ++y) { + int line = y * strideLine; + for (int channel = 3; channel >= 0; --channel) { + int sum = 0; + // Fill the kernel + int maxKernelSize = std::min(dxRight, effectWidth); + for (int i = 0; i < maxKernelSize; ++i) + sum += srcPixelArray->get(line + i * stride + channel); + + // Blurring + for (int x = 0; x < effectWidth; ++x) { + int pixelByteOffset = line + x * stride + channel; + dstPixelArray->set(pixelByteOffset, static_cast<unsigned char>(sum / dx)); + if (x >= dxLeft) + sum -= srcPixelArray->get(pixelByteOffset - dxLeft * stride); + if (x + dxRight < effectWidth) + sum += srcPixelArray->get(pixelByteOffset + dxRight * stride); + } + if (alphaImage) // Source image is black, it just has different alpha values + break; + } + } +} + +inline void kernelPosition(int boxBlur, unsigned& std, int& dLeft, int& dRight) +{ + // check http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement for details + switch (boxBlur) { + case 0: + if (!(std % 2)) { + dLeft = std / 2 - 1; + dRight = std - dLeft; + } else { + dLeft = std / 2; + dRight = std - dLeft; + } + break; + case 1: + if (!(std % 2)) { + dLeft++; + dRight--; + } + break; + case 2: + if (!(std % 2)) { + dRight++; + std++; + } + break; + } +} + +inline void calculateKernelSize(Filter* filter, unsigned& kernelSizeX, unsigned& kernelSizeY, float stdX, float stdY) +{ + stdX = filter->applyHorizontalScale(stdX); + stdY = filter->applyVerticalScale(stdY); + + kernelSizeX = 0; + if (stdX) + kernelSizeX = max<unsigned>(2, static_cast<unsigned>(floorf(stdX * gGaussianKernelFactor + 0.5f))); + kernelSizeY = 0; + if (stdY) + kernelSizeY = max<unsigned>(2, static_cast<unsigned>(floorf(stdY * gGaussianKernelFactor + 0.5f))); + + // Limit the kernel size to 1000. A bigger radius won't make a big difference for the result image but + // inflates the absolute paint rect to much. This is compatible with Firefox' behavior. + if (kernelSizeX > gMaxKernelSize) + kernelSizeX = gMaxKernelSize; + if (kernelSizeY > gMaxKernelSize) + kernelSizeY = gMaxKernelSize; +} + +void FEGaussianBlur::determineAbsolutePaintRect() +{ + FloatRect absolutePaintRect = inputEffect(0)->absolutePaintRect(); + absolutePaintRect.intersect(maxEffectRect()); + + unsigned kernelSizeX = 0; + unsigned kernelSizeY = 0; + calculateKernelSize(filter(), kernelSizeX, kernelSizeY, m_stdX, m_stdY); + + // We take the half kernel size and multiply it with three, because we run box blur three times. + absolutePaintRect.inflateX(3 * kernelSizeX * 0.5f); + absolutePaintRect.inflateY(3 * kernelSizeY * 0.5f); + setAbsolutePaintRect(enclosingIntRect(absolutePaintRect)); +} + +void FEGaussianBlur::apply() +{ + if (hasResult()) + return; + FilterEffect* in = inputEffect(0); + in->apply(); + if (!in->hasResult()) + return; + + ByteArray* srcPixelArray = createPremultipliedImageResult(); + if (!srcPixelArray) + return; + + setIsAlphaImage(in->isAlphaImage()); + + IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); + in->copyPremultipliedImage(srcPixelArray, effectDrawingRect); + + if (!m_stdX && !m_stdY) + return; + + unsigned kernelSizeX = 0; + unsigned kernelSizeY = 0; + calculateKernelSize(filter(), kernelSizeX, kernelSizeY, m_stdX, m_stdY); + + IntSize paintSize = absolutePaintRect().size(); + RefPtr<ByteArray> tmpImageData = ByteArray::create(paintSize.width() * paintSize.height() * 4); + ByteArray* tmpPixelArray = tmpImageData.get(); + + int stride = 4 * paintSize.width(); + int dxLeft = 0; + int dxRight = 0; + int dyLeft = 0; + int dyRight = 0; + for (int i = 0; i < 3; ++i) { + if (kernelSizeX) { + kernelPosition(i, kernelSizeX, dxLeft, dxRight); + boxBlur(srcPixelArray, tmpPixelArray, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height(), isAlphaImage()); + } else { + ByteArray* auxPixelArray = tmpPixelArray; + tmpPixelArray = srcPixelArray; + srcPixelArray = auxPixelArray; + } + + if (kernelSizeY) { + kernelPosition(i, kernelSizeY, dyLeft, dyRight); + boxBlur(tmpPixelArray, srcPixelArray, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width(), isAlphaImage()); + } else { + ByteArray* auxPixelArray = tmpPixelArray; + tmpPixelArray = srcPixelArray; + srcPixelArray = auxPixelArray; + } + } +} + +void FEGaussianBlur::dump() +{ +} + +TextStream& FEGaussianBlur::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feGaussianBlur"; + FilterEffect::externalRepresentation(ts); + ts << " stdDeviation=\"" << m_stdX << ", " << m_stdY << "\"]\n"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + return ts; +} + +float FEGaussianBlur::calculateStdDeviation(float radius) +{ + // Blur radius represents 2/3 times the kernel size, the dest pixel is half of the radius applied 3 times + return max((radius * 2 / 3.f - 0.5f) / gGaussianKernelFactor, 0.f); +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h new file mode 100644 index 0000000..79f9a45 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FEGaussianBlur_h +#define FEGaussianBlur_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" +#include "Filter.h" + +namespace WebCore { + +class FEGaussianBlur : public FilterEffect { +public: + static PassRefPtr<FEGaussianBlur> create(Filter*, float, float); + + float stdDeviationX() const; + void setStdDeviationX(float); + + float stdDeviationY() const; + void setStdDeviationY(float); + + static float calculateStdDeviation(float); + + virtual void apply(); + virtual void dump(); + + virtual void determineAbsolutePaintRect(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEGaussianBlur(Filter*, float, float); + + float m_stdX; + float m_stdY; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEGaussianBlur_h diff --git a/Source/WebCore/platform/graphics/filters/FELighting.cpp b/Source/WebCore/platform/graphics/filters/FELighting.cpp new file mode 100644 index 0000000..ec1ca88 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FELighting.cpp @@ -0,0 +1,359 @@ +/* + * Copyright (C) 2010 University of Szeged + * Copyright (C) 2010 Zoltan Herczeg + * + * 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(FILTERS) +#include "FELighting.h" + +#include "LightSource.h" + +namespace WebCore { + +FELighting::FELighting(Filter* filter, LightingType lightingType, const Color& lightingColor, float surfaceScale, + float diffuseConstant, float specularConstant, float specularExponent, + float kernelUnitLengthX, float kernelUnitLengthY, PassRefPtr<LightSource> lightSource) + : FilterEffect(filter) + , m_lightingType(lightingType) + , 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); +const static float cFactor1div2 = -1 / 2.f; +const static float cFactor1div3 = -1 / 3.f; +const static float cFactor1div4 = -1 / 4.f; +const static float cFactor2div3 = -2 / 3.f; + +// << 1 is signed multiply by 2 +inline void FELighting::LightingData::topLeft(int offset, IntPoint& normalVector) +{ + int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + offset += widthMultipliedByPixelSize; + int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + normalVector.setX(-(center << 1) + (right << 1) - bottom + bottomRight); + normalVector.setY(-(center << 1) - right + (bottom << 1) + bottomRight); +} + +inline void FELighting::LightingData::topRow(int offset, IntPoint& normalVector) +{ + int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + offset += widthMultipliedByPixelSize; + int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + normalVector.setX(-(left << 1) + (right << 1) - bottomLeft + bottomRight); + normalVector.setY(-left - (center << 1) - right + bottomLeft + (bottom << 1) + bottomRight); +} + +inline void FELighting::LightingData::topRight(int offset, IntPoint& normalVector) +{ + int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + offset += widthMultipliedByPixelSize; + int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + normalVector.setX(-(left << 1) + (center << 1) - bottomLeft + bottom); + normalVector.setY(-left - (center << 1) + bottomLeft + (bottom << 1)); +} + +inline void FELighting::LightingData::leftColumn(int offset, IntPoint& normalVector) +{ + int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + offset -= widthMultipliedByPixelSize; + int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + offset += widthMultipliedByPixelSize << 1; + int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + normalVector.setX(-top + topRight - (center << 1) + (right << 1) - bottom + bottomRight); + normalVector.setY(-(top << 1) - topRight + (bottom << 1) + bottomRight); +} + +inline void FELighting::LightingData::interior(int offset, IntPoint& normalVector) +{ + int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + offset -= widthMultipliedByPixelSize; + int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + offset += widthMultipliedByPixelSize << 1; + int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + normalVector.setX(-topLeft + topRight - (left << 1) + (right << 1) - bottomLeft + bottomRight); + normalVector.setY(-topLeft - (top << 1) - topRight + bottomLeft + (bottom << 1) + bottomRight); +} + +inline void FELighting::LightingData::rightColumn(int offset, IntPoint& normalVector) +{ + int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + offset -= widthMultipliedByPixelSize; + int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + offset += widthMultipliedByPixelSize << 1; + int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + normalVector.setX(-topLeft + top - (left << 1) + (center << 1) - bottomLeft + bottom); + normalVector.setY(-topLeft - (top << 1) + bottomLeft + (bottom << 1)); +} + +inline void FELighting::LightingData::bottomLeft(int offset, IntPoint& normalVector) +{ + int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + offset -= widthMultipliedByPixelSize; + int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + normalVector.setX(-top + topRight - (center << 1) + (right << 1)); + normalVector.setY(-(top << 1) - topRight + (center << 1) + right); +} + +inline void FELighting::LightingData::bottomRow(int offset, IntPoint& normalVector) +{ + int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + offset -= widthMultipliedByPixelSize; + int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); + normalVector.setX(-topLeft + topRight - (left << 1) + (right << 1)); + normalVector.setY(-topLeft - (top << 1) - topRight + left + (center << 1) + right); +} + +inline void FELighting::LightingData::bottomRight(int offset, IntPoint& normalVector) +{ + int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + offset -= widthMultipliedByPixelSize; + int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); + int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); + normalVector.setX(-topLeft + top - (left << 1) + (center << 1)); + normalVector.setY(-topLeft - (top << 1) + left + (center << 1)); +} + +inline void FELighting::inlineSetPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData, + int lightX, int lightY, float factorX, float factorY, IntPoint& normal2DVector) +{ + m_lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->get(offset + cAlphaChannelOffset)) * data.surfaceScale); + + float lightStrength; + if (!normal2DVector.x() && !normal2DVector.y()) { + // Normal vector is (0, 0, 1). This is a quite frequent case. + if (m_lightingType == FELighting::DiffuseLighting) + lightStrength = m_diffuseConstant * paintingData.lightVector.z() / paintingData.lightVectorLength; + else { + FloatPoint3D halfwayVector = paintingData.lightVector; + halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength); + float halfwayVectorLength = halfwayVector.length(); + if (m_specularExponent == 1) + lightStrength = m_specularConstant * halfwayVector.z() / halfwayVectorLength; + else + lightStrength = m_specularConstant * powf(halfwayVector.z() / halfwayVectorLength, m_specularExponent); + } + } else { + FloatPoint3D normalVector; + normalVector.setX(factorX * static_cast<float>(normal2DVector.x()) * data.surfaceScale); + normalVector.setY(factorY * static_cast<float>(normal2DVector.y()) * data.surfaceScale); + normalVector.setZ(1); + float normalVectorLength = normalVector.length(); + + if (m_lightingType == FELighting::DiffuseLighting) + lightStrength = m_diffuseConstant * (normalVector * paintingData.lightVector) / (normalVectorLength * paintingData.lightVectorLength); + else { + FloatPoint3D halfwayVector = paintingData.lightVector; + halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength); + float halfwayVectorLength = halfwayVector.length(); + if (m_specularExponent == 1) + lightStrength = m_specularConstant * (normalVector * halfwayVector) / (normalVectorLength * halfwayVectorLength); + else + lightStrength = m_specularConstant * powf((normalVector * halfwayVector) / (normalVectorLength * halfwayVectorLength), m_specularExponent); + } + } + + if (lightStrength > 1) + lightStrength = 1; + if (lightStrength < 0) + lightStrength = 0; + + data.pixels->set(offset, static_cast<unsigned char>(lightStrength * paintingData.colorVector.x())); + data.pixels->set(offset + 1, static_cast<unsigned char>(lightStrength * paintingData.colorVector.y())); + data.pixels->set(offset + 2, static_cast<unsigned char>(lightStrength * paintingData.colorVector.z())); +} + +void FELighting::setPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData, + int lightX, int lightY, float factorX, float factorY, IntPoint& normalVector) +{ + inlineSetPixel(offset, data, paintingData, lightX, lightY, factorX, factorY, normalVector); +} + +bool FELighting::drawLighting(ByteArray* 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 + IntPoint normalVector; + int offset = 0; + data.topLeft(offset, normalVector); + setPixel(offset, data, paintingData, 0, 0, cFactor2div3, cFactor2div3, normalVector); + + // Top/Right pixel + offset = data.widthMultipliedByPixelSize - cPixelSize; + data.topRight(offset, normalVector); + setPixel(offset, data, paintingData, data.widthDecreasedByOne, 0, cFactor2div3, cFactor2div3, normalVector); + + // Bottom/Left pixel + offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize; + data.bottomLeft(offset, normalVector); + setPixel(offset, data, paintingData, 0, data.heightDecreasedByOne, cFactor2div3, cFactor2div3, normalVector); + + // Bottom/Right pixel + offset = height * data.widthMultipliedByPixelSize - cPixelSize; + data.bottomRight(offset, normalVector); + setPixel(offset, data, paintingData, data.widthDecreasedByOne, data.heightDecreasedByOne, cFactor2div3, cFactor2div3, normalVector); + + if (width >= 3) { + // Top row + offset = cPixelSize; + for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize) { + data.topRow(offset, normalVector); + inlineSetPixel(offset, data, paintingData, x, 0, cFactor1div3, cFactor1div2, normalVector); + } + // Bottom row + offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize + cPixelSize; + for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize) { + data.bottomRow(offset, normalVector); + inlineSetPixel(offset, data, paintingData, x, data.heightDecreasedByOne, cFactor1div3, cFactor1div2, normalVector); + } + } + + if (height >= 3) { + // Left column + offset = data.widthMultipliedByPixelSize; + for (int y = 1; y < data.heightDecreasedByOne; ++y, offset += data.widthMultipliedByPixelSize) { + data.leftColumn(offset, normalVector); + inlineSetPixel(offset, data, paintingData, 0, y, cFactor1div2, cFactor1div3, normalVector); + } + // Right column + offset = (data.widthMultipliedByPixelSize << 1) - cPixelSize; + for (int y = 1; y < data.heightDecreasedByOne; ++y, offset += data.widthMultipliedByPixelSize) { + data.rightColumn(offset, normalVector); + inlineSetPixel(offset, data, paintingData, data.widthDecreasedByOne, y, cFactor1div2, cFactor1div3, normalVector); + } + } + + if (width >= 3 && height >= 3) { + // Interior pixels + for (int y = 1; y < data.heightDecreasedByOne; ++y) { + offset = y * data.widthMultipliedByPixelSize + cPixelSize; + for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize) { + data.interior(offset, normalVector); + inlineSetPixel(offset, data, paintingData, x, y, cFactor1div4, cFactor1div4, normalVector); + } + } + } + + int lastPixel = data.widthMultipliedByPixelSize * height; + if (m_lightingType == DiffuseLighting) { + for (int i = cAlphaChannelOffset; i < lastPixel; i += cPixelSize) + data.pixels->set(i, cOpaqueAlpha); + } else { + for (int i = 0; i < lastPixel; i += cPixelSize) { + 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() +{ + if (hasResult()) + return; + FilterEffect* in = inputEffect(0); + in->apply(); + if (!in->hasResult()) + return; + + ByteArray* srcPixelArray = createUnmultipliedImageResult(); + if (!srcPixelArray) + return; + + setIsAlphaImage(false); + + IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); + in->copyUnmultipliedImage(srcPixelArray, effectDrawingRect); + + // 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 + + IntSize absolutePaintSize = absolutePaintRect().size(); + drawLighting(srcPixelArray, absolutePaintSize.width(), absolutePaintSize.height()); +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/FELighting.h b/Source/WebCore/platform/graphics/filters/FELighting.h new file mode 100644 index 0000000..fa1c0aa --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FELighting.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2010 University of Szeged + * Copyright (C) 2010 Zoltan Herczeg + * + * 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 FELighting_h +#define FELighting_h + +#if ENABLE(FILTERS) +#include "Color.h" +#include "Filter.h" +#include "FilterEffect.h" +#include "LightSource.h" +#include <wtf/ByteArray.h> + +// Common base class for FEDiffuseLighting and FESpecularLighting + +namespace WebCore { + +class FELighting : public FilterEffect { +public: + virtual void apply(); + + virtual void determineAbsolutePaintRect() { setAbsolutePaintRect(maxEffectRect()); } + +protected: + enum LightingType { + DiffuseLighting, + SpecularLighting + }; + + struct LightingData { + // This structure contains only read-only (SMP safe) data + ByteArray* pixels; + float surfaceScale; + int widthMultipliedByPixelSize; + int widthDecreasedByOne; + int heightDecreasedByOne; + + inline void topLeft(int offset, IntPoint& normalVector); + inline void topRow(int offset, IntPoint& normalVector); + inline void topRight(int offset, IntPoint& normalVector); + inline void leftColumn(int offset, IntPoint& normalVector); + inline void interior(int offset, IntPoint& normalVector); + inline void rightColumn(int offset, IntPoint& normalVector); + inline void bottomLeft(int offset, IntPoint& normalVector); + inline void bottomRow(int offset, IntPoint& normalVector); + inline void bottomRight(int offset, IntPoint& normalVector); + }; + + FELighting(Filter*, LightingType, const Color&, float, float, float, float, float, float, PassRefPtr<LightSource>); + + bool drawLighting(ByteArray*, int, int); + inline void inlineSetPixel(int offset, LightingData&, LightSource::PaintingData&, + int lightX, int lightY, float factorX, float factorY, IntPoint& normalVector); + + // Not worth to inline every occurence of setPixel. + void setPixel(int offset, LightingData&, LightSource::PaintingData&, + int lightX, int lightY, float factorX, float factorY, IntPoint& normalVector); + + LightingType m_lightingType; + 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(FILTERS) + +#endif // FELighting_h diff --git a/Source/WebCore/platform/graphics/filters/FEMerge.cpp b/Source/WebCore/platform/graphics/filters/FEMerge.cpp new file mode 100644 index 0000000..4395321 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEMerge.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEMerge.h" + +#include "Filter.h" +#include "GraphicsContext.h" + +namespace WebCore { + +FEMerge::FEMerge(Filter* filter) + : FilterEffect(filter) +{ +} + +PassRefPtr<FEMerge> FEMerge::create(Filter* filter) +{ + return adoptRef(new FEMerge(filter)); +} + +void FEMerge::apply() +{ + if (hasResult()) + return; + unsigned size = numberOfEffectInputs(); + ASSERT(size > 0); + for (unsigned i = 0; i < size; ++i) { + FilterEffect* in = inputEffect(i); + in->apply(); + if (!in->hasResult()) + return; + } + + ImageBuffer* resultImage = createImageBufferResult(); + if (!resultImage) + return; + + GraphicsContext* filterContext = resultImage->context(); + for (unsigned i = 0; i < size; ++i) { + FilterEffect* in = inputEffect(i); + filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect())); + } +} + +void FEMerge::dump() +{ +} + +TextStream& FEMerge::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feMerge"; + FilterEffect::externalRepresentation(ts); + unsigned size = numberOfEffectInputs(); + ASSERT(size > 0); + ts << " mergeNodes=\"" << size << "\"]\n"; + for (unsigned i = 0; i < size; ++i) + inputEffect(i)->externalRepresentation(ts, indent + 1); + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/FEMerge.h b/Source/WebCore/platform/graphics/filters/FEMerge.h new file mode 100644 index 0000000..dbee610 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEMerge.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FEMerge_h +#define FEMerge_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" +#include "Filter.h" +#include <wtf/Vector.h> + +namespace WebCore { + +class FEMerge : public FilterEffect { +public: + static PassRefPtr<FEMerge> create(Filter*); + + virtual void apply(); + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEMerge(Filter*); +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEMerge_h diff --git a/Source/WebCore/platform/graphics/filters/FEMorphology.cpp b/Source/WebCore/platform/graphics/filters/FEMorphology.cpp new file mode 100644 index 0000000..45c7edb --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEMorphology.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEMorphology.h" + +#include "Filter.h" + +#include <wtf/ByteArray.h> +#include <wtf/Vector.h> + +using std::min; +using std::max; + +namespace WebCore { + +FEMorphology::FEMorphology(Filter* filter, MorphologyOperatorType type, float radiusX, float radiusY) + : FilterEffect(filter) + , m_type(type) + , m_radiusX(radiusX) + , m_radiusY(radiusY) +{ +} + +PassRefPtr<FEMorphology> FEMorphology::create(Filter* filter, MorphologyOperatorType type, float radiusX, float radiusY) +{ + return adoptRef(new FEMorphology(filter, type, radiusX, radiusY)); +} + +MorphologyOperatorType FEMorphology::morphologyOperator() const +{ + return m_type; +} + +void FEMorphology::setMorphologyOperator(MorphologyOperatorType type) +{ + m_type = type; +} + +float FEMorphology::radiusX() const +{ + return m_radiusX; +} + +void FEMorphology::setRadiusX(float radiusX) +{ + m_radiusX = radiusX; +} + +float FEMorphology::radiusY() const +{ + return m_radiusY; +} + +void FEMorphology::determineAbsolutePaintRect() +{ + FloatRect paintRect = inputEffect(0)->absolutePaintRect(); + Filter* filter = this->filter(); + paintRect.inflateX(filter->applyHorizontalScale(m_radiusX)); + paintRect.inflateY(filter->applyVerticalScale(m_radiusY)); + paintRect.intersect(maxEffectRect()); + setAbsolutePaintRect(enclosingIntRect(paintRect)); +} + +void FEMorphology::setRadiusY(float radiusY) +{ + m_radiusY = radiusY; +} + +void FEMorphology::apply() +{ + if (hasResult()) + return; + FilterEffect* in = inputEffect(0); + in->apply(); + if (!in->hasResult()) + return; + + ByteArray* dstPixelArray = createPremultipliedImageResult(); + if (!dstPixelArray) + return; + + setIsAlphaImage(in->isAlphaImage()); + if (m_radiusX <= 0 || m_radiusY <= 0) + return; + + Filter* filter = this->filter(); + int radiusX = static_cast<int>(floorf(filter->applyHorizontalScale(m_radiusX))); + int radiusY = static_cast<int>(floorf(filter->applyVerticalScale(m_radiusY))); + + IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); + RefPtr<ByteArray> srcPixelArray = in->asPremultipliedImage(effectDrawingRect); + + int effectWidth = effectDrawingRect.width() * 4; + + // Limit the radius size to effect dimensions + radiusX = min(effectDrawingRect.width() - 1, radiusX); + radiusY = min(effectDrawingRect.height() - 1, radiusY); + + Vector<unsigned char> extrema; + for (int y = 0; y < effectDrawingRect.height(); ++y) { + int startY = max(0, y - radiusY); + int endY = min(effectDrawingRect.height() - 1, y + radiusY); + for (unsigned channel = 0; channel < 4; ++channel) { + // Fill the kernel + extrema.clear(); + for (int j = 0; j <= radiusX; ++j) { + unsigned char columnExtrema = srcPixelArray->get(startY * effectWidth + 4 * j + channel); + for (int i = startY; i <= endY; ++i) { + unsigned char pixel = srcPixelArray->get(i * effectWidth + 4 * j + channel); + if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && pixel <= columnExtrema) || + (m_type == FEMORPHOLOGY_OPERATOR_DILATE && pixel >= columnExtrema)) + columnExtrema = pixel; + } + extrema.append(columnExtrema); + } + + // Kernel is filled, get extrema of next column + for (int x = 0; x < effectDrawingRect.width(); ++x) { + unsigned endX = min(x + radiusX, effectDrawingRect.width() - 1); + unsigned char columnExtrema = srcPixelArray->get(startY * effectWidth + endX * 4 + channel); + for (int i = startY; i <= endY; ++i) { + unsigned char pixel = srcPixelArray->get(i * effectWidth + endX * 4 + channel); + if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && pixel <= columnExtrema) || + (m_type == FEMORPHOLOGY_OPERATOR_DILATE && pixel >= columnExtrema)) + columnExtrema = pixel; + } + if (x - radiusX >= 0) + extrema.remove(0); + if (x + radiusX <= effectDrawingRect.width()) + extrema.append(columnExtrema); + unsigned char entireExtrema = extrema[0]; + for (unsigned kernelIndex = 0; kernelIndex < extrema.size(); ++kernelIndex) { + if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && extrema[kernelIndex] <= entireExtrema) || + (m_type == FEMORPHOLOGY_OPERATOR_DILATE && extrema[kernelIndex] >= entireExtrema)) + entireExtrema = extrema[kernelIndex]; + } + dstPixelArray->set(y * effectWidth + 4 * x + channel, entireExtrema); + } + } + } +} + +void FEMorphology::dump() +{ +} + +static TextStream& operator<<(TextStream& ts, const MorphologyOperatorType& type) +{ + 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, int indent) const +{ + writeIndent(ts, indent); + ts << "[feMorphology"; + FilterEffect::externalRepresentation(ts); + ts << " operator=\"" << morphologyOperator() << "\" " + << "radius=\"" << radiusX() << ", " << radiusY() << "\"]\n"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/FEMorphology.h b/Source/WebCore/platform/graphics/filters/FEMorphology.h new file mode 100644 index 0000000..683e7d0 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEMorphology.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FEMorphology_h +#define FEMorphology_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" +#include "Filter.h" + +namespace WebCore { + +enum MorphologyOperatorType { + FEMORPHOLOGY_OPERATOR_UNKNOWN = 0, + FEMORPHOLOGY_OPERATOR_ERODE = 1, + FEMORPHOLOGY_OPERATOR_DILATE = 2 +}; + +class FEMorphology : public FilterEffect { +public: + static PassRefPtr<FEMorphology> create(Filter*, MorphologyOperatorType, float radiusX, float radiusY); + MorphologyOperatorType morphologyOperator() const; + void setMorphologyOperator(MorphologyOperatorType); + + float radiusX() const; + void setRadiusX(float); + + float radiusY() const; + void setRadiusY(float); + + virtual void apply(); + virtual void dump(); + + virtual void determineAbsolutePaintRect(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEMorphology(Filter*, MorphologyOperatorType, float radiusX, float radiusY); + + MorphologyOperatorType m_type; + float m_radiusX; + float m_radiusY; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEMorphology_h diff --git a/Source/WebCore/platform/graphics/filters/FEOffset.cpp b/Source/WebCore/platform/graphics/filters/FEOffset.cpp new file mode 100644 index 0000000..f1d5914 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEOffset.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FEOffset.h" + +#include "Filter.h" +#include "GraphicsContext.h" + +namespace WebCore { + +FEOffset::FEOffset(Filter* filter, float dx, float dy) + : FilterEffect(filter) + , m_dx(dx) + , m_dy(dy) +{ +} + +PassRefPtr<FEOffset> FEOffset::create(Filter* filter, float dx, float dy) +{ + return adoptRef(new FEOffset(filter, dx, dy)); +} + +float FEOffset::dx() const +{ + return m_dx; +} + +void FEOffset::setDx(float dx) +{ + m_dx = dx; +} + +float FEOffset::dy() const +{ + return m_dy; +} + +void FEOffset::setDy(float dy) +{ + m_dy = dy; +} + +void FEOffset::determineAbsolutePaintRect() +{ + FloatRect paintRect = inputEffect(0)->absolutePaintRect(); + Filter* filter = this->filter(); + paintRect.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy)); + paintRect.intersect(maxEffectRect()); + setAbsolutePaintRect(enclosingIntRect(paintRect)); +} + +void FEOffset::apply() +{ + if (hasResult()) + return; + FilterEffect* in = inputEffect(0); + in->apply(); + if (!in->hasResult()) + return; + + ImageBuffer* resultImage = createImageBufferResult(); + if (!resultImage) + return; + + setIsAlphaImage(in->isAlphaImage()); + + FloatRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect()); + Filter* filter = this->filter(); + drawingRegion.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy)); + resultImage->context()->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegion); +} + +void FEOffset::dump() +{ +} + +TextStream& FEOffset::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feOffset"; + FilterEffect::externalRepresentation(ts); + ts << " dx=\"" << dx() << "\" dy=\"" << dy() << "\"]\n"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/FEOffset.h b/Source/WebCore/platform/graphics/filters/FEOffset.h new file mode 100644 index 0000000..5aa5c38 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FEOffset.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FEOffset_h +#define FEOffset_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" +#include "Filter.h" + +namespace WebCore { + +class FEOffset : public FilterEffect { +public: + static PassRefPtr<FEOffset> create(Filter*, float dx, float dy); + + float dx() const; + void setDx(float); + + float dy() const; + void setDy(float); + + virtual void apply(); + virtual void dump(); + + virtual void determineAbsolutePaintRect(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FEOffset(Filter*, float dx, float dy); + + float m_dx; + float m_dy; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FEOffset_h diff --git a/Source/WebCore/platform/graphics/filters/FESpecularLighting.cpp b/Source/WebCore/platform/graphics/filters/FESpecularLighting.cpp new file mode 100644 index 0000000..d21dafd --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FESpecularLighting.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FESpecularLighting.h" + +#include "LightSource.h" + +namespace WebCore { + +FESpecularLighting::FESpecularLighting(Filter* filter, const Color& lightingColor, float surfaceScale, + float specularConstant, float specularExponent, float kernelUnitLengthX, + float kernelUnitLengthY, PassRefPtr<LightSource> lightSource) + : FELighting(filter, SpecularLighting, lightingColor, surfaceScale, 0, specularConstant, specularExponent, kernelUnitLengthX, kernelUnitLengthY, lightSource) +{ +} + +PassRefPtr<FESpecularLighting> FESpecularLighting::create(Filter* filter, const Color& lightingColor, + float surfaceScale, float specularConstant, float specularExponent, + float kernelUnitLengthX, float kernelUnitLengthY, PassRefPtr<LightSource> lightSource) +{ + return adoptRef(new FESpecularLighting(filter, lightingColor, surfaceScale, specularConstant, specularExponent, + kernelUnitLengthX, kernelUnitLengthY, lightSource)); +} + +FESpecularLighting::~FESpecularLighting() +{ +} + +Color FESpecularLighting::lightingColor() const +{ + return m_lightingColor; +} + +void FESpecularLighting::setLightingColor(const Color& lightingColor) +{ + m_lightingColor = lightingColor; +} + +float FESpecularLighting::surfaceScale() const +{ + return m_surfaceScale; +} + +void FESpecularLighting::setSurfaceScale(float surfaceScale) +{ + m_surfaceScale = surfaceScale; +} + +float FESpecularLighting::specularConstant() const +{ + return m_specularConstant; +} + +void FESpecularLighting::setSpecularConstant(float specularConstant) +{ + m_specularConstant = specularConstant; +} + +float FESpecularLighting::specularExponent() const +{ + return m_specularExponent; +} + +void FESpecularLighting::setSpecularExponent(float specularExponent) +{ + m_specularExponent = specularExponent; +} + +float FESpecularLighting::kernelUnitLengthX() const +{ + return m_kernelUnitLengthX; +} + +void FESpecularLighting::setKernelUnitLengthX(float kernelUnitLengthX) +{ + m_kernelUnitLengthX = kernelUnitLengthX; +} + +float FESpecularLighting::kernelUnitLengthY() const +{ + return m_kernelUnitLengthY; +} + +void FESpecularLighting::setKernelUnitLengthY(float kernelUnitLengthY) +{ + m_kernelUnitLengthY = kernelUnitLengthY; +} + +const LightSource* FESpecularLighting::lightSource() const +{ + return m_lightSource.get(); +} + +void FESpecularLighting::setLightSource(PassRefPtr<LightSource> lightSource) +{ + m_lightSource = lightSource; +} + +void FESpecularLighting::dump() +{ +} + +TextStream& FESpecularLighting::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feSpecularLighting"; + FilterEffect::externalRepresentation(ts); + ts << " surfaceScale=\"" << m_surfaceScale << "\" " + << "specualConstant=\"" << m_specularConstant << "\" " + << "specularExponent=\"" << m_specularExponent << "\"]\n"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/FESpecularLighting.h b/Source/WebCore/platform/graphics/filters/FESpecularLighting.h new file mode 100644 index 0000000..b3ccfbc --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FESpecularLighting.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FESpecularLighting_h +#define FESpecularLighting_h + +#if ENABLE(FILTERS) +#include "FELighting.h" + +namespace WebCore { + +class FESpecularLighting : public FELighting { +public: + static PassRefPtr<FESpecularLighting> create(Filter*, const Color&, float, float, + float, float, float, PassRefPtr<LightSource>); + virtual ~FESpecularLighting(); + + Color lightingColor() const; + void setLightingColor(const Color&); + + float surfaceScale() const; + void setSurfaceScale(float); + + float specularConstant() const; + void setSpecularConstant(float); + + float specularExponent() const; + void setSpecularExponent(float); + + float kernelUnitLengthX() const; + void setKernelUnitLengthX(float); + + float kernelUnitLengthY() const; + void setKernelUnitLengthY(float); + + const LightSource* lightSource() const; + void setLightSource(PassRefPtr<LightSource>); + + virtual void dump(); + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FESpecularLighting(Filter*, const Color&, float, float, float, float, float, PassRefPtr<LightSource>); +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FESpecularLighting_h diff --git a/Source/WebCore/platform/graphics/filters/FETile.cpp b/Source/WebCore/platform/graphics/filters/FETile.cpp new file mode 100644 index 0000000..e516c7e --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FETile.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FETile.h" + +#include "AffineTransform.h" +#include "Filter.h" +#include "GraphicsContext.h" +#include "Pattern.h" +#include "SVGImageBufferTools.h" + +namespace WebCore { + +FETile::FETile(Filter* filter) + : FilterEffect(filter) +{ +} + +PassRefPtr<FETile> FETile::create(Filter* filter) +{ + return adoptRef(new FETile(filter)); +} + +void FETile::apply() +{ +// FIXME: See bug 47315. This is a hack to work around a compile failure, but is incorrect behavior otherwise. +#if ENABLE(SVG) + if (hasResult()) + return; + FilterEffect* in = inputEffect(0); + in->apply(); + if (!in->hasResult()) + return; + + ImageBuffer* resultImage = createImageBufferResult(); + if (!resultImage) + return; + + setIsAlphaImage(in->isAlphaImage()); + + // Source input needs more attention. It has the size of the filterRegion but gives the + // size of the cutted sourceImage back. This is part of the specification and optimization. + FloatRect tileRect = in->maxEffectRect(); + FloatPoint inMaxEffectLocation = tileRect.location(); + FloatPoint maxEffectLocation = maxEffectRect().location(); + if (in->filterEffectType() == FilterEffectTypeSourceInput) { + Filter* filter = this->filter(); + tileRect = filter->filterRegion(); + tileRect.scale(filter->filterResolution().width(), filter->filterResolution().height()); + } + + OwnPtr<ImageBuffer> tileImage; + if (!SVGImageBufferTools::createImageBuffer(tileRect, tileRect, tileImage, ColorSpaceDeviceRGB)) + return; + + GraphicsContext* tileImageContext = tileImage->context(); + tileImageContext->translate(-inMaxEffectLocation.x(), -inMaxEffectLocation.y()); + tileImageContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, in->absolutePaintRect().location()); + + RefPtr<Pattern> pattern = Pattern::create(tileImage->copyImage(), true, true); + + AffineTransform patternTransform; + patternTransform.translate(inMaxEffectLocation.x() - maxEffectLocation.x(), inMaxEffectLocation.y() - maxEffectLocation.y()); + pattern->setPatternSpaceTransform(patternTransform); + GraphicsContext* filterContext = resultImage->context(); + filterContext->setFillPattern(pattern); + filterContext->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size())); +#endif +} + +void FETile::dump() +{ +} + +TextStream& FETile::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[feTile"; + FilterEffect::externalRepresentation(ts); + ts << "]\n"; + inputEffect(0)->externalRepresentation(ts, indent + 1); + + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/FETile.h b/Source/WebCore/platform/graphics/filters/FETile.h new file mode 100644 index 0000000..9b02b4c --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FETile.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FETile_h +#define FETile_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" +#include "Filter.h" + +namespace WebCore { + +class FETile : public FilterEffect { +public: + static PassRefPtr<FETile> create(Filter* filter); + + virtual void apply(); + virtual void dump(); + + virtual void determineAbsolutePaintRect() { setAbsolutePaintRect(maxEffectRect()); } + + virtual FilterEffectType filterEffectType() const { return FilterEffectTypeTile; } + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + FETile(Filter*); +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FETile_h diff --git a/Source/WebCore/platform/graphics/filters/FETurbulence.cpp b/Source/WebCore/platform/graphics/filters/FETurbulence.cpp new file mode 100644 index 0000000..f1a159b --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FETurbulence.cpp @@ -0,0 +1,385 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) 2010 Renata Hodovan <reni@inf.u-szeged.hu> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FETurbulence.h" + +#include "Filter.h" + +#include <wtf/ByteArray.h> +#include <wtf/MathExtras.h> + +namespace WebCore { + +/* + Produces results in the range [1, 2**31 - 2]. Algorithm is: + r = (a * r) mod m where a = randAmplitude = 16807 and + m = randMaximum = 2**31 - 1 = 2147483647, r = seed. + See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988 + To test: the algorithm should produce the result 1043618065 + as the 10,000th generated number if the original seed is 1. +*/ +static const int s_perlinNoise = 4096; +static const long s_randMaximum = 2147483647; // 2**31 - 1 +static const int s_randAmplitude = 16807; // 7**5; primitive root of m +static const int s_randQ = 127773; // m / a +static const int s_randR = 2836; // m % a + +FETurbulence::FETurbulence(Filter* filter, TurbulanceType type, float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, bool stitchTiles) + : FilterEffect(filter) + , m_type(type) + , m_baseFrequencyX(baseFrequencyX) + , m_baseFrequencyY(baseFrequencyY) + , m_numOctaves(numOctaves) + , m_seed(seed) + , m_stitchTiles(stitchTiles) +{ +} + +PassRefPtr<FETurbulence> FETurbulence::create(Filter* filter, TurbulanceType type, float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, bool stitchTiles) +{ + return adoptRef(new FETurbulence(filter, type, baseFrequencyX, baseFrequencyY, numOctaves, seed, stitchTiles)); +} + +TurbulanceType FETurbulence::type() const +{ + return m_type; +} + +void FETurbulence::setType(TurbulanceType type) +{ + m_type = type; +} + +float FETurbulence::baseFrequencyY() const +{ + return m_baseFrequencyY; +} + +void FETurbulence::setBaseFrequencyY(float baseFrequencyY) +{ + m_baseFrequencyY = baseFrequencyY; +} + +float FETurbulence::baseFrequencyX() const +{ + return m_baseFrequencyX; +} + +void FETurbulence::setBaseFrequencyX(float baseFrequencyX) +{ + m_baseFrequencyX = baseFrequencyX; +} + +float FETurbulence::seed() const +{ + return m_seed; +} + +void FETurbulence::setSeed(float seed) +{ + m_seed = seed; +} + +int FETurbulence::numOctaves() const +{ + return m_numOctaves; +} + +void FETurbulence::setNumOctaves(bool numOctaves) +{ + m_numOctaves = numOctaves; +} + +bool FETurbulence::stitchTiles() const +{ + return m_stitchTiles; +} + +void FETurbulence::setStitchTiles(bool stitch) +{ + m_stitchTiles = stitch; +} + +// The turbulence calculation code is an adapted version of what appears in the SVG 1.1 specification: +// http://www.w3.org/TR/SVG11/filters.html#feTurbulence + +FETurbulence::PaintingData::PaintingData(long paintingSeed, const IntSize& paintingSize) + : seed(paintingSeed) + , width(0) + , height(0) + , wrapX(0) + , wrapY(0) + , channel(0) + , filterSize(paintingSize) +{ +} + +// Compute pseudo random number. +inline long FETurbulence::PaintingData::random() +{ + long result = s_randAmplitude * (seed % s_randQ) - s_randR * (seed / s_randQ); + if (result <= 0) + result += s_randMaximum; + seed = result; + return result; +} + +inline float smoothCurve(float t) +{ + return t * t * (3 - 2 * t); +} + +inline float linearInterpolation(float t, float a, float b) +{ + return a + t * (b - a); +} + +inline void FETurbulence::initPaint(PaintingData& paintingData) +{ + float normalizationFactor; + + // The seed value clamp to the range [1, s_randMaximum - 1]. + if (paintingData.seed <= 0) + paintingData.seed = -(paintingData.seed % (s_randMaximum - 1)) + 1; + if (paintingData.seed > s_randMaximum - 1) + paintingData.seed = s_randMaximum - 1; + + float* gradient; + for (int channel = 0; channel < 4; ++channel) { + for (int i = 0; i < s_blockSize; ++i) { + paintingData.latticeSelector[i] = i; + gradient = paintingData.gradient[channel][i]; + gradient[0] = static_cast<float>((paintingData.random() % (2 * s_blockSize)) - s_blockSize) / s_blockSize; + gradient[1] = static_cast<float>((paintingData.random() % (2 * s_blockSize)) - s_blockSize) / s_blockSize; + normalizationFactor = sqrtf(gradient[0] * gradient[0] + gradient[1] * gradient[1]); + gradient[0] /= normalizationFactor; + gradient[1] /= normalizationFactor; + } + } + for (int i = s_blockSize - 1; i > 0; --i) { + int k = paintingData.latticeSelector[i]; + int j = paintingData.random() % s_blockSize; + ASSERT(j >= 0); + ASSERT(j < 2 * s_blockSize + 2); + paintingData.latticeSelector[i] = paintingData.latticeSelector[j]; + paintingData.latticeSelector[j] = k; + } + for (int i = 0; i < s_blockSize + 2; ++i) { + paintingData.latticeSelector[s_blockSize + i] = paintingData.latticeSelector[i]; + for (int channel = 0; channel < 4; ++channel) { + paintingData.gradient[channel][s_blockSize + i][0] = paintingData.gradient[channel][i][0]; + paintingData.gradient[channel][s_blockSize + i][1] = paintingData.gradient[channel][i][1]; + } + } +} + +inline void checkNoise(int& noiseValue, int limitValue, int newValue) +{ + if (noiseValue >= limitValue) + noiseValue -= newValue; + if (noiseValue >= limitValue - 1) + noiseValue -= newValue - 1; +} + +float FETurbulence::noise2D(PaintingData& paintingData, const FloatPoint& noiseVector) +{ + struct Noise { + int noisePositionIntegerValue; + float noisePositionFractionValue; + + Noise(float component) + { + float position = component + s_perlinNoise; + noisePositionIntegerValue = static_cast<int>(position); + noisePositionFractionValue = position - noisePositionIntegerValue; + } + }; + + Noise noiseX(noiseVector.x()); + Noise noiseY(noiseVector.y()); + float* q; + float sx, sy, a, b, u, v; + + // If stitching, adjust lattice points accordingly. + if (m_stitchTiles) { + checkNoise(noiseX.noisePositionIntegerValue, paintingData.wrapX, paintingData.width); + checkNoise(noiseY.noisePositionIntegerValue, paintingData.wrapY, paintingData.height); + } + + noiseX.noisePositionIntegerValue &= s_blockMask; + noiseY.noisePositionIntegerValue &= s_blockMask; + int latticeIndex = paintingData.latticeSelector[noiseX.noisePositionIntegerValue]; + int nextLatticeIndex = paintingData.latticeSelector[(noiseX.noisePositionIntegerValue + 1) & s_blockMask]; + + sx = smoothCurve(noiseX.noisePositionFractionValue); + sy = smoothCurve(noiseY.noisePositionFractionValue); + + // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement. + int temp = paintingData.latticeSelector[latticeIndex + noiseY.noisePositionIntegerValue]; + q = paintingData.gradient[paintingData.channel][temp]; + u = noiseX.noisePositionFractionValue * q[0] + noiseY.noisePositionFractionValue * q[1]; + temp = paintingData.latticeSelector[nextLatticeIndex + noiseY.noisePositionIntegerValue]; + q = paintingData.gradient[paintingData.channel][temp]; + v = (noiseX.noisePositionFractionValue - 1) * q[0] + noiseY.noisePositionFractionValue * q[1]; + a = linearInterpolation(sx, u, v); + temp = paintingData.latticeSelector[latticeIndex + noiseY.noisePositionIntegerValue + 1]; + q = paintingData.gradient[paintingData.channel][temp]; + u = noiseX.noisePositionFractionValue * q[0] + (noiseY.noisePositionFractionValue - 1) * q[1]; + temp = paintingData.latticeSelector[nextLatticeIndex + noiseY.noisePositionIntegerValue + 1]; + q = paintingData.gradient[paintingData.channel][temp]; + v = (noiseX.noisePositionFractionValue - 1) * q[0] + (noiseY.noisePositionFractionValue - 1) * q[1]; + b = linearInterpolation(sx, u, v); + return linearInterpolation(sy, a, b); +} + +unsigned char FETurbulence::calculateTurbulenceValueForPoint(PaintingData& paintingData, const FloatPoint& point) +{ + float tileWidth = paintingData.filterSize.width(); + ASSERT(tileWidth > 0); + float tileHeight = paintingData.filterSize.height(); + ASSERT(tileHeight > 0); + // Adjust the base frequencies if necessary for stitching. + if (m_stitchTiles) { + // When stitching tiled turbulence, the frequencies must be adjusted + // so that the tile borders will be continuous. + if (m_baseFrequencyX) { + float lowFrequency = floorf(tileWidth * m_baseFrequencyX) / tileWidth; + float highFrequency = ceilf(tileWidth * m_baseFrequencyX) / tileWidth; + // BaseFrequency should be non-negative according to the standard. + if (m_baseFrequencyX / lowFrequency < highFrequency / m_baseFrequencyX) + m_baseFrequencyX = lowFrequency; + else + m_baseFrequencyX = highFrequency; + } + if (m_baseFrequencyY) { + float lowFrequency = floorf(tileHeight * m_baseFrequencyY) / tileHeight; + float highFrequency = ceilf(tileHeight * m_baseFrequencyY) / tileHeight; + if (m_baseFrequencyY / lowFrequency < highFrequency / m_baseFrequencyY) + m_baseFrequencyY = lowFrequency; + else + m_baseFrequencyY = highFrequency; + } + // Set up TurbulenceInitial stitch values. + paintingData.width = roundf(tileWidth * m_baseFrequencyX); + paintingData.wrapX = s_perlinNoise + paintingData.width; + paintingData.height = roundf(tileHeight * m_baseFrequencyY); + paintingData.wrapY = s_perlinNoise + paintingData.height; + } + float turbulenceFunctionResult = 0; + FloatPoint noiseVector(point.x() * m_baseFrequencyX, point.y() * m_baseFrequencyY); + float ratio = 1; + for (int octave = 0; octave < m_numOctaves; ++octave) { + if (m_type == FETURBULENCE_TYPE_FRACTALNOISE) + turbulenceFunctionResult += noise2D(paintingData, noiseVector) / ratio; + else + turbulenceFunctionResult += fabsf(noise2D(paintingData, noiseVector)) / ratio; + noiseVector.setX(noiseVector.x() * 2); + noiseVector.setY(noiseVector.y() * 2); + ratio *= 2; + if (m_stitchTiles) { + // Update stitch values. Subtracting s_perlinNoiseoise before the multiplication and + // adding it afterward simplifies to subtracting it once. + paintingData.width *= 2; + paintingData.wrapX = 2 * paintingData.wrapX - s_perlinNoise; + paintingData.height *= 2; + paintingData.wrapY = 2 * paintingData.wrapY - s_perlinNoise; + } + } + + // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult * 255) + 255) / 2 by fractalNoise + // and (turbulenceFunctionResult * 255) by turbulence. + if (m_type == FETURBULENCE_TYPE_FRACTALNOISE) + turbulenceFunctionResult = turbulenceFunctionResult * 0.5f + 0.5f; + // Clamp result + turbulenceFunctionResult = std::max(std::min(turbulenceFunctionResult, 1.f), 0.f); + return static_cast<unsigned char>(turbulenceFunctionResult * 255); +} + +void FETurbulence::apply() +{ + if (hasResult()) + return; + ByteArray* pixelArray = createUnmultipliedImageResult(); + if (!pixelArray) + return; + + if (absolutePaintRect().isEmpty()) + return; + + PaintingData paintingData(m_seed, roundedIntSize(filterPrimitiveSubregion().size())); + initPaint(paintingData); + + FloatRect filterRegion = absolutePaintRect(); + FloatPoint point; + point.setY(filterRegion.y()); + int indexOfPixelChannel = 0; + for (int y = 0; y < absolutePaintRect().height(); ++y) { + point.setY(point.y() + 1); + point.setX(filterRegion.x()); + for (int x = 0; x < absolutePaintRect().width(); ++x) { + point.setX(point.x() + 1); + for (paintingData.channel = 0; paintingData.channel < 4; ++paintingData.channel, ++indexOfPixelChannel) + pixelArray->set(indexOfPixelChannel, calculateTurbulenceValueForPoint(paintingData, filter()->mapAbsolutePointToLocalPoint(point))); + } + } +} + +void FETurbulence::dump() +{ +} + +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, int indent) const +{ + writeIndent(ts, indent); + ts << "[feTurbulence"; + FilterEffect::externalRepresentation(ts); + ts << " type=\"" << type() << "\" " + << "baseFrequency=\"" << baseFrequencyX() << ", " << baseFrequencyY() << "\" " + << "seed=\"" << seed() << "\" " + << "numOctaves=\"" << numOctaves() << "\" " + << "stitchTiles=\"" << stitchTiles() << "\"]\n"; + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/FETurbulence.h b/Source/WebCore/platform/graphics/filters/FETurbulence.h new file mode 100644 index 0000000..1bad123 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FETurbulence.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) 2010 Renata Hodovan <reni@inf.u-szeged.hu> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FETurbulence_h +#define FETurbulence_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" +#include "Filter.h" + +namespace WebCore { + +enum TurbulanceType { + FETURBULENCE_TYPE_UNKNOWN = 0, + FETURBULENCE_TYPE_FRACTALNOISE = 1, + FETURBULENCE_TYPE_TURBULENCE = 2 +}; + +class FETurbulence : public FilterEffect { +public: + static PassRefPtr<FETurbulence> create(Filter*, TurbulanceType, float, float, int, float, bool); + + TurbulanceType type() const; + void setType(TurbulanceType); + + float baseFrequencyY() const; + void setBaseFrequencyY(float); + + float baseFrequencyX() const; + void setBaseFrequencyX(float); + + float seed() const; + void setSeed(float); + + int numOctaves() const; + void setNumOctaves(bool); + + bool stitchTiles() const; + void setStitchTiles(bool); + + virtual void apply(); + virtual void dump(); + + virtual void determineAbsolutePaintRect() { setAbsolutePaintRect(maxEffectRect()); } + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + static const int s_blockSize = 256; + static const int s_blockMask = s_blockSize - 1; + + struct PaintingData { + long seed; + int latticeSelector[2 * s_blockSize + 2]; + float gradient[4][2 * s_blockSize + 2][2]; + int width; // How much to subtract to wrap for stitching. + int height; + int wrapX; // Minimum value to wrap. + int wrapY; + int channel; + IntSize filterSize; + + PaintingData(long paintingSeed, const IntSize& paintingSize); + inline long random(); + }; + + FETurbulence(Filter*, TurbulanceType, float, float, int, float, bool); + + inline void initPaint(PaintingData&); + float noise2D(PaintingData&, const FloatPoint&); + unsigned char calculateTurbulenceValueForPoint(PaintingData&, const FloatPoint&); + + TurbulanceType m_type; + float m_baseFrequencyX; + float m_baseFrequencyY; + int m_numOctaves; + float m_seed; + bool m_stitchTiles; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FETurbulence_h diff --git a/Source/WebCore/platform/graphics/filters/Filter.h b/Source/WebCore/platform/graphics/filters/Filter.h new file mode 100644 index 0000000..33cf724 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/Filter.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef Filter_h +#define Filter_h + +#if ENABLE(FILTERS) +#include "FloatRect.h" +#include "FloatSize.h" +#include "ImageBuffer.h" + +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> +#include <wtf/text/StringHash.h> + +namespace WebCore { + + class FilterEffect; + + class Filter : public RefCounted<Filter> { + public: + virtual ~Filter() { } + + void setSourceImage(PassOwnPtr<ImageBuffer> sourceImage) { m_sourceImage = sourceImage; } + ImageBuffer* sourceImage() { return m_sourceImage.get(); } + + FloatSize filterResolution() const { return m_filterResolution; } + void setFilterResolution(const FloatSize& filterResolution) { m_filterResolution = filterResolution; } + + virtual float applyHorizontalScale(float value) const { return value * m_filterResolution.width(); } + virtual float applyVerticalScale(float value) const { return value * m_filterResolution.height(); } + + virtual FloatRect sourceImageRect() const = 0; + virtual FloatRect filterRegion() const = 0; + + virtual FloatPoint mapAbsolutePointToLocalPoint(const FloatPoint&) const { return FloatPoint(); } + + virtual FloatRect filterRegionInUserSpace() const { return FloatRect(); } + + virtual bool effectBoundingBoxMode() const = 0; + + private: + OwnPtr<ImageBuffer> m_sourceImage; + FloatSize m_filterResolution; + }; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // Filter_h diff --git a/Source/WebCore/platform/graphics/filters/FilterEffect.cpp b/Source/WebCore/platform/graphics/filters/FilterEffect.cpp new file mode 100644 index 0000000..05c2a47 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FilterEffect.cpp @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "FilterEffect.h" + +#include <wtf/ByteArray.h> + +namespace WebCore { + +FilterEffect::FilterEffect(Filter* filter) + : m_alphaImage(false) + , m_filter(filter) + , m_hasX(false) + , m_hasY(false) + , m_hasWidth(false) + , m_hasHeight(false) +{ + ASSERT(m_filter); +} + +FilterEffect::~FilterEffect() +{ +} + +void FilterEffect::determineAbsolutePaintRect() +{ + m_absolutePaintRect = IntRect(); + unsigned size = m_inputEffects.size(); + for (unsigned i = 0; i < size; ++i) + m_absolutePaintRect.unite(m_inputEffects.at(i)->absolutePaintRect()); + + // SVG specification wants us to clip to primitive subregion. + m_absolutePaintRect.intersect(m_maxEffectRect); +} + +IntRect FilterEffect::requestedRegionOfInputImageData(const IntRect& effectRect) const +{ + ASSERT(hasResult()); + IntPoint location = m_absolutePaintRect.location(); + location.move(-effectRect.x(), -effectRect.y()); + return IntRect(location, m_absolutePaintRect.size()); +} + +IntRect FilterEffect::drawingRegionOfInputImage(const IntRect& srcRect) const +{ + return IntRect(IntPoint(srcRect.x() - m_absolutePaintRect.x(), + srcRect.y() - m_absolutePaintRect.y()), srcRect.size()); +} + +FilterEffect* FilterEffect::inputEffect(unsigned number) const +{ + ASSERT(number < m_inputEffects.size()); + return m_inputEffects.at(number).get(); +} + +ImageBuffer* FilterEffect::asImageBuffer() +{ + if (!hasResult()) + return 0; + if (m_imageBufferResult) + return m_imageBufferResult.get(); + m_imageBufferResult = ImageBuffer::create(m_absolutePaintRect.size(), ColorSpaceLinearRGB); + IntRect destinationRect(IntPoint(), m_absolutePaintRect.size()); + if (m_premultipliedImageResult) + m_imageBufferResult->putPremultipliedImageData(m_premultipliedImageResult.get(), destinationRect.size(), destinationRect, IntPoint()); + else + m_imageBufferResult->putUnmultipliedImageData(m_unmultipliedImageResult.get(), destinationRect.size(), destinationRect, IntPoint()); + return m_imageBufferResult.get(); +} + +PassRefPtr<ByteArray> FilterEffect::asUnmultipliedImage(const IntRect& rect) +{ + RefPtr<ByteArray> imageData = ByteArray::create(rect.width() * rect.height() * 4); + copyUnmultipliedImage(imageData.get(), rect); + return imageData.release(); +} + +PassRefPtr<ByteArray> FilterEffect::asPremultipliedImage(const IntRect& rect) +{ + RefPtr<ByteArray> imageData = ByteArray::create(rect.width() * rect.height() * 4); + copyPremultipliedImage(imageData.get(), rect); + return imageData.release(); +} + +inline void FilterEffect::copyImageBytes(ByteArray* source, ByteArray* destination, const IntRect& rect) +{ + // Copy the necessary lines. + if (rect.x() < 0 || rect.y() < 0 || rect.bottom() > m_absolutePaintRect.width() || rect.bottom() > m_absolutePaintRect.height()) + memset(destination->data(), 0, destination->length()); + + int xOrigin = rect.x(); + int xDest = 0; + if (xOrigin < 0) { + xDest = -xOrigin; + xOrigin = 0; + } + int xEnd = rect.right(); + if (xEnd > m_absolutePaintRect.width()) + xEnd = m_absolutePaintRect.width(); + + int yOrigin = rect.y(); + int yDest = 0; + if (yOrigin < 0) { + yDest = -yOrigin; + yOrigin = 0; + } + int yEnd = rect.bottom(); + if (yEnd > m_absolutePaintRect.height()) + yEnd = m_absolutePaintRect.height(); + + int size = (xEnd - xOrigin) * 4; + int destinationScanline = rect.width() * 4; + int sourceScanline = m_absolutePaintRect.width() * 4; + unsigned char *destinationPixel = destination->data() + ((yDest * rect.width()) + xDest) * 4; + unsigned char *sourcePixel = source->data() + ((yOrigin * m_absolutePaintRect.width()) + xOrigin) * 4; + + while (yOrigin < yEnd) { + memcpy(destinationPixel, sourcePixel, size); + destinationPixel += destinationScanline; + sourcePixel += sourceScanline; + ++yOrigin; + } +} + +void FilterEffect::copyUnmultipliedImage(ByteArray* destination, const IntRect& rect) +{ + ASSERT(hasResult()); + + if (!m_unmultipliedImageResult) { + // We prefer a conversion from the image buffer. + if (m_imageBufferResult) + m_unmultipliedImageResult = m_imageBufferResult->getUnmultipliedImageData(IntRect(IntPoint(), m_absolutePaintRect.size())); + else { + m_unmultipliedImageResult = ByteArray::create(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4); + unsigned char* sourceComponent = m_premultipliedImageResult->data(); + unsigned char* destinationComponent = m_unmultipliedImageResult->data(); + unsigned char* end = sourceComponent + (m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4); + while (sourceComponent < end) { + int alpha = sourceComponent[3]; + if (alpha) { + destinationComponent[0] = static_cast<int>(sourceComponent[0]) * 255 / alpha; + destinationComponent[1] = static_cast<int>(sourceComponent[1]) * 255 / alpha; + destinationComponent[2] = static_cast<int>(sourceComponent[2]) * 255 / alpha; + } else { + destinationComponent[0] = 0; + destinationComponent[1] = 0; + destinationComponent[2] = 0; + } + destinationComponent[3] = alpha; + sourceComponent += 4; + destinationComponent += 4; + } + } + } + copyImageBytes(m_unmultipliedImageResult.get(), destination, rect); +} + +void FilterEffect::copyPremultipliedImage(ByteArray* destination, const IntRect& rect) +{ + ASSERT(hasResult()); + + if (!m_premultipliedImageResult) { + // We prefer a conversion from the image buffer. + if (m_imageBufferResult) + m_premultipliedImageResult = m_imageBufferResult->getPremultipliedImageData(IntRect(IntPoint(), m_absolutePaintRect.size())); + else { + m_premultipliedImageResult = ByteArray::create(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4); + unsigned char* sourceComponent = m_unmultipliedImageResult->data(); + unsigned char* destinationComponent = m_premultipliedImageResult->data(); + unsigned char* end = sourceComponent + (m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4); + while (sourceComponent < end) { + int alpha = sourceComponent[3]; + destinationComponent[0] = static_cast<int>(sourceComponent[0]) * alpha / 255; + destinationComponent[1] = static_cast<int>(sourceComponent[1]) * alpha / 255; + destinationComponent[2] = static_cast<int>(sourceComponent[2]) * alpha / 255; + destinationComponent[3] = alpha; + sourceComponent += 4; + destinationComponent += 4; + } + } + } + copyImageBytes(m_premultipliedImageResult.get(), destination, rect); +} + +ImageBuffer* FilterEffect::createImageBufferResult() +{ + // Only one result type is allowed. + ASSERT(!hasResult()); + determineAbsolutePaintRect(); + if (m_absolutePaintRect.isEmpty()) + return 0; + m_imageBufferResult = ImageBuffer::create(m_absolutePaintRect.size(), ColorSpaceLinearRGB); + if (!m_imageBufferResult) + return 0; + ASSERT(m_imageBufferResult->context()); + return m_imageBufferResult.get(); +} + +ByteArray* FilterEffect::createUnmultipliedImageResult() +{ + // Only one result type is allowed. + ASSERT(!hasResult()); + determineAbsolutePaintRect(); + if (m_absolutePaintRect.isEmpty()) + return 0; + m_unmultipliedImageResult = ByteArray::create(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4); + return m_unmultipliedImageResult.get(); +} + +ByteArray* FilterEffect::createPremultipliedImageResult() +{ + // Only one result type is allowed. + ASSERT(!hasResult()); + determineAbsolutePaintRect(); + if (m_absolutePaintRect.isEmpty()) + return 0; + m_premultipliedImageResult = ByteArray::create(m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4); + return m_premultipliedImageResult.get(); +} + +TextStream& FilterEffect::externalRepresentation(TextStream& ts, int) const +{ + // FIXME: We should dump the subRegions of the filter primitives here later. This isn't + // possible at the moment, because we need more detailed informations from the target object. + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/FilterEffect.h b/Source/WebCore/platform/graphics/filters/FilterEffect.h new file mode 100644 index 0000000..2554d4b --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/FilterEffect.h @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FilterEffect_h +#define FilterEffect_h + +#if ENABLE(FILTERS) +#include "Filter.h" +#include "FloatRect.h" +#include "GraphicsContext.h" +#include "ImageBuffer.h" +#include "RenderTreeAsText.h" +#include "TextStream.h" + +#include <wtf/PassOwnPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> +#include <wtf/Vector.h> + +namespace WebCore { + +typedef Vector<RefPtr<FilterEffect> > FilterEffectVector; + +enum FilterEffectType { + FilterEffectTypeUnknown, + FilterEffectTypeImage, + FilterEffectTypeTile, + FilterEffectTypeSourceInput +}; + +class FilterEffect : public RefCounted<FilterEffect> { +public: + virtual ~FilterEffect(); + + bool hasResult() const { return m_imageBufferResult || m_unmultipliedImageResult || m_premultipliedImageResult; } + ImageBuffer* asImageBuffer(); + PassRefPtr<ByteArray> asUnmultipliedImage(const IntRect&); + PassRefPtr<ByteArray> asPremultipliedImage(const IntRect&); + void copyUnmultipliedImage(ByteArray* destination, const IntRect&); + void copyPremultipliedImage(ByteArray* destination, const IntRect&); + + FilterEffectVector& inputEffects() { return m_inputEffects; } + FilterEffect* inputEffect(unsigned) const; + unsigned numberOfEffectInputs() const { return m_inputEffects.size(); } + + IntRect drawingRegionOfInputImage(const IntRect&) const; + IntRect requestedRegionOfInputImageData(const IntRect&) const; + + // Solid black image with different alpha values. + bool isAlphaImage() const { return m_alphaImage; } + void setIsAlphaImage(bool alphaImage) { m_alphaImage = alphaImage; } + + IntRect absolutePaintRect() const { return m_absolutePaintRect; } + void setAbsolutePaintRect(const IntRect& absolutePaintRect) { m_absolutePaintRect = absolutePaintRect; } + + IntRect maxEffectRect() const { return m_maxEffectRect; } + void setMaxEffectRect(const IntRect& maxEffectRect) { m_maxEffectRect = maxEffectRect; } + + virtual void apply() = 0; + virtual void dump() = 0; + + virtual void determineAbsolutePaintRect(); + + virtual FilterEffectType filterEffectType() const { return FilterEffectTypeUnknown; } + + virtual TextStream& externalRepresentation(TextStream&, int indention = 0) const; + +public: + // The following functions are SVG specific and will move to RenderSVGResourceFilterPrimitive. + // See bug https://bugs.webkit.org/show_bug.cgi?id=45614. + bool hasX() const { return m_hasX; } + void setHasX(bool value) { m_hasX = value; } + + bool hasY() const { return m_hasY; } + void setHasY(bool value) { m_hasY = value; } + + bool hasWidth() const { return m_hasWidth; } + void setHasWidth(bool value) { m_hasWidth = value; } + + bool hasHeight() const { return m_hasHeight; } + void setHasHeight(bool value) { m_hasHeight = value; } + + FloatRect filterPrimitiveSubregion() const { return m_filterPrimitiveSubregion; } + void setFilterPrimitiveSubregion(const FloatRect& filterPrimitiveSubregion) { m_filterPrimitiveSubregion = filterPrimitiveSubregion; } + + FloatRect effectBoundaries() const { return m_effectBoundaries; } + void setEffectBoundaries(const FloatRect& effectBoundaries) { m_effectBoundaries = effectBoundaries; } + + Filter* filter() { return m_filter; } + +protected: + FilterEffect(Filter*); + + ImageBuffer* createImageBufferResult(); + ByteArray* createUnmultipliedImageResult(); + ByteArray* createPremultipliedImageResult(); + +private: + OwnPtr<ImageBuffer> m_imageBufferResult; + RefPtr<ByteArray> m_unmultipliedImageResult; + RefPtr<ByteArray> m_premultipliedImageResult; + FilterEffectVector m_inputEffects; + + bool m_alphaImage; + + IntRect m_absolutePaintRect; + + // The maximum size of a filter primitive. In SVG this is the primitive subregion in absolute coordinate space. + // The absolute paint rect should never be bigger than m_maxEffectRect. + IntRect m_maxEffectRect; + Filter* m_filter; + +private: + inline void copyImageBytes(ByteArray* source, ByteArray* destination, const IntRect&); + + // The following member variables are SVG specific and will move to RenderSVGResourceFilterPrimitive. + // See bug https://bugs.webkit.org/show_bug.cgi?id=45614. + + // The subregion of a filter primitive according to the SVG Filter specification in local coordinates. + // This is SVG specific and needs to move to RenderSVGResourceFilterPrimitive. + FloatRect m_filterPrimitiveSubregion; + + // x, y, width and height of the actual SVGFE*Element. Is needed to determine the subregion of the + // filter primitive on a later step. + FloatRect m_effectBoundaries; + bool m_hasX; + bool m_hasY; + bool m_hasWidth; + bool m_hasHeight; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // FilterEffect_h diff --git a/Source/WebCore/platform/graphics/filters/LightSource.cpp b/Source/WebCore/platform/graphics/filters/LightSource.cpp new file mode 100644 index 0000000..de0691e --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/LightSource.cpp @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 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 + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "LightSource.h" + +#include "DistantLightSource.h" +#include "PointLightSource.h" +#include "RenderTreeAsText.h" +#include "SpotLightSource.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.lightVectorLength = paintingData.lightVector.length(); +} + +// spot-light edge darkening depends on an absolute treshold +// according to the SVG 1.1 SE light regression tests +static const float antiAliasTreshold = 0.016f; + +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 = -antiAliasTreshold; + } else { + float limitingConeAngle = m_limitingConeAngle; + if (limitingConeAngle < 0.0f) + limitingConeAngle = -limitingConeAngle; + if (limitingConeAngle > 90.0f) + limitingConeAngle = 90.0f; + paintingData.coneCutOffLimit = cosf(deg2rad(180.0f - limitingConeAngle)); + paintingData.coneFullLight = paintingData.coneCutOffLimit - antiAliasTreshold; + } + + // 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.lightVectorLength = paintingData.lightVector.length(); + + float cosineOfAngle = (paintingData.lightVector * paintingData.directionVector) / paintingData.lightVectorLength; + 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)); + paintingData.lightVectorLength = 1; +} + +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(); + return ts; +} + +TextStream& PointLightSource::externalRepresentation(TextStream& ts) const +{ + ts << "[type=POINT-LIGHT] "; + ts << "[position=\"" << position() << "\"]"; + return ts; +} + +TextStream& SpotLightSource::externalRepresentation(TextStream& ts) const +{ + ts << "[type=SPOT-LIGHT] "; + ts << "[position=\"" << position() << "\"]"; + ts << "[direction=\"" << direction() << "\"]"; + ts << "[specularExponent=\"" << specularExponent() << "\"]"; + ts << "[limitingConeAngle=\"" << limitingConeAngle() << "\"]"; + return ts; +} + +TextStream& DistantLightSource::externalRepresentation(TextStream& ts) const +{ + ts << "[type=DISTANT-LIGHT] "; + ts << "[azimuth=\"" << azimuth() << "\"]"; + ts << "[elevation=\"" << elevation() << "\"]"; + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/LightSource.h b/Source/WebCore/platform/graphics/filters/LightSource.h new file mode 100644 index 0000000..013e910 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/LightSource.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * Copyright (C) 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 + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef LightSource_h +#define LightSource_h + +#if ENABLE(FILTERS) +#include "FloatPoint3D.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> + +namespace WebCore { + +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; + float lightVectorLength; + // Private members + FloatPoint3D directionVector; + FloatPoint3D privateColorVector; + float coneCutOffLimit; + float coneFullLight; + int specularExponent; + }; + + LightSource(LightType type) + : m_type(type) + { } + + virtual ~LightSource() { } + + 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; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // LightSource_h diff --git a/Source/WebCore/platform/graphics/filters/PointLightSource.h b/Source/WebCore/platform/graphics/filters/PointLightSource.h new file mode 100644 index 0000000..163c829 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/PointLightSource.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef PointLightSource_h +#define PointLightSource_h + +#if ENABLE(FILTERS) +#include "LightSource.h" + +namespace WebCore { + +class PointLightSource : public LightSource { +public: + static PassRefPtr<PointLightSource> create(const FloatPoint3D& position) + { + return adoptRef(new PointLightSource(position)); + } + + const FloatPoint3D& position() const { return m_position; } + + virtual void initPaintingData(PaintingData&); + virtual void updatePaintingData(PaintingData&, int x, int y, float z); + + virtual TextStream& externalRepresentation(TextStream&) const; + +private: + PointLightSource(const FloatPoint3D& position) + : LightSource(LS_POINT) + , m_position(position) + { + } + + FloatPoint3D m_position; +}; + +} // namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // PointLightSource_h diff --git a/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp b/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp new file mode 100644 index 0000000..2d2de00 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "SourceAlpha.h" + +#include "Color.h" +#include "GraphicsContext.h" +#include "PlatformString.h" +#include "Filter.h" + +#include <wtf/StdLibExtras.h> + +namespace WebCore { + +PassRefPtr<SourceAlpha> SourceAlpha::create(Filter* filter) +{ + return adoptRef(new SourceAlpha(filter)); +} + +const AtomicString& SourceAlpha::effectName() +{ + DEFINE_STATIC_LOCAL(const AtomicString, s_effectName, ("SourceAlpha")); + return s_effectName; +} + +void SourceAlpha::determineAbsolutePaintRect() +{ + Filter* filter = this->filter(); + FloatRect paintRect = filter->sourceImageRect(); + paintRect.scale(filter->filterResolution().width(), filter->filterResolution().height()); + setAbsolutePaintRect(enclosingIntRect(paintRect)); +} + +void SourceAlpha::apply() +{ + if (hasResult()) + return; + ImageBuffer* resultImage = createImageBufferResult(); + Filter* filter = this->filter(); + if (!resultImage || !filter->sourceImage()) + return; + + setIsAlphaImage(true); + + FloatRect imageRect(FloatPoint(), absolutePaintRect().size()); + GraphicsContext* filterContext = resultImage->context(); + filterContext->save(); + filterContext->clipToImageBuffer(filter->sourceImage(), imageRect); + filterContext->fillRect(imageRect, Color::black, ColorSpaceDeviceRGB); + filterContext->restore(); +} + +void SourceAlpha::dump() +{ +} + +TextStream& SourceAlpha::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[SourceAlpha]\n"; + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/SourceAlpha.h b/Source/WebCore/platform/graphics/filters/SourceAlpha.h new file mode 100644 index 0000000..c6f95d3 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/SourceAlpha.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef SourceAlpha_h +#define SourceAlpha_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" + +#include "PlatformString.h" +#include "Filter.h" + +namespace WebCore { + +class SourceAlpha : public FilterEffect { +public: + static PassRefPtr<SourceAlpha> create(Filter*); + + static const AtomicString& effectName(); + + virtual void apply(); + virtual void dump(); + + virtual void determineAbsolutePaintRect(); + + virtual FilterEffectType filterEffectType() const { return FilterEffectTypeSourceInput; } + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + SourceAlpha(Filter* filter) + : FilterEffect(filter) + { + } +}; + +} //namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // SourceAlpha_h diff --git a/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp b/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp new file mode 100644 index 0000000..04082ad --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(FILTERS) +#include "SourceGraphic.h" + +#include "GraphicsContext.h" +#include "PlatformString.h" +#include "Filter.h" + +#include <wtf/StdLibExtras.h> + +namespace WebCore { + +PassRefPtr<SourceGraphic> SourceGraphic::create(Filter* filter) +{ + return adoptRef(new SourceGraphic(filter)); +} + +const AtomicString& SourceGraphic::effectName() +{ + DEFINE_STATIC_LOCAL(const AtomicString, s_effectName, ("SourceGraphic")); + return s_effectName; +} + +void SourceGraphic::determineAbsolutePaintRect() +{ + Filter* filter = this->filter(); + FloatRect paintRect = filter->sourceImageRect(); + paintRect.scale(filter->filterResolution().width(), filter->filterResolution().height()); + setAbsolutePaintRect(enclosingIntRect(paintRect)); +} + +void SourceGraphic::apply() +{ + if (hasResult()) + return; + ImageBuffer* resultImage = createImageBufferResult(); + Filter* filter = this->filter(); + if (!resultImage || !filter->sourceImage()) + return; + + resultImage->context()->drawImageBuffer(filter->sourceImage(), ColorSpaceDeviceRGB, IntPoint()); +} + +void SourceGraphic::dump() +{ +} + +TextStream& SourceGraphic::externalRepresentation(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "[SourceGraphic]\n"; + return ts; +} + +} // namespace WebCore + +#endif // ENABLE(FILTERS) diff --git a/Source/WebCore/platform/graphics/filters/SourceGraphic.h b/Source/WebCore/platform/graphics/filters/SourceGraphic.h new file mode 100644 index 0000000..97d6882 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/SourceGraphic.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef SourceGraphic_h +#define SourceGraphic_h + +#if ENABLE(FILTERS) +#include "FilterEffect.h" + +#include "Filter.h" +#include "PlatformString.h" + +namespace WebCore { + +class SourceGraphic : public FilterEffect { +public: + static PassRefPtr<SourceGraphic> create(Filter*); + + static const AtomicString& effectName(); + + virtual void apply(); + virtual void dump(); + + virtual void determineAbsolutePaintRect(); + + virtual FilterEffectType filterEffectType() const { return FilterEffectTypeSourceInput; } + + virtual TextStream& externalRepresentation(TextStream&, int indention) const; + +private: + SourceGraphic(Filter* filter) + : FilterEffect(filter) + { + } +}; + +} //namespace WebCore + +#endif // ENABLE(FILTERS) + +#endif // SourceGraphic_h diff --git a/Source/WebCore/platform/graphics/filters/SpotLightSource.h b/Source/WebCore/platform/graphics/filters/SpotLightSource.h new file mode 100644 index 0000000..cd6a614 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/SpotLightSource.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2008 Alex Mathews <possessedpenguinbob@gmail.com> + * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> + * Copyright (C) 2005 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef SpotLightSource_h +#define SpotLightSource_h + +#if ENABLE(FILTERS) +#include "LightSource.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 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 + +#endif // ENABLE(FILTERS) + +#endif // SpotLightSource_h |