summaryrefslogtreecommitdiff
path: root/Source/WebCore/platform/graphics/filters
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-01-06 14:44:00 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2012-01-06 14:44:00 +0100
commit40736c5763bf61337c8c14e16d8587db021a87d4 (patch)
treeb17a9c00042ad89cb1308e2484491799aa14e9f8 /Source/WebCore/platform/graphics/filters
downloadqtwebkit-40736c5763bf61337c8c14e16d8587db021a87d4.tar.gz
Imported WebKit commit 2ea9d364d0f6efa8fa64acf19f451504c59be0e4 (http://svn.webkit.org/repository/webkit/trunk@104285)
Diffstat (limited to 'Source/WebCore/platform/graphics/filters')
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterMesh.cpp266
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterMesh.h80
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterShader.cpp171
-rw-r--r--Source/WebCore/platform/graphics/filters/CustomFilterShader.h107
-rw-r--r--Source/WebCore/platform/graphics/filters/DistantLightSource.cpp80
-rw-r--r--Source/WebCore/platform/graphics/filters/DistantLightSource.h64
-rw-r--r--Source/WebCore/platform/graphics/filters/FEBlend.cpp188
-rw-r--r--Source/WebCore/platform/graphics/filters/FEBlend.h63
-rw-r--r--Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp244
-rw-r--r--Source/WebCore/platform/graphics/filters/FEColorMatrix.h67
-rw-r--r--Source/WebCore/platform/graphics/filters/FEComponentTransfer.cpp245
-rw-r--r--Source/WebCore/platform/graphics/filters/FEComponentTransfer.h100
-rw-r--r--Source/WebCore/platform/graphics/filters/FEComposite.cpp312
-rw-r--r--Source/WebCore/platform/graphics/filters/FEComposite.h86
-rw-r--r--Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp521
-rw-r--r--Source/WebCore/platform/graphics/filters/FEConvolveMatrix.h138
-rw-r--r--Source/WebCore/platform/graphics/filters/FECustomFilter.cpp214
-rw-r--r--Source/WebCore/platform/graphics/filters/FECustomFilter.h98
-rw-r--r--Source/WebCore/platform/graphics/filters/FEDiffuseLighting.cpp143
-rw-r--r--Source/WebCore/platform/graphics/filters/FEDiffuseLighting.h68
-rw-r--r--Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp177
-rw-r--r--Source/WebCore/platform/graphics/filters/FEDisplacementMap.h72
-rw-r--r--Source/WebCore/platform/graphics/filters/FEDropShadow.cpp136
-rw-r--r--Source/WebCore/platform/graphics/filters/FEDropShadow.h75
-rw-r--r--Source/WebCore/platform/graphics/filters/FEFlood.cpp99
-rw-r--r--Source/WebCore/platform/graphics/filters/FEFlood.h60
-rw-r--r--Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp330
-rw-r--r--Source/WebCore/platform/graphics/filters/FEGaussianBlur.h115
-rw-r--r--Source/WebCore/platform/graphics/filters/FELighting.cpp411
-rw-r--r--Source/WebCore/platform/graphics/filters/FELighting.h127
-rw-r--r--Source/WebCore/platform/graphics/filters/FEMerge.cpp79
-rw-r--r--Source/WebCore/platform/graphics/filters/FEMerge.h49
-rw-r--r--Source/WebCore/platform/graphics/filters/FEMorphology.cpp261
-rw-r--r--Source/WebCore/platform/graphics/filters/FEMorphology.h90
-rw-r--r--Source/WebCore/platform/graphics/filters/FEOffset.cpp112
-rw-r--r--Source/WebCore/platform/graphics/filters/FEOffset.h59
-rw-r--r--Source/WebCore/platform/graphics/filters/FESpecularLighting.cpp158
-rw-r--r--Source/WebCore/platform/graphics/filters/FESpecularLighting.h69
-rw-r--r--Source/WebCore/platform/graphics/filters/FETile.cpp105
-rw-r--r--Source/WebCore/platform/graphics/filters/FETile.h52
-rw-r--r--Source/WebCore/platform/graphics/filters/FETurbulence.cpp447
-rw-r--r--Source/WebCore/platform/graphics/filters/FETurbulence.h122
-rw-r--r--Source/WebCore/platform/graphics/filters/Filter.h65
-rw-r--r--Source/WebCore/platform/graphics/filters/FilterEffect.cpp303
-rw-r--r--Source/WebCore/platform/graphics/filters/FilterEffect.h172
-rw-r--r--Source/WebCore/platform/graphics/filters/FilterOperation.cpp157
-rw-r--r--Source/WebCore/platform/graphics/filters/FilterOperation.h307
-rw-r--r--Source/WebCore/platform/graphics/filters/FilterOperations.cpp141
-rw-r--r--Source/WebCore/platform/graphics/filters/FilterOperations.h76
-rw-r--r--Source/WebCore/platform/graphics/filters/LightSource.cpp115
-rw-r--r--Source/WebCore/platform/graphics/filters/LightSource.h96
-rw-r--r--Source/WebCore/platform/graphics/filters/PointLightSource.cpp91
-rw-r--r--Source/WebCore/platform/graphics/filters/PointLightSource.h62
-rw-r--r--Source/WebCore/platform/graphics/filters/SourceAlpha.cpp84
-rw-r--r--Source/WebCore/platform/graphics/filters/SourceAlpha.h57
-rw-r--r--Source/WebCore/platform/graphics/filters/SourceGraphic.cpp77
-rw-r--r--Source/WebCore/platform/graphics/filters/SourceGraphic.h58
-rw-r--r--Source/WebCore/platform/graphics/filters/SpotLightSource.cpp198
-rw-r--r--Source/WebCore/platform/graphics/filters/SpotLightSource.h80
-rw-r--r--Source/WebCore/platform/graphics/filters/arm/FECompositeArithmeticNEON.cpp155
-rw-r--r--Source/WebCore/platform/graphics/filters/arm/FECompositeArithmeticNEON.h53
-rw-r--r--Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.cpp338
-rw-r--r--Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h116
-rw-r--r--Source/WebCore/platform/graphics/filters/arm/FELightingNEON.cpp504
-rw-r--r--Source/WebCore/platform/graphics/filters/arm/FELightingNEON.h203
-rw-r--r--Source/WebCore/platform/graphics/filters/skia/FEGaussianBlurSkia.cpp64
66 files changed, 10032 insertions, 0 deletions
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterMesh.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterMesh.cpp
new file mode 100644
index 000000000..40ec330d4
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterMesh.cpp
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2011 Adobe Systems Incorporated. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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(CSS_SHADERS) && ENABLE(WEBGL)
+#include "CustomFilterMesh.h"
+#include "GraphicsContext3D.h"
+
+namespace WebCore {
+
+#ifndef NDEBUG
+// Use "call 'WebCore::s_dumpCustomFilterMeshBuffers' = 1" in GDB to activate printing of the mesh buffers.
+static bool s_dumpCustomFilterMeshBuffers = false;
+#endif
+
+class MeshGenerator {
+public:
+ // Lines and columns are the values passed in CSS. The result is vertex mesh that has 'rows' numbers of rows
+ // and 'columns' number of columns with a total of 'rows + 1' * 'columns + 1' vertices.
+ // MeshBox is the filtered area calculated defined using the border-box, padding-box, content-box or filter-box
+ // attributes. A value of (0, 0, 1, 1) will cover the entire output surface.
+ MeshGenerator(unsigned columns, unsigned rows, const FloatRect& meshBox, CustomFilterOperation::MeshType meshType)
+ : m_meshType(meshType)
+ , m_points(columns + 1, rows + 1)
+ , m_tiles(columns, rows)
+ , m_tileSizeInPixels(meshBox.width() / m_tiles.width(), meshBox.height() / m_tiles.height())
+ , m_tileSizeInDeviceSpace(1.0f / m_tiles.width(), 1.0f / m_tiles.height())
+ , m_meshBox(meshBox)
+ {
+ // Build the two buffers needed to draw triangles:
+ // * m_vertices has a number of float attributes that will be passed to the vertex shader
+ // for each computed vertex. This number is calculated in floatsPerVertex() based on the meshType.
+ // * m_indices is a buffer that will have 3 indices per triangle. Each index will point inside
+ // the m_vertices buffer.
+ m_vertices.reserveCapacity(verticesCount() * floatsPerVertex());
+ m_indices.reserveCapacity(indicesCount());
+
+ // Based on the meshType there can be two types of meshes.
+ // * attached: each triangle uses vertices from the neighbor triangles. This is useful to save some GPU memory
+ // when there's no need to explode the tiles.
+ // * detached: each triangle has its own vertices. This means each triangle can be moved independently and a vec3
+ // attribute is passed, so that each vertex can be uniquely identified.
+ if (m_meshType == CustomFilterOperation::ATTACHED)
+ generateAttachedMesh();
+ else
+ generateDetachedMesh();
+
+#ifndef NDEBUG
+ if (s_dumpCustomFilterMeshBuffers)
+ dumpBuffers();
+#endif
+ }
+
+ const Vector<float>& vertices() const { return m_vertices; }
+ const Vector<uint16_t>& indices() const { return m_indices; }
+
+ const IntSize& points() const { return m_points; }
+ unsigned pointsCount() const { return m_points.width() * m_points.height(); }
+
+ const IntSize& tiles() const { return m_tiles; }
+ unsigned tilesCount() const { return m_tiles.width() * m_tiles.height(); }
+
+ unsigned indicesCount() const
+ {
+ const unsigned trianglesPerTile = 2;
+ const unsigned indicesPerTriangle = 3;
+ return tilesCount() * trianglesPerTile * indicesPerTriangle;
+ }
+
+ unsigned floatsPerVertex() const
+ {
+ static const unsigned AttachedMeshVertexSize = 4 + // vec4 a_position
+ 2 + // vec2 a_texCoord
+ 2; // vec2 a_meshCoord
+
+ static const unsigned DetachedMeshVertexSize = AttachedMeshVertexSize +
+ 3; // vec3 a_triangleCoord
+
+ return m_meshType == CustomFilterOperation::ATTACHED ? AttachedMeshVertexSize : DetachedMeshVertexSize;
+ }
+
+ unsigned verticesCount() const
+ {
+ return m_meshType == CustomFilterOperation::ATTACHED ? pointsCount() : indicesCount();
+ }
+
+private:
+ typedef void (MeshGenerator::*AddTriangleVertexFunction)(int quadX, int quadY, int triangleX, int triangleY, int triangle);
+
+ template <AddTriangleVertexFunction addTriangleVertex>
+ void addTile(int quadX, int quadY)
+ {
+ ((*this).*(addTriangleVertex))(quadX, quadY, 0, 0, 1);
+ ((*this).*(addTriangleVertex))(quadX, quadY, 1, 0, 2);
+ ((*this).*(addTriangleVertex))(quadX, quadY, 1, 1, 3);
+ ((*this).*(addTriangleVertex))(quadX, quadY, 0, 0, 4);
+ ((*this).*(addTriangleVertex))(quadX, quadY, 1, 1, 5);
+ ((*this).*(addTriangleVertex))(quadX, quadY, 0, 1, 6);
+ }
+
+ void addAttachedMeshIndex(int quadX, int quadY, int triangleX, int triangleY, int triangle)
+ {
+ UNUSED_PARAM(triangle);
+ m_indices.append((quadY + triangleY) * m_points.width() + (quadX + triangleX));
+ }
+
+ void generateAttachedMesh()
+ {
+ for (int j = 0; j < m_points.height(); ++j) {
+ for (int i = 0; i < m_points.width(); ++i)
+ addAttachedMeshVertexAttributes(i, j);
+ }
+
+ for (int j = 0; j < m_tiles.height(); ++j) {
+ for (int i = 0; i < m_tiles.width(); ++i)
+ addTile<&MeshGenerator::addAttachedMeshIndex>(i, j);
+ }
+ }
+
+ void addDetachedMeshVertexAndIndex(int quadX, int quadY, int triangleX, int triangleY, int triangle)
+ {
+ addDetachedMeshVertexAttributes(quadX, quadY, triangleX, triangleY, triangle);
+ m_indices.append(m_indices.size());
+ }
+
+ void generateDetachedMesh()
+ {
+ for (int j = 0; j < m_tiles.height(); ++j) {
+ for (int i = 0; i < m_tiles.width(); ++i)
+ addTile<&MeshGenerator::addDetachedMeshVertexAndIndex>(i, j);
+ }
+ }
+
+ void addPositionAttribute(int quadX, int quadY)
+ {
+ // vec4 a_position
+ m_vertices.append(m_tileSizeInPixels.width() * quadX - 0.5f + m_meshBox.x());
+ m_vertices.append(m_tileSizeInPixels.height() * quadY - 0.5f + m_meshBox.y());
+ m_vertices.append(0.0f); // z
+ m_vertices.append(1.0f);
+ }
+
+ void addTexCoordAttribute(int quadX, int quadY)
+ {
+ // vec2 a_texCoord
+ m_vertices.append(m_tileSizeInPixels.width() * quadX + m_meshBox.x());
+ m_vertices.append(m_tileSizeInPixels.height() * quadY + m_meshBox.y());
+ }
+
+ void addMeshCoordAttribute(int quadX, int quadY)
+ {
+ // vec2 a_meshCoord
+ m_vertices.append(m_tileSizeInDeviceSpace.width() * quadX);
+ m_vertices.append(m_tileSizeInDeviceSpace.height() * quadY);
+ }
+
+ void addTriangleCoordAttribute(int quadX, int quadY, int triangle)
+ {
+ // vec3 a_triangleCoord
+ m_vertices.append(quadX);
+ m_vertices.append(quadY);
+ m_vertices.append(triangle);
+ }
+
+ void addAttachedMeshVertexAttributes(int quadX, int quadY)
+ {
+ addPositionAttribute(quadX, quadY);
+ addTexCoordAttribute(quadX, quadY);
+ addMeshCoordAttribute(quadX, quadY);
+ }
+
+ void addDetachedMeshVertexAttributes(int quadX, int quadY, int triangleX, int triangleY, int triangle)
+ {
+ addAttachedMeshVertexAttributes(quadX + triangleX, quadY + triangleY);
+ addTriangleCoordAttribute(quadX, quadY, triangle);
+ }
+
+#ifndef NDEBUG
+ void dumpBuffers() const
+ {
+ printf("Mesh buffers: Points.width(): %d, Points.height(): %d meshBox: %f, %f, %f, %f, type: %s\n",
+ m_points.width(), m_points.height(), m_meshBox.x(), m_meshBox.y(), m_meshBox.width(), m_meshBox.height(),
+ (m_meshType == CustomFilterOperation::ATTACHED) ? "Attached" : "Detached");
+ printf("---Vertex:\n\t");
+ for (unsigned i = 0; i < m_vertices.size(); ++i) {
+ printf("%f ", m_vertices.at(i));
+ if (!((i + 1) % floatsPerVertex()))
+ printf("\n\t");
+ }
+ printf("\n---Indices: ");
+ for (unsigned i = 0; i < m_indices.size(); ++i)
+ printf("%d ", m_indices.at(i));
+ printf("\n");
+ }
+#endif
+
+private:
+ Vector<float> m_vertices;
+ Vector<uint16_t> m_indices;
+
+ CustomFilterOperation::MeshType m_meshType;
+ IntSize m_points;
+ IntSize m_tiles;
+ FloatSize m_tileSizeInPixels;
+ FloatSize m_tileSizeInDeviceSpace;
+ FloatRect m_meshBox;
+};
+
+CustomFilterMesh::CustomFilterMesh(GraphicsContext3D* context, unsigned columns, unsigned rows,
+ const FloatRect& meshBox, CustomFilterOperation::MeshType meshType)
+ : m_context(context)
+ , m_verticesBufferObject(0)
+ , m_elementsBufferObject(0)
+ , m_meshBox(meshBox)
+ , m_meshType(meshType)
+{
+ MeshGenerator generator(columns, rows, meshBox, meshType);
+ m_indicesCount = generator.indicesCount();
+ m_bytesPerVertex = generator.floatsPerVertex() * sizeof(float);
+
+ m_verticesBufferObject = m_context->createBuffer();
+ m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_verticesBufferObject);
+ m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, generator.vertices().size() * sizeof(float), generator.vertices().data(), GraphicsContext3D::STATIC_DRAW);
+
+ m_elementsBufferObject = m_context->createBuffer();
+ m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, m_elementsBufferObject);
+ m_context->bufferData(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, generator.indices().size() * sizeof(uint16_t), generator.indices().data(), GraphicsContext3D::STATIC_DRAW);
+}
+
+CustomFilterMesh::~CustomFilterMesh()
+{
+ m_context->deleteBuffer(m_verticesBufferObject);
+ m_context->deleteBuffer(m_elementsBufferObject);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_SHADERS) && ENABLE(WEBGL)
+
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterMesh.h b/Source/WebCore/platform/graphics/filters/CustomFilterMesh.h
new file mode 100644
index 000000000..b557d3eaf
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterMesh.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2011 Adobe Systems Incorporated. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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 CustomFilterMesh_h
+#define CustomFilterMesh_h
+
+#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL)
+
+#include "CustomFilterOperation.h"
+#include "FloatRect.h"
+#include "GraphicsTypes3D.h"
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class GraphicsContext3D;
+
+class CustomFilterMesh : public RefCounted<CustomFilterMesh> {
+public:
+ static PassRefPtr<CustomFilterMesh> create(GraphicsContext3D* context, unsigned cols, unsigned rows, const FloatRect& meshBox, CustomFilterOperation::MeshType meshType)
+ {
+ return adoptRef(new CustomFilterMesh(context, cols, rows, meshBox, meshType));
+ }
+ ~CustomFilterMesh();
+
+ Platform3DObject verticesBufferObject() const { return m_verticesBufferObject; }
+ unsigned bytesPerVertex() const { return m_bytesPerVertex; }
+
+ Platform3DObject elementsBufferObject() const { return m_elementsBufferObject; }
+ unsigned indicesCount() const { return m_indicesCount; }
+
+ const FloatRect& meshBox() const { return m_meshBox; }
+ CustomFilterOperation::MeshType meshType() const { return m_meshType; }
+
+private:
+ CustomFilterMesh(GraphicsContext3D*, unsigned cols, unsigned rows, const FloatRect& meshBox, CustomFilterOperation::MeshType);
+
+ GraphicsContext3D* m_context;
+
+ Platform3DObject m_verticesBufferObject;
+ unsigned m_bytesPerVertex;
+
+ Platform3DObject m_elementsBufferObject;
+ unsigned m_indicesCount;
+
+ FloatRect m_meshBox;
+ CustomFilterOperation::MeshType m_meshType;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_SHADERS) && ENABLE(WEBGL)
+
+#endif // CustomFilterMesh_h
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterShader.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterShader.cpp
new file mode 100644
index 000000000..6df78de97
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterShader.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2011 Adobe Systems Incorporated. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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(CSS_SHADERS) && ENABLE(WEBGL)
+#include "CustomFilterShader.h"
+#include "GraphicsContext3D.h"
+
+namespace WebCore {
+
+#define SHADER(Src) (#Src)
+
+String CustomFilterShader::defaultVertexShaderString()
+{
+ DEFINE_STATIC_LOCAL(String, vertexShaderString, SHADER(
+ precision mediump float;
+ attribute vec4 a_position;
+ attribute vec2 a_texCoord;
+ uniform mat4 u_projectionMatrix;
+ varying vec2 v_texCoord;
+ void main()
+ {
+ gl_Position = u_projectionMatrix * a_position;
+ v_texCoord = a_texCoord;
+ }
+ ));
+ return vertexShaderString;
+}
+
+String CustomFilterShader::defaultFragmentShaderString()
+{
+ DEFINE_STATIC_LOCAL(String, fragmentShaderString, SHADER(
+ precision mediump float;
+ varying vec2 v_texCoord;
+ uniform sampler2D s_texture;
+ void main()
+ {
+ gl_FragColor = texture2D(s_texture, v_texCoord);
+ }
+ ));
+ return fragmentShaderString;
+}
+
+CustomFilterShader::CustomFilterShader(GraphicsContext3D* context, const String& vertexShaderString, const String& fragmentShaderString)
+ : m_context(context)
+ , m_vertexShaderString(!vertexShaderString.isNull() ? vertexShaderString : defaultVertexShaderString())
+ , m_fragmentShaderString(!fragmentShaderString.isNull() ? fragmentShaderString : defaultFragmentShaderString())
+ , m_program(0)
+ , m_positionAttribLocation(-1)
+ , m_texAttribLocation(-1)
+ , m_meshAttribLocation(-1)
+ , m_triangleAttribLocation(-1)
+ , m_meshBoxLocation(-1)
+ , m_projectionMatrixLocation(-1)
+ , m_tileSizeLocation(-1)
+ , m_meshSizeLocation(-1)
+ , m_samplerLocation(-1)
+ , m_samplerSizeLocation(-1)
+ , m_contentSamplerLocation(-1)
+ , m_isInitialized(false)
+{
+ Platform3DObject vertexShader = compileShader(GraphicsContext3D::VERTEX_SHADER, m_vertexShaderString);
+ if (!vertexShader)
+ return;
+
+ Platform3DObject fragmentShader = compileShader(GraphicsContext3D::FRAGMENT_SHADER, m_fragmentShaderString);
+ if (!fragmentShader) {
+ m_context->deleteShader(vertexShader);
+ return;
+ }
+
+ m_program = linkProgram(vertexShader, fragmentShader);
+
+ m_context->deleteShader(vertexShader);
+ m_context->deleteShader(fragmentShader);
+
+ if (!m_program)
+ return;
+
+ initializeParameterLocations();
+
+ m_isInitialized = true;
+}
+
+Platform3DObject CustomFilterShader::compileShader(GC3Denum shaderType, const String& shaderString)
+{
+ Platform3DObject shader = m_context->createShader(shaderType);
+ m_context->shaderSource(shader, shaderString);
+ m_context->compileShader(shader);
+
+ int compiled = 0;
+ m_context->getShaderiv(shader, GraphicsContext3D::COMPILE_STATUS, &compiled);
+ if (!compiled) {
+ // FIXME: This is an invalid shader. Throw some errors.
+ // https://bugs.webkit.org/show_bug.cgi?id=74416
+ m_context->deleteShader(shader);
+ return 0;
+ }
+
+ return shader;
+}
+
+Platform3DObject CustomFilterShader::linkProgram(Platform3DObject vertexShader, Platform3DObject fragmentShader)
+{
+ Platform3DObject program = m_context->createProgram();
+ m_context->attachShader(program, vertexShader);
+ m_context->attachShader(program, fragmentShader);
+ m_context->linkProgram(program);
+
+ int linked = 0;
+ m_context->getProgramiv(program, GraphicsContext3D::LINK_STATUS, &linked);
+ if (!linked) {
+ // FIXME: Invalid vertex/fragment shader combination. Throw some errors here.
+ // https://bugs.webkit.org/show_bug.cgi?id=74416
+ m_context->deleteProgram(program);
+ return 0;
+ }
+
+ return program;
+}
+
+void CustomFilterShader::initializeParameterLocations()
+{
+ m_positionAttribLocation = m_context->getAttribLocation(m_program, "a_position");
+ m_texAttribLocation = m_context->getAttribLocation(m_program, "a_texCoord");
+ m_meshAttribLocation = m_context->getAttribLocation(m_program, "a_meshCoord");
+ m_triangleAttribLocation = m_context->getAttribLocation(m_program, "a_triangleCoord");
+ m_meshBoxLocation = m_context->getUniformLocation(m_program, "u_meshBox");
+ m_tileSizeLocation = m_context->getUniformLocation(m_program, "u_tileSize");
+ m_meshSizeLocation = m_context->getUniformLocation(m_program, "u_meshSize");
+ m_projectionMatrixLocation = m_context->getUniformLocation(m_program, "u_projectionMatrix");
+ m_samplerLocation = m_context->getUniformLocation(m_program, "s_texture");
+ m_samplerSizeLocation = m_context->getUniformLocation(m_program, "s_textureSize");
+ m_contentSamplerLocation = m_context->getUniformLocation(m_program, "s_contentTexture");
+}
+
+CustomFilterShader::~CustomFilterShader()
+{
+ if (m_program)
+ m_context->deleteProgram(m_program);
+}
+
+} // namespace WebCore
+#endif // ENABLE(CSS_SHADERS) && ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterShader.h b/Source/WebCore/platform/graphics/filters/CustomFilterShader.h
new file mode 100644
index 000000000..90602cb1e
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/CustomFilterShader.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2011 Adobe Systems Incorporated. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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 CustomFilterShader_h
+#define CustomFilterShader_h
+
+#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL)
+
+#include "GraphicsTypes3D.h"
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class GraphicsContext3D;
+
+class CustomFilterShader: public RefCounted<CustomFilterShader> {
+public:
+ static PassRefPtr<CustomFilterShader> create(GraphicsContext3D* context, const String& vertexShader, const String& fragmentShader)
+ {
+ return adoptRef(new CustomFilterShader(context, vertexShader, fragmentShader));
+ }
+
+ ~CustomFilterShader();
+
+ String vertexShaderString() const { return m_vertexShaderString; }
+ String fragmentShaderString() const { return m_fragmentShaderString; }
+
+ int positionAttribLocation() const { return m_positionAttribLocation; }
+ int texAttribLocation() const { return m_texAttribLocation; }
+ int meshAttribLocation() const { return m_meshAttribLocation; }
+ int triangleAttribLocation() const { return m_triangleAttribLocation; }
+ int meshBoxLocation() const { return m_meshBoxLocation; }
+ int projectionMatrixLocation() const { return m_projectionMatrixLocation; }
+ int tileSizeLocation() const { return m_tileSizeLocation; }
+ int meshSizeLocation() const { return m_meshSizeLocation; }
+ int samplerLocation() const { return m_samplerLocation; }
+ int contentSamplerLocation() const { return m_contentSamplerLocation; }
+ int samplerSizeLocation() const { return m_samplerSizeLocation; }
+
+ bool isInitialized() const { return m_isInitialized; }
+
+ Platform3DObject program() const { return m_program; }
+
+private:
+ CustomFilterShader(GraphicsContext3D*, const String& vertexShader, const String& fragmentShader);
+
+ Platform3DObject compileShader(GC3Denum shaderType, const String& shaderString);
+ Platform3DObject linkProgram(Platform3DObject vertexShader, Platform3DObject fragmentShader);
+ void initializeParameterLocations();
+
+ static String defaultVertexShaderString();
+ static String defaultFragmentShaderString();
+
+ RefPtr<GraphicsContext3D> m_context;
+
+ String m_vertexShaderString;
+ String m_fragmentShaderString;
+
+ Platform3DObject m_program;
+
+ int m_positionAttribLocation;
+ int m_texAttribLocation;
+ int m_meshAttribLocation;
+ int m_triangleAttribLocation;
+ int m_meshBoxLocation;
+ int m_projectionMatrixLocation;
+ int m_tileSizeLocation;
+ int m_meshSizeLocation;
+ int m_samplerLocation;
+ int m_samplerSizeLocation;
+ int m_contentSamplerLocation;
+
+ bool m_isInitialized;
+};
+
+}
+
+#endif // ENABLE(CSS_SHADERS) && ENABLE(WEBGL)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/filters/DistantLightSource.cpp b/Source/WebCore/platform/graphics/filters/DistantLightSource.cpp
new file mode 100644
index 000000000..4c3b49b3b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/DistantLightSource.cpp
@@ -0,0 +1,80 @@
+/*
+ * 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>
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
+ *
+ * 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 "DistantLightSource.h"
+
+#include "RenderTreeAsText.h"
+
+namespace WebCore {
+
+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)
+{
+}
+
+bool DistantLightSource::setAzimuth(float azimuth)
+{
+ if (m_azimuth == azimuth)
+ return false;
+ m_azimuth = azimuth;
+ return true;
+}
+
+bool DistantLightSource::setElevation(float elevation)
+{
+ if (m_elevation == elevation)
+ return false;
+ m_elevation = elevation;
+ return true;
+}
+
+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/DistantLightSource.h b/Source/WebCore/platform/graphics/filters/DistantLightSource.h
new file mode 100644
index 000000000..1e19c62bd
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/DistantLightSource.h
@@ -0,0 +1,64 @@
+/*
+ * 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; }
+ bool setAzimuth(float);
+ float elevation() const { return m_elevation; }
+ bool setElevation(float);
+
+ 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 000000000..530636da9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FEBlend.cpp
@@ -0,0 +1,188 @@
+/*
+ * 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 "RenderTreeAsText.h"
+#include "TextStream.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;
+}
+
+bool FEBlend::setBlendMode(BlendModeType mode)
+{
+ if (m_mode == mode)
+ return false;
+ m_mode = mode;
+ return true;
+}
+
+static inline unsigned char normal(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char)
+{
+ return (((255 - alphaA) * colorB + colorA * 255) / 255);
+}
+
+static inline 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 inline unsigned char screen(unsigned char colorA, unsigned char colorB, unsigned char, unsigned char)
+{
+ return (((colorB + colorA) * 255 - colorA * colorB) / 255);
+}
+
+static inline 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 inline 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::platformApplySoftware()
+{
+ FilterEffect* in = inputEffect(0);
+ FilterEffect* in2 = inputEffect(1);
+
+ ASSERT(m_mode > FEBLEND_MODE_UNKNOWN);
+ ASSERT(m_mode <= FEBLEND_MODE_LIGHTEN);
+
+ 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);
+
+ 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;
+
+ switch (m_mode) {
+ case FEBLEND_MODE_NORMAL:
+ result = normal(colorA, colorB, alphaA, alphaB);
+ break;
+ case FEBLEND_MODE_MULTIPLY:
+ result = multiply(colorA, colorB, alphaA, alphaB);
+ break;
+ case FEBLEND_MODE_SCREEN:
+ result = screen(colorA, colorB, alphaA, alphaB);
+ break;
+ case FEBLEND_MODE_DARKEN:
+ result = darken(colorA, colorB, alphaA, alphaB);
+ break;
+ case FEBLEND_MODE_LIGHTEN:
+ result = lighten(colorA, colorB, alphaA, alphaB);
+ break;
+ case FEBLEND_MODE_UNKNOWN:
+ default:
+ result = 0;
+ break;
+ }
+
+ 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 000000000..68cd1d37a
--- /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;
+ bool setBlendMode(BlendModeType);
+
+ virtual void platformApplySoftware();
+ 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 000000000..ed6cb90dc
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp
@@ -0,0 +1,244 @@
+/*
+ * 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 "RenderTreeAsText.h"
+#include "TextStream.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;
+}
+
+bool FEColorMatrix::setType(ColorMatrixType type)
+{
+ if (m_type == type)
+ return false;
+ m_type = type;
+ return true;
+}
+
+const Vector<float>& FEColorMatrix::values() const
+{
+ return m_values;
+}
+
+bool FEColorMatrix::setValues(const Vector<float> &values)
+{
+ if (m_values == values)
+ return false;
+ m_values = values;
+ return true;
+}
+
+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::platformApplySoftware()
+{
+ FilterEffect* in = inputEffect(0);
+
+ 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 000000000..d03b6d376
--- /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;
+ bool setType(ColorMatrixType);
+
+ const Vector<float>& values() const;
+ bool setValues(const Vector<float>&);
+
+ virtual void platformApplySoftware();
+ 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 000000000..8db62dc4d
--- /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 "RenderTreeAsText.h"
+#include "TextStream.h"
+
+#include <wtf/ByteArray.h>
+#include <wtf/MathExtras.h>
+#include <wtf/StdLibExtras.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::platformApplySoftware()
+{
+ FilterEffect* in = inputEffect(0);
+
+ 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++) {
+ ASSERT(static_cast<size_t>(transferFunction[channel].type) < WTF_ARRAY_LENGTH(callEffect));
+ (*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 000000000..d461deff0
--- /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 platformApplySoftware();
+ 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 000000000..c64d02c8a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FEComposite.cpp
@@ -0,0 +1,312 @@
+/*
+ * 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 "FECompositeArithmeticNEON.h"
+#include "Filter.h"
+#include "GraphicsContext.h"
+#include "RenderTreeAsText.h"
+#include "TextStream.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;
+}
+
+bool FEComposite::setOperation(CompositeOperationType type)
+{
+ if (m_type == type)
+ return false;
+ m_type = type;
+ return true;
+}
+
+float FEComposite::k1() const
+{
+ return m_k1;
+}
+
+bool FEComposite::setK1(float k1)
+{
+ if (m_k1 == k1)
+ return false;
+ m_k1 = k1;
+ return true;
+}
+
+float FEComposite::k2() const
+{
+ return m_k2;
+}
+
+bool FEComposite::setK2(float k2)
+{
+ if (m_k2 == k2)
+ return false;
+ m_k2 = k2;
+ return true;
+}
+
+float FEComposite::k3() const
+{
+ return m_k3;
+}
+
+bool FEComposite::setK3(float k3)
+{
+ if (m_k3 == k3)
+ return false;
+ m_k3 = k3;
+ return true;
+}
+
+float FEComposite::k4() const
+{
+ return m_k4;
+}
+
+bool FEComposite::setK4(float k4)
+{
+ if (m_k4 == k4)
+ return false;
+ m_k4 = k4;
+ return true;
+}
+
+template <int b1, int b2, int b3, int b4>
+static inline void computeArithmeticPixels(unsigned char* source, unsigned char* destination, int pixelArrayLength,
+ float k1, float k2, float k3, float k4)
+{
+ float scaledK1;
+ float scaledK4;
+ 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;
+ }
+}
+
+static inline void arithmeticSoftware(unsigned char* source, unsigned char* destination, int pixelArrayLength,
+ float k1, float k2, float k3, float k4)
+{
+ 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);
+}
+
+inline void FEComposite::platformArithmeticSoftware(ByteArray* source, ByteArray* destination,
+ float k1, float k2, float k3, float k4)
+{
+ int length = source->length();
+ ASSERT(length == static_cast<int>(destination->length()));
+ // The selection here eventually should happen dynamically.
+#if CPU(ARM_NEON) && COMPILER(GCC)
+ ASSERT(!(length & 0x3));
+ float coefficients[4] = { k1, k2, k3, k4 };
+ platformArithmeticNeon(source->data(), destination->data(), length, coefficients);
+#else
+ arithmeticSoftware(source->data(), destination->data(), length, k1, k2, k3, k4);
+#endif
+}
+
+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(enclosingIntRect(maxEffectRect()));
+ return;
+ default:
+ // Take the union of both input effects.
+ FilterEffect::determineAbsolutePaintRect();
+ return;
+ }
+}
+
+void FEComposite::platformApplySoftware()
+{
+ FilterEffect* in = inputEffect(0);
+ FilterEffect* in2 = inputEffect(1);
+
+ 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);
+
+ platformArithmeticSoftware(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: {
+ GraphicsContextStateSaver stateSaver(*filterContext);
+ filterContext->clipToImageBuffer(in2->asImageBuffer(), drawingRegionOfInputImage(in2->absolutePaintRect()));
+ filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
+ 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 000000000..35f2505e3
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FEComposite.h
@@ -0,0 +1,86 @@
+/*
+ * 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;
+ bool setOperation(CompositeOperationType);
+
+ float k1() const;
+ bool setK1(float);
+
+ float k2() const;
+ bool setK2(float);
+
+ float k3() const;
+ bool setK3(float);
+
+ float k4() const;
+ bool setK4(float);
+
+ virtual void platformApplySoftware();
+ virtual void dump();
+
+ virtual void determineAbsolutePaintRect();
+
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+
+private:
+ FEComposite(Filter*, const CompositeOperationType&, float, float, float, float);
+
+ inline void platformArithmeticSoftware(ByteArray* source, ByteArray* destination, float k1, float k2, float k3, float k4);
+ inline void platformArithmeticNeon(unsigned char* source, unsigned char* destination, unsigned pixelArrayLength, float* kArray);
+
+ 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 000000000..cda5f193e
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp
@@ -0,0 +1,521 @@
+/*
+ * 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 "RenderTreeAsText.h"
+#include "TextStream.h"
+
+#include <wtf/ByteArray.h>
+#include <wtf/ParallelJobs.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(const 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;
+}
+
+bool FEConvolveMatrix::setDivisor(float divisor)
+{
+ if (m_divisor == divisor)
+ return false;
+ m_divisor = divisor;
+ return true;
+}
+
+float FEConvolveMatrix::bias() const
+{
+ return m_bias;
+}
+
+bool FEConvolveMatrix::setBias(float bias)
+{
+ if (m_bias == bias)
+ return false;
+ m_bias = bias;
+ return true;
+}
+
+IntPoint FEConvolveMatrix::targetOffset() const
+{
+ return m_targetOffset;
+}
+
+bool FEConvolveMatrix::setTargetOffset(const IntPoint& targetOffset)
+{
+ if (m_targetOffset == targetOffset)
+ return false;
+ m_targetOffset = targetOffset;
+ return true;
+}
+
+EdgeModeType FEConvolveMatrix::edgeMode() const
+{
+ return m_edgeMode;
+}
+
+bool FEConvolveMatrix::setEdgeMode(EdgeModeType edgeMode)
+{
+ if (m_edgeMode == edgeMode)
+ return false;
+ m_edgeMode = edgeMode;
+ return true;
+}
+
+FloatPoint FEConvolveMatrix::kernelUnitLength() const
+{
+ return m_kernelUnitLength;
+}
+
+bool FEConvolveMatrix::setKernelUnitLength(const FloatPoint& kernelUnitLength)
+{
+ if (m_kernelUnitLength == kernelUnitLength)
+ return false;
+ m_kernelUnitLength = kernelUnitLength;
+ return true;
+}
+
+bool FEConvolveMatrix::preserveAlpha() const
+{
+ return m_preserveAlpha;
+}
+
+bool FEConvolveMatrix::setPreserveAlpha(bool preserveAlpha)
+{
+ if (m_preserveAlpha == preserveAlpha)
+ return false;
+ m_preserveAlpha = preserveAlpha;
+ return true;
+}
+
+/*
+ -----------------------------------
+ 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, int yStart, int yEnd)
+{
+ // edge mode does not affect these pixels
+ int pixel = (m_targetOffset.y() * paintingData.width + m_targetOffset.x()) * 4;
+ 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);
+
+ // Skip the first '(clipBottom - yEnd)' lines
+ pixel += (clipBottom - yEnd) * (xIncrease + (clipRight + 1) * 4);
+ int startKernelPixel = (clipBottom - yEnd) * (xIncrease + (clipRight + 1) * 4);
+
+ for (int y = yEnd + 1; y > yStart; --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 && y >= 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, int yStart, int yEnd)
+{
+ // 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, yStart, yEnd);
+ else
+ fastSetInteriorPixels<false>(paintingData, clipRight, clipBottom, yStart, yEnd);
+}
+
+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::setInteriorPixelsWorker(InteriorPixelParameters* param)
+{
+ param->filter->setInteriorPixels(*param->paintingData, param->clipRight, param->clipBottom, param->yStart, param->yEnd);
+}
+
+void FEConvolveMatrix::platformApplySoftware()
+{
+ FilterEffect* in = inputEffect(0);
+
+ 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) {
+
+ int optimalThreadNumber = (absolutePaintRect().width() * absolutePaintRect().height()) / s_minimalRectDimension;
+ if (optimalThreadNumber > 1) {
+ WTF::ParallelJobs<InteriorPixelParameters> parallelJobs(&WebCore::FEConvolveMatrix::setInteriorPixelsWorker, optimalThreadNumber);
+ const int numOfThreads = parallelJobs.numberOfJobs();
+ const int heightPerThread = clipBottom / numOfThreads;
+ int startY = 0;
+
+ for (int job = 0; job < numOfThreads; ++job) {
+ InteriorPixelParameters& param = parallelJobs.parameter(job);
+ param.filter = this;
+ param.paintingData = &paintingData;
+ param.clipRight = clipRight;
+ param.clipBottom = clipBottom;
+ param.yStart = startY;
+ if (job < numOfThreads - 1) {
+ startY += heightPerThread;
+ param.yEnd = startY - 1;
+ } else
+ param.yEnd = clipBottom;
+ }
+
+ parallelJobs.execute();
+ } else {
+ // Fallback to single threaded mode.
+ setInteriorPixels(paintingData, clipRight, clipBottom, 0, 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 000000000..34baf6f17
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.h
@@ -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>
+ * 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(const IntSize&);
+
+ const Vector<float>& kernel() const;
+ void setKernel(const Vector<float>&);
+
+ float divisor() const;
+ bool setDivisor(float);
+
+ float bias() const;
+ bool setBias(float);
+
+ IntPoint targetOffset() const;
+ bool setTargetOffset(const IntPoint&);
+
+ EdgeModeType edgeMode() const;
+ bool setEdgeMode(EdgeModeType);
+
+ FloatPoint kernelUnitLength() const;
+ bool setKernelUnitLength(const FloatPoint&);
+
+ bool preserveAlpha() const;
+ bool setPreserveAlpha(bool);
+
+ virtual void platformApplySoftware();
+ virtual void dump();
+
+ virtual void determineAbsolutePaintRect() { setAbsolutePaintRect(enclosingIntRect(maxEffectRect())); }
+
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+
+private:
+
+ struct PaintingData {
+ ByteArray* srcPixelArray;
+ ByteArray* dstPixelArray;
+ int width;
+ int height;
+ float bias;
+ };
+
+ FEConvolveMatrix(Filter*, const IntSize&, float, float,
+ const IntPoint&, EdgeModeType, const FloatPoint&, bool, const Vector<float>&);
+
+ template<bool preserveAlphaValues>
+ ALWAYS_INLINE void fastSetInteriorPixels(PaintingData&, int clipRight, int clipBottom, int yStart, int yEnd);
+
+ 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&, int clipRight, int clipBottom, int yStart, int yEnd);
+ ALWAYS_INLINE void setOuterPixels(PaintingData&, int x1, int y1, int x2, int y2);
+
+ // Parallelization parts
+ static const int s_minimalRectDimension = (100 * 100); // Empirical data limit for parallel jobs
+
+ template<typename Type>
+ friend class ParallelJobs;
+
+ struct InteriorPixelParameters {
+ FEConvolveMatrix* filter;
+ PaintingData* paintingData;
+ int clipBottom;
+ int clipRight;
+ int yStart;
+ int yEnd;
+ };
+
+ static void setInteriorPixelsWorker(InteriorPixelParameters*);
+
+ 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/FECustomFilter.cpp b/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp
new file mode 100644
index 000000000..fb4270e47
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2011 Adobe Systems Incorporated. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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(CSS_SHADERS) && ENABLE(WEBGL)
+#include "FECustomFilter.h"
+
+#include "CachedShader.h"
+#include "CustomFilterMesh.h"
+#include "CustomFilterShader.h"
+#include "Document.h"
+#include "DrawingBuffer.h"
+#include "FrameView.h"
+#include "GraphicsContext3D.h"
+#include "ImageData.h"
+#include "RenderTreeAsText.h"
+#include "StyleCachedShader.h"
+#include "TextStream.h"
+#include "Texture.h"
+#include "TilingData.h"
+#include "TransformationMatrix.h"
+
+#include <wtf/ByteArray.h>
+
+namespace WebCore {
+
+static void orthogonalProjectionMatrix(TransformationMatrix& matrix, float left, float right, float bottom, float top)
+{
+ ASSERT(matrix.isIdentity());
+
+ float deltaX = right - left;
+ float deltaY = top - bottom;
+ if (!deltaX || !deltaY)
+ return;
+ matrix.setM11(2.0f / deltaX);
+ matrix.setM41(-(right + left) / deltaX);
+ matrix.setM22(2.0f / deltaY);
+ matrix.setM42(-(top + bottom) / deltaY);
+
+ // Use big enough near/far values, so that simple rotations of rather large objects will not
+ // get clipped. 10000 should cover most of the screen resolutions.
+ const float farValue = 10000;
+ const float nearValue = -10000;
+ matrix.setM33(-2.0f / (farValue - nearValue));
+ matrix.setM43(- (farValue + nearValue) / (farValue - nearValue));
+ matrix.setM44(1.0f);
+}
+
+FECustomFilter::FECustomFilter(Filter* filter, Document* document, const String& vertexShader, const String& fragmentShader,
+ unsigned meshRows, unsigned meshColumns, CustomFilterOperation::MeshBoxType meshBoxType,
+ CustomFilterOperation::MeshType meshType)
+ : FilterEffect(filter)
+ , m_document(document)
+ , m_vertexShader(vertexShader)
+ , m_fragmentShader(fragmentShader)
+ , m_meshRows(meshRows)
+ , m_meshColumns(meshColumns)
+ , m_meshBoxType(meshBoxType)
+ , m_meshType(meshType)
+{
+}
+
+PassRefPtr<FECustomFilter> FECustomFilter::create(Filter* filter, Document* document, const String& vertexShader, const String& fragmentShader,
+ unsigned meshRows, unsigned meshColumns, CustomFilterOperation::MeshBoxType meshBoxType,
+ CustomFilterOperation::MeshType meshType)
+{
+ return adoptRef(new FECustomFilter(filter, document, vertexShader, fragmentShader, meshRows, meshColumns, meshBoxType, meshType));
+}
+
+void FECustomFilter::platformApplySoftware()
+{
+ ByteArray* dstPixelArray = createPremultipliedImageResult();
+ if (!dstPixelArray)
+ return;
+
+ FilterEffect* in = inputEffect(0);
+ IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
+ RefPtr<ByteArray> srcPixelArray = in->asPremultipliedImage(effectDrawingRect);
+
+ IntSize newContextSize(effectDrawingRect.size());
+ bool hadContext = m_context;
+ if (!m_context)
+ initializeContext(newContextSize);
+
+ if (!hadContext || m_contextSize != newContextSize)
+ resizeContext(newContextSize);
+
+ // Do not draw the filter if the input image cannot fit inside a single GPU texture.
+ if (m_inputTexture->tiles().numTiles() != 1)
+ return;
+
+ m_context->clearColor(0, 0, 0, 0);
+ m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT);
+
+ bindProgramAndBuffers(srcPixelArray.get());
+
+ m_context->drawElements(GraphicsContext3D::TRIANGLES, m_mesh->indicesCount(), GraphicsContext3D::UNSIGNED_SHORT, 0);
+
+ m_drawingBuffer->commit();
+
+ RefPtr<ImageData> imageData = m_context->paintRenderingResultsToImageData(m_drawingBuffer.get());
+ ByteArray* gpuResult = imageData->data()->data();
+ ASSERT(gpuResult->length() == dstPixelArray->length());
+ memcpy(dstPixelArray->data(), gpuResult->data(), gpuResult->length());
+}
+
+void FECustomFilter::initializeContext(const IntSize& contextSize)
+{
+ GraphicsContext3D::Attributes attributes;
+ attributes.preserveDrawingBuffer = true;
+ attributes.premultipliedAlpha = false;
+
+ m_context = GraphicsContext3D::create(attributes, m_document->view()->root()->hostWindow(), GraphicsContext3D::RenderOffscreen);
+ m_drawingBuffer = DrawingBuffer::create(m_context.get(), contextSize, !attributes.preserveDrawingBuffer);
+
+ m_shader = CustomFilterShader::create(m_context.get(), m_vertexShader, m_fragmentShader);
+ m_mesh = CustomFilterMesh::create(m_context.get(), m_meshColumns, m_meshRows,
+ FloatRect(0, 0, 1, 1),
+ m_meshType);
+}
+
+void FECustomFilter::resizeContext(const IntSize& newContextSize)
+{
+ m_inputTexture = 0;
+ m_drawingBuffer->reset(newContextSize);
+ m_context->reshape(newContextSize.width(), newContextSize.height());
+ m_context->viewport(0, 0, newContextSize.width(), newContextSize.height());
+ m_inputTexture = Texture::create(m_context.get(), Texture::RGBA8, newContextSize.width(), newContextSize.height());
+ m_contextSize = newContextSize;
+}
+
+void FECustomFilter::bindVertexAttribute(int attributeLocation, unsigned size, unsigned& offset)
+{
+ if (attributeLocation != -1) {
+ m_context->vertexAttribPointer(attributeLocation, 4, GraphicsContext3D::FLOAT, false, m_mesh->bytesPerVertex(), offset);
+ m_context->enableVertexAttribArray(attributeLocation);
+ }
+ offset += size * sizeof(float);
+}
+
+void FECustomFilter::bindProgramAndBuffers(ByteArray* srcPixelArray)
+{
+ m_context->useProgram(m_shader->program());
+
+ if (m_shader->samplerLocation() != -1) {
+ m_context->activeTexture(GraphicsContext3D::TEXTURE0);
+ m_context->uniform1i(m_shader->samplerLocation(), 0);
+ m_inputTexture->load(srcPixelArray->data());
+ m_inputTexture->bindTile(0);
+ }
+
+ if (m_shader->projectionMatrixLocation() != -1) {
+ TransformationMatrix projectionMatrix;
+ orthogonalProjectionMatrix(projectionMatrix, -0.5, 0.5, -0.5, 0.5);
+ float glProjectionMatrix[16];
+ projectionMatrix.toColumnMajorFloatArray(glProjectionMatrix);
+ m_context->uniformMatrix4fv(m_shader->projectionMatrixLocation(), false, &glProjectionMatrix[0], 1);
+ }
+
+ m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_mesh->verticesBufferObject());
+ m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, m_mesh->elementsBufferObject());
+
+ unsigned offset = 0;
+ bindVertexAttribute(m_shader->positionAttribLocation(), 4, offset);
+ bindVertexAttribute(m_shader->texAttribLocation(), 2, offset);
+ bindVertexAttribute(m_shader->meshAttribLocation(), 2, offset);
+ if (m_meshType == CustomFilterOperation::DETACHED)
+ bindVertexAttribute(m_shader->triangleAttribLocation(), 3, offset);
+}
+
+void FECustomFilter::dump()
+{
+}
+
+TextStream& FECustomFilter::externalRepresentation(TextStream& ts, int indent) const
+{
+ writeIndent(ts, indent);
+ ts << "[feCustomFilter";
+ FilterEffect::externalRepresentation(ts);
+ ts << "]\n";
+ inputEffect(0)->externalRepresentation(ts, indent + 1);
+ return ts;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_SHADERS) && ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/filters/FECustomFilter.h b/Source/WebCore/platform/graphics/filters/FECustomFilter.h
new file mode 100644
index 000000000..2aaabf6ba
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FECustomFilter.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2011 Adobe Systems Incorporated. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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 FECustomFilter_h
+#define FECustomFilter_h
+
+#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL)
+
+#include "CustomFilterOperation.h"
+#include "Filter.h"
+#include "FilterEffect.h"
+#include <wtf/RefPtr.h>
+
+namespace JSC {
+class ByteArray;
+}
+
+namespace WebCore {
+
+class CachedShader;
+class CustomFilterMesh;
+class CustomFilterShader;
+class Document;
+class DrawingBuffer;
+class GraphicsContext3D;
+class IntSize;
+class Texture;
+
+class FECustomFilter : public FilterEffect {
+public:
+ static PassRefPtr<FECustomFilter> create(Filter*, Document*, const String& vertexShader, const String& fragmentShader,
+ unsigned meshRows, unsigned meshColumns, CustomFilterOperation::MeshBoxType,
+ CustomFilterOperation::MeshType);
+
+ virtual void platformApplySoftware();
+ virtual void dump();
+
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+
+private:
+ FECustomFilter(Filter*, Document*, const String& vertexShader, const String& fragmentShader,
+ unsigned meshRows, unsigned meshColumns, CustomFilterOperation::MeshBoxType,
+ CustomFilterOperation::MeshType);
+
+ void initializeContext(const IntSize& contextSize);
+ void resizeContext(const IntSize& newContextSize);
+ void bindVertexAttribute(int attributeLocation, unsigned size, unsigned& offset);
+ void bindProgramAndBuffers(ByteArray* srcPixelArray);
+
+ Document* m_document;
+
+ RefPtr<GraphicsContext3D> m_context;
+ RefPtr<DrawingBuffer> m_drawingBuffer;
+ RefPtr<Texture> m_inputTexture;
+ RefPtr<CustomFilterShader> m_shader;
+ RefPtr<CustomFilterMesh> m_mesh;
+ IntSize m_contextSize;
+
+ String m_vertexShader;
+ String m_fragmentShader;
+
+ unsigned m_meshRows;
+ unsigned m_meshColumns;
+ CustomFilterOperation::MeshBoxType m_meshBoxType;
+ CustomFilterOperation::MeshType m_meshType;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_SHADERS) && ENABLE(WEBGL)
+
+#endif // FECustomFilter_h
diff --git a/Source/WebCore/platform/graphics/filters/FEDiffuseLighting.cpp b/Source/WebCore/platform/graphics/filters/FEDiffuseLighting.cpp
new file mode 100644
index 000000000..5f9d049ef
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FEDiffuseLighting.cpp
@@ -0,0 +1,143 @@
+/*
+ * 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"
+#include "RenderTreeAsText.h"
+#include "TextStream.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;
+}
+
+bool FEDiffuseLighting::setLightingColor(const Color& lightingColor)
+{
+ if (m_lightingColor == lightingColor)
+ return false;
+ m_lightingColor = lightingColor;
+ return true;
+}
+
+float FEDiffuseLighting::surfaceScale() const
+{
+ return m_surfaceScale;
+}
+
+bool FEDiffuseLighting::setSurfaceScale(float surfaceScale)
+{
+ if (m_surfaceScale == surfaceScale)
+ return false;
+ m_surfaceScale = surfaceScale;
+ return true;
+}
+
+float FEDiffuseLighting::diffuseConstant() const
+{
+ return m_diffuseConstant;
+}
+
+bool FEDiffuseLighting::setDiffuseConstant(float diffuseConstant)
+{
+ if (m_diffuseConstant == diffuseConstant)
+ return false;
+ m_diffuseConstant = diffuseConstant;
+ return true;
+}
+
+float FEDiffuseLighting::kernelUnitLengthX() const
+{
+ return m_kernelUnitLengthX;
+}
+
+bool FEDiffuseLighting::setKernelUnitLengthX(float kernelUnitLengthX)
+{
+ if (m_kernelUnitLengthX == kernelUnitLengthX)
+ return false;
+ m_kernelUnitLengthX = kernelUnitLengthX;
+ return true;
+}
+
+float FEDiffuseLighting::kernelUnitLengthY() const
+{
+ return m_kernelUnitLengthY;
+}
+
+bool FEDiffuseLighting::setKernelUnitLengthY(float kernelUnitLengthY)
+{
+ if (m_kernelUnitLengthY == kernelUnitLengthY)
+ return false;
+ m_kernelUnitLengthY = kernelUnitLengthY;
+ return true;
+}
+
+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 000000000..5f2065163
--- /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;
+ bool setLightingColor(const Color&);
+
+ float surfaceScale() const;
+ bool setSurfaceScale(float);
+
+ float diffuseConstant() const;
+ bool setDiffuseConstant(float);
+
+ float kernelUnitLengthX() const;
+ bool setKernelUnitLengthX(float);
+
+ float kernelUnitLengthY() const;
+ bool 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 000000000..b0eac449a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp
@@ -0,0 +1,177 @@
+/*
+ * 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 "RenderTreeAsText.h"
+#include "TextStream.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;
+}
+
+bool FEDisplacementMap::setXChannelSelector(const ChannelSelectorType xChannelSelector)
+{
+ if (m_xChannelSelector == xChannelSelector)
+ return false;
+ m_xChannelSelector = xChannelSelector;
+ return true;
+}
+
+ChannelSelectorType FEDisplacementMap::yChannelSelector() const
+{
+ return m_yChannelSelector;
+}
+
+bool FEDisplacementMap::setYChannelSelector(const ChannelSelectorType yChannelSelector)
+{
+ if (m_yChannelSelector == yChannelSelector)
+ return false;
+ m_yChannelSelector = yChannelSelector;
+ return true;
+}
+
+float FEDisplacementMap::scale() const
+{
+ return m_scale;
+}
+
+bool FEDisplacementMap::setScale(float scale)
+{
+ if (m_scale == scale)
+ return false;
+ m_scale = scale;
+ return true;
+}
+
+void FEDisplacementMap::platformApplySoftware()
+{
+ FilterEffect* in = inputEffect(0);
+ FilterEffect* in2 = inputEffect(1);
+
+ ASSERT(m_xChannelSelector != CHANNEL_UNKNOWN);
+ ASSERT(m_yChannelSelector != CHANNEL_UNKNOWN);
+
+ 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 000000000..6d9bdfe3a
--- /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;
+ bool setXChannelSelector(const ChannelSelectorType);
+
+ ChannelSelectorType yChannelSelector() const;
+ bool setYChannelSelector(const ChannelSelectorType);
+
+ float scale() const;
+ bool setScale(float);
+
+ virtual void platformApplySoftware();
+ virtual void dump();
+
+ virtual void determineAbsolutePaintRect() { setAbsolutePaintRect(enclosingIntRect(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/FEDropShadow.cpp b/Source/WebCore/platform/graphics/filters/FEDropShadow.cpp
new file mode 100644
index 000000000..5d807785b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FEDropShadow.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) Research In Motion Limited 2011. 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 "FEDropShadow.h"
+
+#include "ColorSpace.h"
+#include "FEGaussianBlur.h"
+#include "Filter.h"
+#include "GraphicsContext.h"
+#include "RenderTreeAsText.h"
+#include "ShadowBlur.h"
+#include "TextStream.h"
+#include <wtf/ByteArray.h>
+#include <wtf/MathExtras.h>
+
+using namespace std;
+
+namespace WebCore {
+
+FEDropShadow::FEDropShadow(Filter* filter, float stdX, float stdY, float dx, float dy, const Color& shadowColor, float shadowOpacity)
+ : FilterEffect(filter)
+ , m_stdX(stdX)
+ , m_stdY(stdY)
+ , m_dx(dx)
+ , m_dy(dy)
+ , m_shadowColor(shadowColor)
+ , m_shadowOpacity(shadowOpacity)
+{
+}
+
+PassRefPtr<FEDropShadow> FEDropShadow::create(Filter* filter, float stdX, float stdY, float dx, float dy, const Color& shadowColor, float shadowOpacity)
+{
+ return adoptRef(new FEDropShadow(filter, stdX, stdY, dx, dy, shadowColor, shadowOpacity));
+}
+
+void FEDropShadow::determineAbsolutePaintRect()
+{
+ Filter* filter = this->filter();
+ ASSERT(filter);
+
+ FloatRect absolutePaintRect = inputEffect(0)->absolutePaintRect();
+ FloatRect absoluteOffsetPaintRect(absolutePaintRect);
+ absoluteOffsetPaintRect.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy));
+ absolutePaintRect.unite(absoluteOffsetPaintRect);
+ if (clipsToBounds())
+ absolutePaintRect.intersect(maxEffectRect());
+ else
+ absolutePaintRect.unite(maxEffectRect());
+
+ unsigned kernelSizeX = 0;
+ unsigned kernelSizeY = 0;
+ FEGaussianBlur::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 FEDropShadow::platformApplySoftware()
+{
+ FilterEffect* in = inputEffect(0);
+
+ ImageBuffer* resultImage = createImageBufferResult();
+ if (!resultImage)
+ return;
+
+ Filter* filter = this->filter();
+ FloatSize blurRadius(filter->applyHorizontalScale(m_stdX), filter->applyVerticalScale(m_stdY));
+ FloatSize offset(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy));
+
+ FloatRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());
+ FloatRect drawingRegionWithOffset(drawingRegion);
+ drawingRegionWithOffset.move(offset);
+
+ ImageBuffer* sourceImage = in->asImageBuffer();
+ ASSERT(sourceImage);
+ GraphicsContext* resultContext = resultImage->context();
+ ASSERT(resultContext);
+ resultContext->setAlpha(m_shadowOpacity);
+ resultContext->drawImageBuffer(sourceImage, ColorSpaceDeviceRGB, drawingRegionWithOffset);
+ resultContext->setAlpha(1);
+
+ ShadowBlur contextShadow(blurRadius, offset, m_shadowColor, ColorSpaceDeviceRGB);
+
+ // TODO: Direct pixel access to ImageBuffer would avoid copying the ImageData.
+ IntRect shadowArea(IntPoint(), resultImage->size());
+ RefPtr<ByteArray> srcPixelArray = resultImage->getPremultipliedImageData(shadowArea);
+
+ contextShadow.blurLayerImage(srcPixelArray->data(), shadowArea.size(), 4 * shadowArea.size().width());
+
+ resultImage->putPremultipliedImageData(srcPixelArray.get(), shadowArea.size(), shadowArea, IntPoint());
+
+ resultContext->setCompositeOperation(CompositeSourceIn);
+ resultContext->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()), m_shadowColor, ColorSpaceDeviceRGB);
+ resultContext->setCompositeOperation(CompositeDestinationOver);
+
+ resultImage->context()->drawImageBuffer(sourceImage, ColorSpaceDeviceRGB, drawingRegion);
+}
+
+void FEDropShadow::dump()
+{
+}
+
+TextStream& FEDropShadow::externalRepresentation(TextStream& ts, int indent) const
+{
+ writeIndent(ts, indent);
+ ts << "[feDropShadow";
+ FilterEffect::externalRepresentation(ts);
+ ts << " stdDeviation=\"" << m_stdX << ", " << m_stdY << "\" dx=\"" << m_dx << "\" dy=\"" << m_dy << "\" flood-color=\"" << m_shadowColor.nameForRenderTreeAsText() <<"\" flood-opacity=\"" << m_shadowOpacity << "]\n";
+ inputEffect(0)->externalRepresentation(ts, indent + 1);
+ return ts;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(FILTERS)
diff --git a/Source/WebCore/platform/graphics/filters/FEDropShadow.h b/Source/WebCore/platform/graphics/filters/FEDropShadow.h
new file mode 100644
index 000000000..d155b4638
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FEDropShadow.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) Research In Motion Limited 2011. 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 FEDropShadow_h
+#define FEDropShadow_h
+
+#if ENABLE(FILTERS)
+#include "Color.h"
+#include "Filter.h"
+#include "FilterEffect.h"
+
+namespace WebCore {
+
+class FEDropShadow : public FilterEffect {
+public:
+ static PassRefPtr<FEDropShadow> create(Filter*, float, float, float, float, const Color&, float);
+
+ float stdDeviationX() const { return m_stdX; }
+ void setStdDeviationX(float stdX) { m_stdX = stdX; }
+
+ float stdDeviationY() const { return m_stdY; }
+ void setStdDeviationY(float stdY) { m_stdY = stdY; }
+
+ float dx() const { return m_dx; }
+ void setDx(float dx) { m_dx = dx; }
+
+ float dy() const { return m_dy; }
+ void setDy(float dy) { m_dy = dy; }
+
+ Color shadowColor() const { return m_shadowColor; }
+ void setShadowColor(const Color& shadowColor) { m_shadowColor = shadowColor; }
+
+ float shadowOpacity() const { return m_shadowOpacity; }
+ void setShadowOpacity(float shadowOpacity) { m_shadowOpacity = shadowOpacity; }
+
+ static float calculateStdDeviation(float);
+
+ virtual void platformApplySoftware();
+ virtual void dump();
+
+ virtual void determineAbsolutePaintRect();
+
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+
+private:
+ FEDropShadow(Filter*, float, float, float, float, const Color&, float);
+
+ float m_stdX;
+ float m_stdY;
+ float m_dx;
+ float m_dy;
+ Color m_shadowColor;
+ float m_shadowOpacity;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(FILTERS)
+#endif // FEDropShadow_h
diff --git a/Source/WebCore/platform/graphics/filters/FEFlood.cpp b/Source/WebCore/platform/graphics/filters/FEFlood.cpp
new file mode 100644
index 000000000..086eb966e
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FEFlood.cpp
@@ -0,0 +1,99 @@
+/*
+ * 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"
+#include "RenderTreeAsText.h"
+#include "TextStream.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;
+}
+
+bool FEFlood::setFloodColor(const Color& color)
+{
+ if (m_floodColor == color)
+ return false;
+ m_floodColor = color;
+ return true;
+}
+
+float FEFlood::floodOpacity() const
+{
+ return m_floodOpacity;
+}
+
+bool FEFlood::setFloodOpacity(float floodOpacity)
+{
+ if (m_floodOpacity == floodOpacity)
+ return false;
+ m_floodOpacity = floodOpacity;
+ return true;
+}
+
+void FEFlood::platformApplySoftware()
+{
+ 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().nameForRenderTreeAsText() << "\" "
+ << "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 000000000..e0484b449
--- /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;
+ bool setFloodColor(const Color &);
+
+ float floodOpacity() const;
+ bool setFloodOpacity(float);
+
+ virtual void platformApplySoftware();
+ virtual void dump();
+
+ virtual void determineAbsolutePaintRect() { setAbsolutePaintRect(enclosingIntRect(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 000000000..f9a86eb17
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
@@ -0,0 +1,330 @@
+/*
+ * 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 "FEGaussianBlurNEON.h"
+#include "Filter.h"
+#include "GraphicsContext.h"
+#include "RenderTreeAsText.h"
+#include "TextStream.h"
+
+#include <wtf/ByteArray.h>
+#include <wtf/MathExtras.h>
+#include <wtf/ParallelJobs.h>
+
+using namespace std;
+
+static inline float gaussianKernelFactor()
+{
+ return 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 = 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 FEGaussianBlur::platformApplyGeneric(ByteArray* srcPixelArray, ByteArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize)
+{
+ int stride = 4 * paintSize.width();
+ int dxLeft = 0;
+ int dxRight = 0;
+ int dyLeft = 0;
+ int dyRight = 0;
+ ByteArray* src = srcPixelArray;
+ ByteArray* dst = tmpPixelArray;
+
+ for (int i = 0; i < 3; ++i) {
+ if (kernelSizeX) {
+ kernelPosition(i, kernelSizeX, dxLeft, dxRight);
+ boxBlur(src, dst, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height(), isAlphaImage());
+ swap(src, dst);
+ }
+
+ if (kernelSizeY) {
+ kernelPosition(i, kernelSizeY, dyLeft, dyRight);
+ boxBlur(src, dst, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width(), isAlphaImage());
+ swap(src, dst);
+ }
+ }
+
+ // The final result should be stored in srcPixelArray.
+ if (dst == srcPixelArray) {
+ ASSERT(src->length() == dst->length());
+ memcpy(dst->data(), src->data(), src->length());
+ }
+
+}
+
+void FEGaussianBlur::platformApplyWorker(PlatformApplyParameters* parameters)
+{
+ IntSize paintSize(parameters->width, parameters->height);
+#if CPU(ARM_NEON) && COMPILER(GCC)
+ parameters->filter->platformApplyNeon(parameters->srcPixelArray.get(), parameters->dstPixelArray.get(),
+ parameters->kernelSizeX, parameters->kernelSizeY, paintSize);
+#else
+ parameters->filter->platformApplyGeneric(parameters->srcPixelArray.get(), parameters->dstPixelArray.get(),
+ parameters->kernelSizeX, parameters->kernelSizeY, paintSize);
+#endif
+}
+
+inline void FEGaussianBlur::platformApply(ByteArray* srcPixelArray, ByteArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize)
+{
+ int scanline = 4 * paintSize.width();
+ int extraHeight = 3 * kernelSizeY * 0.5f;
+ int optimalThreadNumber = (paintSize.width() * paintSize.height()) / (s_minimalRectDimension + extraHeight * paintSize.width());
+
+ if (optimalThreadNumber > 1) {
+ WTF::ParallelJobs<PlatformApplyParameters> parallelJobs(&platformApplyWorker, optimalThreadNumber);
+
+ int jobs = parallelJobs.numberOfJobs();
+ if (jobs > 1) {
+ int blockHeight = paintSize.height() / jobs;
+ --jobs;
+ for (int job = jobs; job >= 0; --job) {
+ PlatformApplyParameters& params = parallelJobs.parameter(job);
+ params.filter = this;
+
+ int startY;
+ int endY;
+ if (!job) {
+ startY = 0;
+ endY = blockHeight + extraHeight;
+ params.srcPixelArray = srcPixelArray;
+ params.dstPixelArray = tmpPixelArray;
+ } else {
+ if (job == jobs) {
+ startY = job * blockHeight - extraHeight;
+ endY = paintSize.height();
+ } else {
+ startY = job * blockHeight - extraHeight;
+ endY = (job + 1) * blockHeight + extraHeight;
+ }
+
+ int blockSize = (endY - startY) * scanline;
+ params.srcPixelArray = ByteArray::create(blockSize);
+ params.dstPixelArray = ByteArray::create(blockSize);
+ memcpy(params.srcPixelArray->data(), srcPixelArray->data() + startY * scanline, blockSize);
+ }
+
+ params.width = paintSize.width();
+ params.height = endY - startY;
+ params.kernelSizeX = kernelSizeX;
+ params.kernelSizeY = kernelSizeY;
+ }
+
+ parallelJobs.execute();
+
+ // Copy together the parts of the image.
+ for (int job = jobs; job >= 1; --job) {
+ PlatformApplyParameters& params = parallelJobs.parameter(job);
+ int sourceOffset;
+ int destinationOffset;
+ int size;
+ if (job == jobs) {
+ sourceOffset = extraHeight * scanline;
+ destinationOffset = job * blockHeight * scanline;
+ size = (paintSize.height() - job * blockHeight) * scanline;
+ } else {
+ sourceOffset = extraHeight * scanline;
+ destinationOffset = job * blockHeight * scanline;
+ size = blockHeight * scanline;
+ }
+ memcpy(srcPixelArray->data() + destinationOffset, params.srcPixelArray->data() + sourceOffset, size);
+ }
+ return;
+ }
+ // Fallback to single threaded mode.
+ }
+
+ // The selection here eventually should happen dynamically on some platforms.
+#if CPU(ARM_NEON) && COMPILER(GCC)
+ platformApplyNeon(srcPixelArray, tmpPixelArray, kernelSizeX, kernelSizeY, paintSize);
+#else
+ platformApplyGeneric(srcPixelArray, tmpPixelArray, kernelSizeX, kernelSizeY, paintSize);
+#endif
+}
+
+void FEGaussianBlur::calculateUnscaledKernelSize(unsigned& kernelSizeX, unsigned& kernelSizeY, float stdX, float stdY)
+{
+ kernelSizeX = 0;
+ if (stdX)
+ kernelSizeX = max<unsigned>(2, static_cast<unsigned>(floorf(stdX * gaussianKernelFactor() + 0.5f)));
+ kernelSizeY = 0;
+ if (stdY)
+ kernelSizeY = max<unsigned>(2, static_cast<unsigned>(floorf(stdY * gaussianKernelFactor() + 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::calculateKernelSize(Filter* filter, unsigned& kernelSizeX, unsigned& kernelSizeY, float stdX, float stdY)
+{
+ stdX = filter->applyHorizontalScale(stdX);
+ stdY = filter->applyVerticalScale(stdY);
+
+ calculateUnscaledKernelSize(kernelSizeX, kernelSizeY, stdX, stdY);
+}
+
+void FEGaussianBlur::determineAbsolutePaintRect()
+{
+ FloatRect absolutePaintRect = inputEffect(0)->absolutePaintRect();
+ if (clipsToBounds())
+ absolutePaintRect.intersect(maxEffectRect());
+ else
+ absolutePaintRect.unite(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::platformApplySoftware()
+{
+#if USE(SKIA)
+ if (filter()->renderingMode() == Accelerated) {
+ platformApplySkia();
+ return;
+ }
+#endif
+
+ FilterEffect* in = inputEffect(0);
+
+ 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();
+
+ platformApply(srcPixelArray, tmpPixelArray, kernelSizeX, kernelSizeY, paintSize);
+}
+
+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) / gaussianKernelFactor(), 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 000000000..7f6c3bbee
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h
@@ -0,0 +1,115 @@
+/*
+ * 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 platformApplySoftware();
+ virtual void dump();
+
+ virtual void determineAbsolutePaintRect();
+ static void calculateKernelSize(Filter*, unsigned& kernelSizeX, unsigned& kernelSizeY, float stdX, float stdY);
+ static void calculateUnscaledKernelSize(unsigned& kernelSizeX, unsigned& kernelSizeY, float stdX, float stdY);
+
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+
+private:
+ static const int s_minimalRectDimension = 100 * 100; // Empirical data limit for parallel jobs
+
+ template<typename Type>
+ friend class ParallelJobs;
+
+ struct PlatformApplyParameters {
+ FEGaussianBlur* filter;
+ RefPtr<ByteArray> srcPixelArray;
+ RefPtr<ByteArray> dstPixelArray;
+ int width;
+ int height;
+ unsigned kernelSizeX;
+ unsigned kernelSizeY;
+ };
+
+ static void platformApplyWorker(PlatformApplyParameters*);
+
+ FEGaussianBlur(Filter*, float, float);
+
+ static inline void kernelPosition(int boxBlur, unsigned& std, int& dLeft, int& dRight);
+ inline void platformApply(ByteArray* srcPixelArray, ByteArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize);
+
+ inline void platformApplyGeneric(ByteArray* srcPixelArray, ByteArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize);
+ inline void platformApplyNeon(ByteArray* srcPixelArray, ByteArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize);
+ void platformApplySkia();
+
+ float m_stdX;
+ float m_stdY;
+};
+
+inline void FEGaussianBlur::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;
+ }
+}
+
+} // 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 000000000..e795d3549
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FELighting.cpp
@@ -0,0 +1,411 @@
+/*
+ * 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 "FELightingNEON.h"
+#include <wtf/ParallelJobs.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);
+}
+
+inline void FELighting::platformApplyGenericPaint(LightingData& data, LightSource::PaintingData& paintingData, int startY, int endY)
+{
+ IntPoint normalVector;
+ int offset = 0;
+
+ for (int y = startY; y < endY; ++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);
+ }
+ }
+}
+
+void FELighting::platformApplyGenericWorker(PlatformApplyGenericParameters* parameters)
+{
+ parameters->filter->platformApplyGenericPaint(parameters->data, parameters->paintingData, parameters->yStart, parameters->yEnd);
+}
+
+inline void FELighting::platformApplyGeneric(LightingData& data, LightSource::PaintingData& paintingData)
+{
+ int optimalThreadNumber = ((data.widthDecreasedByOne - 1) * (data.heightDecreasedByOne - 1)) / s_minimalRectDimension;
+ if (optimalThreadNumber > 1) {
+ // Initialize parallel jobs
+ WTF::ParallelJobs<PlatformApplyGenericParameters> parallelJobs(&platformApplyGenericWorker, optimalThreadNumber);
+
+ // Fill the parameter array
+ int job = parallelJobs.numberOfJobs();
+ if (job > 1) {
+ int yStart = 1;
+ int yStep = (data.heightDecreasedByOne - 1) / job;
+ for (--job; job >= 0; --job) {
+ PlatformApplyGenericParameters& params = parallelJobs.parameter(job);
+ params.filter = this;
+ params.data = data;
+ params.paintingData = paintingData;
+ params.yStart = yStart;
+ if (job > 0) {
+ params.yEnd = yStart + yStep;
+ yStart += yStep;
+ } else
+ params.yEnd = data.heightDecreasedByOne;
+ }
+ parallelJobs.execute();
+ return;
+ }
+ // Fallback to single threaded mode.
+ }
+
+ platformApplyGenericPaint(data, paintingData, 1, data.heightDecreasedByOne);
+}
+
+inline void FELighting::platformApply(LightingData& data, LightSource::PaintingData& paintingData)
+{
+ // The selection here eventually should happen dynamically on some platforms.
+#if CPU(ARM_NEON) && COMPILER(GCC)
+ platformApplyNeon(data, paintingData);
+#else
+ platformApplyGeneric(data, paintingData);
+#endif
+}
+
+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.
+ platformApply(data, paintingData);
+ }
+
+ 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::platformApplySoftware()
+{
+ FilterEffect* in = inputEffect(0);
+
+ 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 000000000..5426f912c
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FELighting.h
@@ -0,0 +1,127 @@
+/*
+ * 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 "PointLightSource.h"
+#include "SpotLightSource.h"
+#include <wtf/ByteArray.h>
+#include <wtf/Platform.h>
+
+// Common base class for FEDiffuseLighting and FESpecularLighting
+
+namespace WebCore {
+
+struct FELightingPaintingDataForNeon;
+
+class FELighting : public FilterEffect {
+public:
+ virtual void platformApplySoftware();
+
+ virtual void determineAbsolutePaintRect() { setAbsolutePaintRect(enclosingIntRect(maxEffectRect())); }
+
+protected:
+ static const int s_minimalRectDimension = 100 * 100; // Empirical data limit for parallel jobs
+
+ 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);
+ };
+
+ template<typename Type>
+ friend class ParallelJobs;
+
+ struct PlatformApplyGenericParameters {
+ FELighting* filter;
+ LightingData data;
+ LightSource::PaintingData paintingData;
+ int yStart;
+ int yEnd;
+ };
+
+ static void platformApplyGenericWorker(PlatformApplyGenericParameters*);
+ static void platformApplyNeonWorker(FELightingPaintingDataForNeon*);
+
+ 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);
+
+ inline void platformApply(LightingData&, LightSource::PaintingData&);
+
+ inline void platformApplyGenericPaint(LightingData&, LightSource::PaintingData&, int startX, int startY);
+ inline void platformApplyGeneric(LightingData&, LightSource::PaintingData&);
+
+ static int getPowerCoefficients(float exponent);
+ inline void platformApplyNeon(LightingData&, LightSource::PaintingData&);
+
+ 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 000000000..eddb61a21
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FEMerge.cpp
@@ -0,0 +1,79 @@
+/*
+ * 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"
+#include "RenderTreeAsText.h"
+#include "TextStream.h"
+
+namespace WebCore {
+
+FEMerge::FEMerge(Filter* filter)
+ : FilterEffect(filter)
+{
+}
+
+PassRefPtr<FEMerge> FEMerge::create(Filter* filter)
+{
+ return adoptRef(new FEMerge(filter));
+}
+
+void FEMerge::platformApplySoftware()
+{
+ unsigned size = numberOfEffectInputs();
+ ASSERT(size > 0);
+
+ 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 000000000..302336b63
--- /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 platformApplySoftware();
+ 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 000000000..5ba4dfc14
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FEMorphology.cpp
@@ -0,0 +1,261 @@
+/*
+ * 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 "RenderTreeAsText.h"
+#include "TextStream.h"
+
+#include <wtf/ByteArray.h>
+#include <wtf/ParallelJobs.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;
+}
+
+bool FEMorphology::setMorphologyOperator(MorphologyOperatorType type)
+{
+ if (m_type == type)
+ return false;
+ m_type = type;
+ return true;
+}
+
+float FEMorphology::radiusX() const
+{
+ return m_radiusX;
+}
+
+bool FEMorphology::setRadiusX(float radiusX)
+{
+ if (m_radiusX == radiusX)
+ return false;
+ m_radiusX = radiusX;
+ return true;
+}
+
+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));
+ if (clipsToBounds())
+ paintRect.intersect(maxEffectRect());
+ else
+ paintRect.unite(maxEffectRect());
+ setAbsolutePaintRect(enclosingIntRect(paintRect));
+}
+
+bool FEMorphology::setRadiusY(float radiusY)
+{
+ if (m_radiusY == radiusY)
+ return false;
+ m_radiusY = radiusY;
+ return true;
+}
+
+void FEMorphology::platformApplyGeneric(PaintingData* paintingData, int yStart, int yEnd)
+{
+ ByteArray* srcPixelArray = paintingData->srcPixelArray;
+ ByteArray* dstPixelArray = paintingData->dstPixelArray;
+ const int width = paintingData->width;
+ const int height = paintingData->height;
+ const int effectWidth = width * 4;
+ const int radiusX = paintingData->radiusX;
+ const int radiusY = paintingData->radiusY;
+
+ Vector<unsigned char> extrema;
+ for (int y = yStart; y < yEnd; ++y) {
+ int extremaStartY = max(0, y - radiusY);
+ int extremaEndY = min(height - 1, y + radiusY);
+ for (unsigned int clrChannel = 0; clrChannel < 4; ++clrChannel) {
+ extrema.clear();
+ // Compute extremas for each columns
+ for (int x = 0; x <= radiusX; ++x) {
+ unsigned char columnExtrema = srcPixelArray->get(extremaStartY * effectWidth + 4 * x + clrChannel);
+ for (int eY = extremaStartY + 1; eY < extremaEndY; ++eY) {
+ unsigned char pixel = srcPixelArray->get(eY * effectWidth + 4 * x + clrChannel);
+ 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 < width; ++x) {
+ const int endX = min(x + radiusX, width - 1);
+ unsigned char columnExtrema = srcPixelArray->get(extremaStartY * effectWidth + endX * 4 + clrChannel);
+ for (int i = extremaStartY + 1; i <= extremaEndY; ++i) {
+ unsigned char pixel = srcPixelArray->get(i * effectWidth + endX * 4 + clrChannel);
+ 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 <= width)
+ extrema.append(columnExtrema);
+
+ unsigned char entireExtrema = extrema[0];
+ for (unsigned kernelIndex = 1; 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 + clrChannel, entireExtrema);
+ }
+ }
+ }
+}
+
+void FEMorphology::platformApplyWorker(PlatformApplyParameters* param)
+{
+ param->filter->platformApplyGeneric(param->paintingData, param->startY, param->endY);
+}
+
+void FEMorphology::platformApply(PaintingData* paintingData)
+{
+ int optimalThreadNumber = (paintingData->width * paintingData->height) / s_minimalArea;
+ if (optimalThreadNumber > 1) {
+ ParallelJobs<PlatformApplyParameters> parallelJobs(&WebCore::FEMorphology::platformApplyWorker, optimalThreadNumber);
+ int numOfThreads = parallelJobs.numberOfJobs();
+ if (numOfThreads > 1) {
+ const int deltaY = 1 + paintingData->height / numOfThreads;
+ int currentY = 0;
+ for (int job = numOfThreads - 1; job >= 0; --job) {
+ PlatformApplyParameters& param = parallelJobs.parameter(job);
+ param.filter = this;
+ param.startY = currentY;
+ currentY += deltaY;
+ param.endY = job ? currentY : paintingData->height;
+ param.paintingData = paintingData;
+ }
+ parallelJobs.execute();
+ return;
+ }
+ // Fallback to single thread model
+ }
+
+ platformApplyGeneric(paintingData, 0, paintingData->height);
+}
+
+
+void FEMorphology::platformApplySoftware()
+{
+ FilterEffect* in = inputEffect(0);
+
+ ByteArray* dstPixelArray = createPremultipliedImageResult();
+ if (!dstPixelArray)
+ return;
+
+ setIsAlphaImage(in->isAlphaImage());
+ if (m_radiusX <= 0 || m_radiusY <= 0) {
+ dstPixelArray->clear();
+ 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);
+
+ PaintingData paintingData;
+ paintingData.srcPixelArray = srcPixelArray.get();
+ paintingData.dstPixelArray = dstPixelArray;
+ paintingData.width = effectDrawingRect.width();
+ paintingData.height = effectDrawingRect.height();
+ paintingData.radiusX = min(effectDrawingRect.width() - 1, radiusX);
+ paintingData.radiusY = min(effectDrawingRect.height() - 1, radiusY);
+
+ platformApply(&paintingData);
+}
+
+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 000000000..f92540342
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FEMorphology.h
@@ -0,0 +1,90 @@
+/*
+ * 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;
+ bool setMorphologyOperator(MorphologyOperatorType);
+
+ float radiusX() const;
+ bool setRadiusX(float);
+
+ float radiusY() const;
+ bool setRadiusY(float);
+
+ virtual void platformApplySoftware();
+ virtual void dump();
+
+ virtual void determineAbsolutePaintRect();
+
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+
+ struct PaintingData {
+ ByteArray* srcPixelArray;
+ ByteArray* dstPixelArray;
+ int width;
+ int height;
+ int radiusX;
+ int radiusY;
+ };
+
+ static const int s_minimalArea = (300 * 300); // Empirical data limit for parallel jobs
+
+ struct PlatformApplyParameters {
+ FEMorphology* filter;
+ int startY;
+ int endY;
+ PaintingData* paintingData;
+ };
+
+ static void platformApplyWorker(PlatformApplyParameters*);
+
+ inline void platformApply(PaintingData*);
+ inline void platformApplyGeneric(PaintingData*, const int yStart, const int yEnd);
+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 000000000..ef2c46683
--- /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"
+#include "RenderTreeAsText.h"
+#include "TextStream.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));
+ if (clipsToBounds())
+ paintRect.intersect(maxEffectRect());
+ else
+ paintRect.unite(maxEffectRect());
+ setAbsolutePaintRect(enclosingIntRect(paintRect));
+}
+
+void FEOffset::platformApplySoftware()
+{
+ FilterEffect* in = inputEffect(0);
+
+ 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 000000000..e75febd9c
--- /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 platformApplySoftware();
+ 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 000000000..2c7b1ebf9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FESpecularLighting.cpp
@@ -0,0 +1,158 @@
+/*
+ * 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"
+#include "RenderTreeAsText.h"
+#include "TextStream.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;
+}
+
+bool FESpecularLighting::setLightingColor(const Color& lightingColor)
+{
+ if (m_lightingColor == lightingColor)
+ return false;
+ m_lightingColor = lightingColor;
+ return true;
+}
+
+float FESpecularLighting::surfaceScale() const
+{
+ return m_surfaceScale;
+}
+
+bool FESpecularLighting::setSurfaceScale(float surfaceScale)
+{
+ if (m_surfaceScale == surfaceScale)
+ return false;
+ m_surfaceScale = surfaceScale;
+ return true;
+}
+
+float FESpecularLighting::specularConstant() const
+{
+ return m_specularConstant;
+}
+
+bool FESpecularLighting::setSpecularConstant(float specularConstant)
+{
+ if (m_specularConstant == specularConstant)
+ return false;
+ m_specularConstant = specularConstant;
+ return true;
+}
+
+float FESpecularLighting::specularExponent() const
+{
+ return m_specularExponent;
+}
+
+bool FESpecularLighting::setSpecularExponent(float specularExponent)
+{
+ if (m_specularExponent == specularExponent)
+ return false;
+ m_specularExponent = specularExponent;
+ return true;
+}
+
+float FESpecularLighting::kernelUnitLengthX() const
+{
+ return m_kernelUnitLengthX;
+}
+
+bool FESpecularLighting::setKernelUnitLengthX(float kernelUnitLengthX)
+{
+ if (m_kernelUnitLengthX == kernelUnitLengthX)
+ return false;
+ m_kernelUnitLengthX = kernelUnitLengthX;
+ return true;
+}
+
+float FESpecularLighting::kernelUnitLengthY() const
+{
+ return m_kernelUnitLengthY;
+}
+
+bool FESpecularLighting::setKernelUnitLengthY(float kernelUnitLengthY)
+{
+ if (m_kernelUnitLengthY == kernelUnitLengthY)
+ return false;
+ m_kernelUnitLengthY = kernelUnitLengthY;
+ return true;
+}
+
+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 000000000..9fa3addac
--- /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;
+ bool setLightingColor(const Color&);
+
+ float surfaceScale() const;
+ bool setSurfaceScale(float);
+
+ float specularConstant() const;
+ bool setSpecularConstant(float);
+
+ float specularExponent() const;
+ bool setSpecularExponent(float);
+
+ float kernelUnitLengthX() const;
+ bool setKernelUnitLengthX(float);
+
+ float kernelUnitLengthY() const;
+ bool 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 000000000..a6e1da334
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FETile.cpp
@@ -0,0 +1,105 @@
+/*
+ * 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 "RenderTreeAsText.h"
+#include "SVGImageBufferTools.h"
+#include "TextStream.h"
+
+namespace WebCore {
+
+FETile::FETile(Filter* filter)
+ : FilterEffect(filter)
+{
+}
+
+PassRefPtr<FETile> FETile::create(Filter* filter)
+{
+ return adoptRef(new FETile(filter));
+}
+
+void FETile::platformApplySoftware()
+{
+// FIXME: See bug 47315. This is a hack to work around a compile failure, but is incorrect behavior otherwise.
+#if ENABLE(SVG)
+ FilterEffect* in = inputEffect(0);
+
+ 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, filter()->renderingMode()))
+ 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(CopyBackingStore), 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 000000000..633276a3e
--- /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 platformApplySoftware();
+ virtual void dump();
+
+ virtual void determineAbsolutePaintRect() { setAbsolutePaintRect(enclosingIntRect(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 000000000..3ca45717e
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FETurbulence.cpp
@@ -0,0 +1,447 @@
+/*
+ * 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>
+ * Copyright (C) 2011 Gabor Loki <loki@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 "FETurbulence.h"
+
+#include "Filter.h"
+#include "RenderTreeAsText.h"
+#include "TextStream.h"
+
+#include <wtf/ByteArray.h>
+#include <wtf/MathExtras.h>
+#include <wtf/ParallelJobs.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, TurbulenceType 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, TurbulenceType type, float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, bool stitchTiles)
+{
+ return adoptRef(new FETurbulence(filter, type, baseFrequencyX, baseFrequencyY, numOctaves, seed, stitchTiles));
+}
+
+TurbulenceType FETurbulence::type() const
+{
+ return m_type;
+}
+
+bool FETurbulence::setType(TurbulenceType type)
+{
+ if (m_type == type)
+ return false;
+ m_type = type;
+ return true;
+}
+
+float FETurbulence::baseFrequencyY() const
+{
+ return m_baseFrequencyY;
+}
+
+bool FETurbulence::setBaseFrequencyY(float baseFrequencyY)
+{
+ if (m_baseFrequencyY == baseFrequencyY)
+ return false;
+ m_baseFrequencyY = baseFrequencyY;
+ return true;
+}
+
+float FETurbulence::baseFrequencyX() const
+{
+ return m_baseFrequencyX;
+}
+
+bool FETurbulence::setBaseFrequencyX(float baseFrequencyX)
+{
+ if (m_baseFrequencyX == baseFrequencyX)
+ return false;
+ m_baseFrequencyX = baseFrequencyX;
+ return true;
+}
+
+float FETurbulence::seed() const
+{
+ return m_seed;
+}
+
+bool FETurbulence::setSeed(float seed)
+{
+ if (m_seed == seed)
+ return false;
+ m_seed = seed;
+ return true;
+}
+
+int FETurbulence::numOctaves() const
+{
+ return m_numOctaves;
+}
+
+bool FETurbulence::setNumOctaves(int numOctaves)
+{
+ if (m_numOctaves == numOctaves)
+ return false;
+ m_numOctaves = numOctaves;
+ return true;
+}
+
+bool FETurbulence::stitchTiles() const
+{
+ return m_stitchTiles;
+}
+
+bool FETurbulence::setStitchTiles(bool stitch)
+{
+ if (m_stitchTiles == stitch)
+ return false;
+ m_stitchTiles = stitch;
+ return true;
+}
+
+// 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)
+ , 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(int channel, 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[channel][temp];
+ u = noiseX.noisePositionFractionValue * q[0] + noiseY.noisePositionFractionValue * q[1];
+ temp = paintingData.latticeSelector[nextLatticeIndex + noiseY.noisePositionIntegerValue];
+ q = paintingData.gradient[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[channel][temp];
+ u = noiseX.noisePositionFractionValue * q[0] + (noiseY.noisePositionFractionValue - 1) * q[1];
+ temp = paintingData.latticeSelector[nextLatticeIndex + noiseY.noisePositionIntegerValue + 1];
+ q = paintingData.gradient[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(int channel, 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(channel, paintingData, noiseVector) / ratio;
+ else
+ turbulenceFunctionResult += fabsf(noise2D(channel, 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);
+}
+
+inline void FETurbulence::fillRegion(ByteArray* pixelArray, PaintingData& paintingData, int startY, int endY)
+{
+ IntRect filterRegion = absolutePaintRect();
+ IntPoint point(0, filterRegion.y() + startY);
+ int indexOfPixelChannel = startY * (filterRegion.width() << 2);
+ int channel;
+
+ for (int y = startY; y < endY; ++y) {
+ point.setY(point.y() + 1);
+ point.setX(filterRegion.x());
+ for (int x = 0; x < filterRegion.width(); ++x) {
+ point.setX(point.x() + 1);
+ for (channel = 0; channel < 4; ++channel, ++indexOfPixelChannel)
+ pixelArray->set(indexOfPixelChannel, calculateTurbulenceValueForPoint(channel, paintingData, filter()->mapAbsolutePointToLocalPoint(point)));
+ }
+ }
+}
+
+void FETurbulence::fillRegionWorker(FillRegionParameters* parameters)
+{
+ parameters->filter->fillRegion(parameters->pixelArray, *parameters->paintingData, parameters->startY, parameters->endY);
+}
+
+void FETurbulence::platformApplySoftware()
+{
+ ByteArray* pixelArray = createUnmultipliedImageResult();
+ if (!pixelArray)
+ return;
+
+ if (absolutePaintRect().isEmpty()) {
+ pixelArray->clear();
+ return;
+ }
+
+ PaintingData paintingData(m_seed, roundedIntSize(filterPrimitiveSubregion().size()));
+ initPaint(paintingData);
+
+ int optimalThreadNumber = (absolutePaintRect().width() * absolutePaintRect().height()) / s_minimalRectDimension;
+ if (optimalThreadNumber > 1) {
+ // Initialize parallel jobs
+ WTF::ParallelJobs<FillRegionParameters> parallelJobs(&WebCore::FETurbulence::fillRegionWorker, optimalThreadNumber);
+
+ // Fill the parameter array
+ int i = parallelJobs.numberOfJobs();
+ if (i > 1) {
+ int startY = 0;
+ int stepY = absolutePaintRect().height() / i;
+ for (; i > 0; --i) {
+ FillRegionParameters& params = parallelJobs.parameter(i-1);
+ params.filter = this;
+ params.pixelArray = pixelArray;
+ params.paintingData = &paintingData;
+ params.startY = startY;
+ if (i != 1) {
+ params.endY = startY + stepY;
+ startY = startY + stepY;
+ } else
+ params.endY = absolutePaintRect().height();
+ }
+
+ // Execute parallel jobs
+ parallelJobs.execute();
+ return;
+ }
+ }
+
+ // Fallback to single threaded mode if there is no room for a new thread or the paint area is too small.
+ fillRegion(pixelArray, paintingData, 0, absolutePaintRect().height());
+}
+
+void FETurbulence::dump()
+{
+}
+
+static TextStream& operator<<(TextStream& ts, const TurbulenceType& 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 000000000..01d3c597a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FETurbulence.h
@@ -0,0 +1,122 @@
+/*
+ * 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 TurbulenceType {
+ FETURBULENCE_TYPE_UNKNOWN = 0,
+ FETURBULENCE_TYPE_FRACTALNOISE = 1,
+ FETURBULENCE_TYPE_TURBULENCE = 2
+};
+
+class FETurbulence : public FilterEffect {
+public:
+ static PassRefPtr<FETurbulence> create(Filter*, TurbulenceType, float, float, int, float, bool);
+
+ TurbulenceType type() const;
+ bool setType(TurbulenceType);
+
+ float baseFrequencyY() const;
+ bool setBaseFrequencyY(float);
+
+ float baseFrequencyX() const;
+ bool setBaseFrequencyX(float);
+
+ float seed() const;
+ bool setSeed(float);
+
+ int numOctaves() const;
+ bool setNumOctaves(int);
+
+ bool stitchTiles() const;
+ bool setStitchTiles(bool);
+
+ static void fillRegionWorker(void*);
+
+ virtual void platformApplySoftware();
+ virtual void dump();
+
+ virtual void determineAbsolutePaintRect() { setAbsolutePaintRect(enclosingIntRect(maxEffectRect())); }
+
+ virtual TextStream& externalRepresentation(TextStream&, int indention) const;
+
+private:
+ static const int s_blockSize = 256;
+ static const int s_blockMask = s_blockSize - 1;
+
+ static const int s_minimalRectDimension = (100 * 100); // Empirical data limit for parallel jobs.
+
+ 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;
+ IntSize filterSize;
+
+ PaintingData(long paintingSeed, const IntSize& paintingSize);
+ inline long random();
+ };
+
+ template<typename Type>
+ friend class ParallelJobs;
+
+ struct FillRegionParameters {
+ FETurbulence* filter;
+ ByteArray* pixelArray;
+ PaintingData* paintingData;
+ int startY;
+ int endY;
+ };
+
+ static void fillRegionWorker(FillRegionParameters*);
+
+ FETurbulence(Filter*, TurbulenceType, float, float, int, float, bool);
+
+ inline void initPaint(PaintingData&);
+ float noise2D(int channel, PaintingData&, const FloatPoint&);
+ unsigned char calculateTurbulenceValueForPoint(int channel, PaintingData&, const FloatPoint&);
+ inline void fillRegion(ByteArray*, PaintingData&, int, int);
+
+ TurbulenceType 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 000000000..b0f604d56
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/Filter.h
@@ -0,0 +1,65 @@
+/*
+ * 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/RefCounted.h>
+
+namespace WebCore {
+
+class FilterEffect;
+
+class Filter : public RefCounted<Filter> {
+public:
+ Filter() : m_renderingMode(Unaccelerated) { }
+ 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; }
+
+ RenderingMode renderingMode() const { return m_renderingMode; }
+ void setRenderingMode(RenderingMode renderingMode) { m_renderingMode = renderingMode; }
+
+ 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(); }
+
+private:
+ OwnPtr<ImageBuffer> m_sourceImage;
+ FloatSize m_filterResolution;
+ RenderingMode m_renderingMode;
+};
+
+} // 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 000000000..6516faadc
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FilterEffect.cpp
@@ -0,0 +1,303 @@
+/*
+ * 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 "Filter.h"
+#include "ImageBuffer.h"
+#include "TextStream.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)
+ , m_clipsToBounds(true)
+{
+ ASSERT(m_filter);
+}
+
+FilterEffect::~FilterEffect()
+{
+}
+
+inline bool isFilterSizeValid(IntRect rect)
+{
+ if (rect.width() < 0 || rect.width() > kMaxFilterSize
+ || rect.height() < 0 || rect.height() > kMaxFilterSize)
+ return false;
+ return true;
+}
+
+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());
+
+ // Filters in SVG clip to primitive subregion, while CSS doesn't.
+ if (m_clipsToBounds)
+ m_absolutePaintRect.intersect(enclosingIntRect(m_maxEffectRect));
+ else
+ m_absolutePaintRect.unite(enclosingIntRect(m_maxEffectRect));
+
+}
+
+IntRect FilterEffect::requestedRegionOfInputImageData(const IntRect& effectRect) const
+{
+ ASSERT(hasResult());
+ IntPoint location = m_absolutePaintRect.location();
+ location.moveBy(-effectRect.location());
+ 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();
+}
+
+void FilterEffect::apply()
+{
+ if (hasResult())
+ return;
+ unsigned size = m_inputEffects.size();
+ for (unsigned i = 0; i < size; ++i) {
+ FilterEffect* in = m_inputEffects.at(i).get();
+ in->apply();
+ if (!in->hasResult())
+ return;
+ }
+ determineAbsolutePaintRect();
+
+ // Add platform specific apply functions here and return earlier.
+ platformApplySoftware();
+}
+
+void FilterEffect::clearResult()
+{
+ if (m_imageBufferResult)
+ m_imageBufferResult.clear();
+ if (m_unmultipliedImageResult)
+ m_unmultipliedImageResult.clear();
+ if (m_premultipliedImageResult)
+ m_premultipliedImageResult.clear();
+}
+
+ImageBuffer* FilterEffect::asImageBuffer()
+{
+ if (!hasResult())
+ return 0;
+ if (m_imageBufferResult)
+ return m_imageBufferResult.get();
+ m_imageBufferResult = ImageBuffer::create(m_absolutePaintRect.size(), ColorSpaceLinearRGB, m_filter->renderingMode());
+ 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)
+{
+ ASSERT(isFilterSizeValid(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)
+{
+ ASSERT(isFilterSizeValid(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)
+{
+ // Initialize the destination to transparent black, if not entirely covered by the source.
+ if (rect.x() < 0 || rect.y() < 0 || rect.maxX() > m_absolutePaintRect.width() || rect.maxY() > m_absolutePaintRect.height())
+ memset(destination->data(), 0, destination->length());
+
+ // Early return if the rect does not intersect with the source.
+ if (rect.maxX() <= 0 || rect.maxY() <= 0 || rect.x() >= m_absolutePaintRect.width() || rect.y() >= m_absolutePaintRect.height())
+ return;
+
+ int xOrigin = rect.x();
+ int xDest = 0;
+ if (xOrigin < 0) {
+ xDest = -xOrigin;
+ xOrigin = 0;
+ }
+ int xEnd = rect.maxX();
+ 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.maxY();
+ 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 {
+ ASSERT(isFilterSizeValid(m_absolutePaintRect));
+ 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 {
+ ASSERT(isFilterSizeValid(m_absolutePaintRect));
+ 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());
+ if (m_absolutePaintRect.isEmpty())
+ return 0;
+ m_imageBufferResult = ImageBuffer::create(m_absolutePaintRect.size(), ColorSpaceLinearRGB, m_filter->renderingMode());
+ if (!m_imageBufferResult)
+ return 0;
+ ASSERT(m_imageBufferResult->context());
+ return m_imageBufferResult.get();
+}
+
+ByteArray* FilterEffect::createUnmultipliedImageResult()
+{
+ // Only one result type is allowed.
+ ASSERT(!hasResult());
+ ASSERT(isFilterSizeValid(m_absolutePaintRect));
+
+ 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());
+ ASSERT(isFilterSizeValid(m_absolutePaintRect));
+
+ 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 000000000..073010d27
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FilterEffect.h
@@ -0,0 +1,172 @@
+/*
+ * 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 "FloatRect.h"
+#include "IntRect.h"
+
+#include <wtf/ByteArray.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+static const float kMaxFilterSize = 5000.0f;
+
+namespace WebCore {
+
+class Filter;
+class FilterEffect;
+class ImageBuffer;
+class TextStream;
+
+typedef Vector<RefPtr<FilterEffect> > FilterEffectVector;
+
+enum FilterEffectType {
+ FilterEffectTypeUnknown,
+ FilterEffectTypeImage,
+ FilterEffectTypeTile,
+ FilterEffectTypeSourceInput
+};
+
+class FilterEffect : public RefCounted<FilterEffect> {
+public:
+ virtual ~FilterEffect();
+
+ void clearResult();
+ 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(); }
+
+ inline bool hasResult() const
+ {
+ // This function needs platform specific checks, if the memory managment is not done by FilterEffect.
+ return m_imageBufferResult || m_unmultipliedImageResult || m_premultipliedImageResult;
+ }
+
+ 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; }
+
+ FloatRect maxEffectRect() const { return m_maxEffectRect; }
+ void setMaxEffectRect(const FloatRect& maxEffectRect) { m_maxEffectRect = maxEffectRect; }
+
+ void apply();
+
+ virtual void platformApplySoftware() = 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; }
+
+ bool clipsToBounds() const { return m_clipsToBounds; }
+ void setClipsToBounds(bool value) { m_clipsToBounds = value; }
+
+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.
+ FloatRect 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;
+
+ // Should the effect clip to its primitive region, or expand to use the combined region of its inputs.
+ bool m_clipsToBounds;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(FILTERS)
+
+#endif // FilterEffect_h
diff --git a/Source/WebCore/platform/graphics/filters/FilterOperation.cpp b/Source/WebCore/platform/graphics/filters/FilterOperation.cpp
new file mode 100644
index 000000000..5de6ec0aa
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FilterOperation.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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(CSS_FILTERS)
+#include "FilterOperation.h"
+
+#include "AnimationUtilities.h"
+
+namespace WebCore {
+
+PassRefPtr<FilterOperation> BasicColorMatrixFilterOperation::blend(const FilterOperation* from, double progress, bool blendToPassthrough)
+{
+ if (from && !from->isSameType(*this))
+ return this;
+
+ if (blendToPassthrough)
+ return BasicColorMatrixFilterOperation::create(WebCore::blend(m_amount, passthroughAmount(), progress), m_type);
+
+ const BasicColorMatrixFilterOperation* fromOp = static_cast<const BasicColorMatrixFilterOperation*>(from);
+ double fromAmount = fromOp ? fromOp->amount() : passthroughAmount();
+ return BasicColorMatrixFilterOperation::create(WebCore::blend(fromAmount, m_amount, progress), m_type);
+}
+
+double BasicColorMatrixFilterOperation::passthroughAmount() const
+{
+ switch (m_type) {
+ case GRAYSCALE:
+ case SEPIA:
+ case HUE_ROTATE:
+ return 0;
+ case SATURATE:
+ return 1;
+ default:
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
+}
+
+PassRefPtr<FilterOperation> BasicComponentTransferFilterOperation::blend(const FilterOperation* from, double progress, bool blendToPassthrough)
+{
+ if (from && !from->isSameType(*this))
+ return this;
+
+ if (blendToPassthrough)
+ return BasicComponentTransferFilterOperation::create(WebCore::blend(m_amount, passthroughAmount(), progress), m_type);
+
+ const BasicComponentTransferFilterOperation* fromOp = static_cast<const BasicComponentTransferFilterOperation*>(from);
+ double fromAmount = fromOp ? fromOp->amount() : passthroughAmount();
+ return BasicComponentTransferFilterOperation::create(WebCore::blend(fromAmount, m_amount, progress), m_type);
+}
+
+double BasicComponentTransferFilterOperation::passthroughAmount() const
+{
+ switch (m_type) {
+ case OPACITY:
+ return 1;
+ case INVERT:
+ return 0;
+ case CONTRAST:
+ return 1;
+ case BRIGHTNESS:
+ return 1;
+ default:
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
+}
+
+PassRefPtr<FilterOperation> GammaFilterOperation::blend(const FilterOperation* from, double progress, bool blendToPassthrough)
+{
+ if (from && !from->isSameType(*this))
+ return this;
+
+ if (blendToPassthrough)
+ return GammaFilterOperation::create(
+ WebCore::blend(m_amplitude, 1.0, progress),
+ WebCore::blend(m_exponent, 1.0, progress),
+ WebCore::blend(m_offset, 0.0, progress), m_type);
+
+ const GammaFilterOperation* fromOp = static_cast<const GammaFilterOperation*>(from);
+ double fromAmplitude = fromOp ? fromOp->amplitude() : 1;
+ double fromExponent = fromOp ? fromOp->exponent() : 1;
+ double fromOffset = fromOp ? fromOp->offset() : 0;
+ return GammaFilterOperation::create(
+ WebCore::blend(fromAmplitude, m_amplitude, progress),
+ WebCore::blend(fromExponent, m_exponent, progress),
+ WebCore::blend(fromOffset, m_offset, progress), m_type);
+}
+
+PassRefPtr<FilterOperation> BlurFilterOperation::blend(const FilterOperation* from, double progress, bool blendToPassthrough)
+{
+ if (from && !from->isSameType(*this))
+ return this;
+
+ LengthType lengthType = m_stdDeviation.type();
+
+ if (blendToPassthrough)
+ return BlurFilterOperation::create(Length(lengthType).blend(m_stdDeviation, progress), m_type);
+
+ const BlurFilterOperation* fromOp = static_cast<const BlurFilterOperation*>(from);
+ Length fromLength = fromOp ? fromOp->m_stdDeviation : Length(lengthType);
+ return BlurFilterOperation::create(m_stdDeviation.blend(fromLength, progress), m_type);
+}
+
+PassRefPtr<FilterOperation> DropShadowFilterOperation::blend(const FilterOperation* from, double progress, bool blendToPassthrough)
+{
+ if (from && !from->isSameType(*this))
+ return this;
+
+ if (blendToPassthrough)
+ return DropShadowFilterOperation::create(
+ WebCore::blend(m_x, 0, progress),
+ WebCore::blend(m_y, 0, progress),
+ WebCore::blend(m_stdDeviation, 0, progress),
+ WebCore::blend(m_color, Color(Color::transparent), progress),
+ m_type);
+
+ const DropShadowFilterOperation* fromOp = static_cast<const DropShadowFilterOperation*>(from);
+ int fromX = fromOp ? fromOp->x() : 0;
+ int fromY = fromOp ? fromOp->y() : 0;
+ int fromStdDeviation = fromOp ? fromOp->stdDeviation() : 0;
+ Color fromColor = fromOp ? fromOp->color() : Color(Color::transparent);
+
+ return DropShadowFilterOperation::create(
+ WebCore::blend(fromX, m_x, progress),
+ WebCore::blend(fromY, m_y, progress),
+ WebCore::blend(fromStdDeviation, m_stdDeviation, progress),
+ WebCore::blend(fromColor, m_color, progress), m_type);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_FILTERS)
diff --git a/Source/WebCore/platform/graphics/filters/FilterOperation.h b/Source/WebCore/platform/graphics/filters/FilterOperation.h
new file mode 100644
index 000000000..4d15ec8ed
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FilterOperation.h
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 FilterOperation_h
+#define FilterOperation_h
+
+#if ENABLE(CSS_FILTERS)
+
+#include "Color.h"
+#include "Length.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/AtomicString.h>
+
+// Annoyingly, wingdi.h #defines this.
+#ifdef PASSTHROUGH
+#undef PASSTHROUGH
+#endif
+
+namespace WebCore {
+
+// CSS Filters
+
+class FilterOperation : public RefCounted<FilterOperation> {
+public:
+ enum OperationType {
+ REFERENCE, // url(#somefilter)
+ GRAYSCALE,
+ SEPIA,
+ SATURATE,
+ HUE_ROTATE,
+ INVERT,
+ OPACITY,
+ BRIGHTNESS,
+ CONTRAST,
+ BLUR,
+ DROP_SHADOW,
+#if ENABLE(CSS_SHADERS)
+ CUSTOM,
+#endif
+ PASSTHROUGH,
+ NONE
+ };
+
+ virtual ~FilterOperation() { }
+
+ virtual bool operator==(const FilterOperation&) const = 0;
+ bool operator!=(const FilterOperation& o) const { return !(*this == o); }
+
+ virtual PassRefPtr<FilterOperation> blend(const FilterOperation* /*from*/, double /*progress*/, bool /*blendToPassthrough*/ = false) { return 0; }
+
+ virtual OperationType getOperationType() const { return m_type; }
+ virtual bool isSameType(const FilterOperation& o) const { return o.getOperationType() == m_type; }
+
+protected:
+ FilterOperation(OperationType type)
+ : m_type(type)
+ {
+ }
+
+ OperationType m_type;
+};
+
+class PassthroughFilterOperation : public FilterOperation {
+public:
+ static PassRefPtr<PassthroughFilterOperation> create()
+ {
+ return adoptRef(new PassthroughFilterOperation());
+ }
+
+private:
+
+ virtual bool operator==(const FilterOperation& o) const
+ {
+ return isSameType(o);
+ }
+
+ PassthroughFilterOperation()
+ : FilterOperation(PASSTHROUGH)
+ {
+ }
+};
+
+class ReferenceFilterOperation : public FilterOperation {
+public:
+ static PassRefPtr<ReferenceFilterOperation> create(const AtomicString& reference, OperationType type)
+ {
+ return adoptRef(new ReferenceFilterOperation(reference, type));
+ }
+
+ const AtomicString& reference() const { return m_reference; }
+
+private:
+
+ virtual bool operator==(const FilterOperation& o) const
+ {
+ if (!isSameType(o))
+ return false;
+ const ReferenceFilterOperation* other = static_cast<const ReferenceFilterOperation*>(&o);
+ return m_reference == other->m_reference;
+ }
+
+ ReferenceFilterOperation(const AtomicString& reference, OperationType type)
+ : FilterOperation(type)
+ , m_reference(reference)
+ {
+ }
+
+ AtomicString m_reference;
+};
+
+// GRAYSCALE, SEPIA, SATURATE and HUE_ROTATE are variations on a basic color matrix effect.
+// For HUE_ROTATE, the angle of rotation is stored in m_amount.
+class BasicColorMatrixFilterOperation : public FilterOperation {
+public:
+ static PassRefPtr<BasicColorMatrixFilterOperation> create(double amount, OperationType type)
+ {
+ return adoptRef(new BasicColorMatrixFilterOperation(amount, type));
+ }
+
+ double amount() const { return m_amount; }
+
+ virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false);
+
+private:
+ virtual bool operator==(const FilterOperation& o) const
+ {
+ if (!isSameType(o))
+ return false;
+ const BasicColorMatrixFilterOperation* other = static_cast<const BasicColorMatrixFilterOperation*>(&o);
+ return m_amount == other->m_amount;
+ }
+
+ double passthroughAmount() const;
+
+ BasicColorMatrixFilterOperation(double amount, OperationType type)
+ : FilterOperation(type)
+ , m_amount(amount)
+ {
+ }
+
+ double m_amount;
+};
+
+// INVERT, BRIGHTNESS, CONTRAST and OPACITY are variations on a basic component transfer effect.
+class BasicComponentTransferFilterOperation : public FilterOperation {
+public:
+ static PassRefPtr<BasicComponentTransferFilterOperation> create(double amount, OperationType type)
+ {
+ return adoptRef(new BasicComponentTransferFilterOperation(amount, type));
+ }
+
+ double amount() const { return m_amount; }
+
+ virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false);
+
+private:
+ virtual bool operator==(const FilterOperation& o) const
+ {
+ if (!isSameType(o))
+ return false;
+ const BasicComponentTransferFilterOperation* other = static_cast<const BasicComponentTransferFilterOperation*>(&o);
+ return m_amount == other->m_amount;
+ }
+
+ double passthroughAmount() const;
+
+ BasicComponentTransferFilterOperation(double amount, OperationType type)
+ : FilterOperation(type)
+ , m_amount(amount)
+ {
+ }
+
+ double m_amount;
+};
+
+class GammaFilterOperation : public FilterOperation {
+public:
+ static PassRefPtr<GammaFilterOperation> create(double amplitude, double exponent, double offset, OperationType type)
+ {
+ return adoptRef(new GammaFilterOperation(amplitude, exponent, offset, type));
+ }
+
+ double amplitude() const { return m_amplitude; }
+ double exponent() const { return m_exponent; }
+ double offset() const { return m_offset; }
+
+ virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false);
+
+private:
+ virtual bool operator==(const FilterOperation& o) const
+ {
+ if (!isSameType(o))
+ return false;
+ const GammaFilterOperation* other = static_cast<const GammaFilterOperation*>(&o);
+ return m_amplitude == other->m_amplitude && m_exponent == other->m_exponent && m_offset == other->m_offset;
+ }
+
+ GammaFilterOperation(double amplitude, double exponent, double offset, OperationType type)
+ : FilterOperation(type)
+ , m_amplitude(amplitude)
+ , m_exponent(exponent)
+ , m_offset(offset)
+ {
+ }
+
+ double m_amplitude;
+ double m_exponent;
+ double m_offset;
+};
+
+class BlurFilterOperation : public FilterOperation {
+public:
+ static PassRefPtr<BlurFilterOperation> create(Length stdDeviation, OperationType type)
+ {
+ return adoptRef(new BlurFilterOperation(stdDeviation, type));
+ }
+
+ Length stdDeviation() const { return m_stdDeviation; }
+
+ virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false);
+
+private:
+ virtual bool operator==(const FilterOperation& o) const
+ {
+ if (!isSameType(o))
+ return false;
+ const BlurFilterOperation* other = static_cast<const BlurFilterOperation*>(&o);
+ return m_stdDeviation == other->m_stdDeviation;
+ }
+
+ BlurFilterOperation(Length stdDeviation, OperationType type)
+ : FilterOperation(type)
+ , m_stdDeviation(stdDeviation)
+ {
+ }
+
+ Length m_stdDeviation;
+};
+
+class DropShadowFilterOperation : public FilterOperation {
+public:
+ static PassRefPtr<DropShadowFilterOperation> create(int x, int y, int stdDeviation, Color color, OperationType type)
+ {
+ return adoptRef(new DropShadowFilterOperation(x, y, stdDeviation, color, type));
+ }
+
+ int x() const { return m_x; }
+ int y() const { return m_y; }
+ int stdDeviation() const { return m_stdDeviation; }
+ Color color() const { return m_color; }
+
+ virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false);
+
+private:
+
+ virtual bool operator==(const FilterOperation& o) const
+ {
+ if (!isSameType(o))
+ return false;
+ const DropShadowFilterOperation* other = static_cast<const DropShadowFilterOperation*>(&o);
+ return m_x == other->m_x && m_y == other->m_y && m_stdDeviation == other->m_stdDeviation && m_color == other->m_color;
+ }
+
+ DropShadowFilterOperation(int x, int y, int stdDeviation, Color color, OperationType type)
+ : FilterOperation(type)
+ , m_x(x)
+ , m_y(y)
+ , m_stdDeviation(stdDeviation)
+ , m_color(color)
+ {
+ }
+
+ int m_x; // FIXME: x and y should be Lengths?
+ int m_y;
+ int m_stdDeviation;
+ Color m_color;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_FILTERS)
+
+#endif // FilterOperation_h
diff --git a/Source/WebCore/platform/graphics/filters/FilterOperations.cpp b/Source/WebCore/platform/graphics/filters/FilterOperations.cpp
new file mode 100644
index 000000000..dd92ac1aa
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FilterOperations.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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"
+#include "FilterOperations.h"
+
+#include "FEGaussianBlur.h"
+#include "IntSize.h"
+
+#if ENABLE(CSS_FILTERS)
+
+namespace WebCore {
+
+static inline IntSize outsetSizeForBlur(float stdDeviation)
+{
+ unsigned kernelSizeX = 0;
+ unsigned kernelSizeY = 0;
+ FEGaussianBlur::calculateUnscaledKernelSize(kernelSizeX, kernelSizeY, stdDeviation, stdDeviation);
+
+ IntSize outset;
+ // We take the half kernel size and multiply it with three, because we run box blur three times.
+ outset.setWidth(3 * kernelSizeX * 0.5f);
+ outset.setHeight(3 * kernelSizeY * 0.5f);
+
+ return outset;
+}
+
+FilterOperations::FilterOperations()
+{
+}
+
+FilterOperations& FilterOperations::operator=(const FilterOperations& other)
+{
+ m_operations = other.m_operations;
+ return *this;
+}
+
+bool FilterOperations::operator==(const FilterOperations& o) const
+{
+ if (m_operations.size() != o.m_operations.size())
+ return false;
+
+ unsigned s = m_operations.size();
+ for (unsigned i = 0; i < s; i++) {
+ if (*m_operations[i] != *o.m_operations[i])
+ return false;
+ }
+
+ return true;
+}
+
+bool FilterOperations::operationsMatch(const FilterOperations& other) const
+{
+ size_t numOperations = operations().size();
+ // If the sizes of the function lists don't match, the lists don't match
+ if (numOperations != other.operations().size())
+ return false;
+
+ // If the types of each function are not the same, the lists don't match
+ for (size_t i = 0; i < numOperations; ++i) {
+ if (!operations()[i]->isSameType(*other.operations()[i]))
+ return false;
+ }
+ return true;
+}
+
+bool FilterOperations::hasOutsets() const
+{
+ for (size_t i = 0; i < m_operations.size(); ++i) {
+ FilterOperation::OperationType operationType = m_operations.at(i).get()->getOperationType();
+ if (operationType == FilterOperation::BLUR || operationType == FilterOperation::DROP_SHADOW)
+ return true;
+ }
+ return false;
+}
+
+void FilterOperations::getOutsets(LayoutUnit& top, LayoutUnit& right, LayoutUnit& bottom, LayoutUnit& left) const
+{
+ top = 0;
+ right = 0;
+ bottom = 0;
+ left = 0;
+ for (size_t i = 0; i < m_operations.size(); ++i) {
+ FilterOperation* filterOperation = m_operations.at(i).get();
+ switch (filterOperation->getOperationType()) {
+ case FilterOperation::BLUR: {
+ BlurFilterOperation* blurOperation = static_cast<BlurFilterOperation*>(filterOperation);
+ float stdDeviation = blurOperation->stdDeviation().calcFloatValue(0);
+ IntSize outset = outsetSizeForBlur(stdDeviation);
+ top += outset.height();
+ right += outset.width();
+ bottom += outset.height();
+ left += outset.width();
+ break;
+ }
+ case FilterOperation::DROP_SHADOW: {
+ DropShadowFilterOperation* dropShadowOperation = static_cast<DropShadowFilterOperation*>(filterOperation);
+ IntSize outset = outsetSizeForBlur(dropShadowOperation->stdDeviation());
+ top += outset.height() - dropShadowOperation->y();
+ right += outset.width() + dropShadowOperation->x();
+ bottom += outset.height() + dropShadowOperation->y();
+ left += outset.width() - dropShadowOperation->x();
+ break;
+ }
+#if ENABLE(CSS_SHADERS)
+ case FilterOperation::CUSTOM: {
+ // Need to include the filter margins here.
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+ }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_FILTERS)
diff --git a/Source/WebCore/platform/graphics/filters/FilterOperations.h b/Source/WebCore/platform/graphics/filters/FilterOperations.h
new file mode 100644
index 000000000..64cee8808
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/FilterOperations.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 FilterOperations_h
+#define FilterOperations_h
+
+#if ENABLE(CSS_FILTERS)
+
+#include "FilterOperation.h"
+#include "LayoutTypes.h"
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class FilterOperations {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ FilterOperations();
+ FilterOperations(const FilterOperations& other) { *this = other; }
+
+ FilterOperations& operator=(const FilterOperations&);
+
+ bool operator==(const FilterOperations&) const;
+ bool operator!=(const FilterOperations& o) const
+ {
+ return !(*this == o);
+ }
+
+ void clear()
+ {
+ m_operations.clear();
+ }
+
+ Vector<RefPtr<FilterOperation> >& operations() { return m_operations; }
+ const Vector<RefPtr<FilterOperation> >& operations() const { return m_operations; }
+
+ size_t size() const { return m_operations.size(); }
+ const FilterOperation* at(size_t index) const { return index < m_operations.size() ? m_operations.at(index).get() : 0; }
+
+ bool operationsMatch(const FilterOperations&) const;
+
+ bool hasOutsets() const;
+ void getOutsets(LayoutUnit& top, LayoutUnit& right, LayoutUnit& bottom, LayoutUnit& left) const;
+
+private:
+ Vector<RefPtr<FilterOperation> > m_operations;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_FILTERS)
+
+#endif // FilterOperations_h
diff --git a/Source/WebCore/platform/graphics/filters/LightSource.cpp b/Source/WebCore/platform/graphics/filters/LightSource.cpp
new file mode 100644
index 000000000..cf262e852
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/LightSource.cpp
@@ -0,0 +1,115 @@
+/*
+ * 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>
+ * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>, University of Szeged.
+ *
+ * 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 {
+
+bool LightSource::setAzimuth(float azimuth)
+{
+ if (m_type == LS_DISTANT)
+ return static_cast<DistantLightSource*>(this)->setAzimuth(azimuth);
+ return false;
+}
+
+bool LightSource::setElevation(float elevation)
+{
+ if (m_type == LS_DISTANT)
+ return static_cast<DistantLightSource*>(this)->setElevation(elevation);
+ return false;
+}
+
+bool LightSource::setX(float x)
+{
+ if (m_type == LS_SPOT)
+ return static_cast<SpotLightSource*>(this)->setX(x);
+ if (m_type == LS_POINT)
+ return static_cast<PointLightSource*>(this)->setX(x);
+ return false;
+}
+
+bool LightSource::setY(float y)
+{
+ if (m_type == LS_SPOT)
+ return static_cast<SpotLightSource*>(this)->setY(y);
+ if (m_type == LS_POINT)
+ return static_cast<PointLightSource*>(this)->setY(y);
+ return false;
+}
+
+bool LightSource::setZ(float z)
+{
+ if (m_type == LS_SPOT)
+ return static_cast<SpotLightSource*>(this)->setZ(z);
+ if (m_type == LS_POINT)
+ return static_cast<PointLightSource*>(this)->setZ(z);
+ return false;
+}
+
+bool LightSource::setPointsAtX(float pointsAtX)
+{
+ if (m_type == LS_SPOT)
+ return static_cast<SpotLightSource*>(this)->setPointsAtX(pointsAtX);
+ return false;
+}
+
+bool LightSource::setPointsAtY(float pointsAtY)
+{
+ if (m_type == LS_SPOT)
+ return static_cast<SpotLightSource*>(this)->setPointsAtY(pointsAtY);
+ return false;
+}
+
+bool LightSource::setPointsAtZ(float pointsAtZ)
+{
+ if (m_type == LS_SPOT)
+ return static_cast<SpotLightSource*>(this)->setPointsAtZ(pointsAtZ);
+ return false;
+}
+
+bool LightSource::setSpecularExponent(float specularExponent)
+{
+ if (m_type == LS_SPOT)
+ return static_cast<SpotLightSource*>(this)->setSpecularExponent(specularExponent);
+ return false;
+}
+
+bool LightSource::setLimitingConeAngle(float limitingConeAngle)
+{
+ if (m_type == LS_SPOT)
+ return static_cast<SpotLightSource*>(this)->setLimitingConeAngle(limitingConeAngle);
+ return false;
+}
+
+} // 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 000000000..24c319a61
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/LightSource.h
@@ -0,0 +1,96 @@
+/*
+ * 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;
+
+ bool setAzimuth(float);
+ bool setElevation(float);
+ bool setX(float);
+ bool setY(float);
+ bool setZ(float);
+ bool setPointsAtX(float);
+ bool setPointsAtY(float);
+ bool setPointsAtZ(float);
+ bool setSpecularExponent(float);
+ bool setLimitingConeAngle(float);
+
+private:
+ LightType m_type;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(FILTERS)
+
+#endif // LightSource_h
diff --git a/Source/WebCore/platform/graphics/filters/PointLightSource.cpp b/Source/WebCore/platform/graphics/filters/PointLightSource.cpp
new file mode 100644
index 000000000..207ed8eae
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/PointLightSource.cpp
@@ -0,0 +1,91 @@
+/*
+ * 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>
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
+ *
+ * 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 "PointLightSource.h"
+
+#include "TextStream.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();
+}
+
+bool PointLightSource::setX(float x)
+{
+ if (m_position.x() == x)
+ return false;
+ m_position.setX(x);
+ return true;
+}
+
+bool PointLightSource::setY(float y)
+{
+ if (m_position.y() == y)
+ return false;
+ m_position.setY(y);
+ return true;
+}
+
+bool PointLightSource::setZ(float z)
+{
+ if (m_position.z() == z)
+ return false;
+ m_position.setZ(z);
+ return true;
+}
+
+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;
+}
+
+}; // namespace WebCore
+
+#endif // ENABLE(FILTERS)
diff --git a/Source/WebCore/platform/graphics/filters/PointLightSource.h b/Source/WebCore/platform/graphics/filters/PointLightSource.h
new file mode 100644
index 000000000..a93bf2cf7
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/PointLightSource.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 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; }
+ bool setX(float);
+ bool setY(float);
+ bool setZ(float);
+
+ 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 000000000..aeebde6f8
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp
@@ -0,0 +1,84 @@
+/*
+ * 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 "Filter.h"
+#include "GraphicsContext.h"
+#include "PlatformString.h"
+#include "RenderTreeAsText.h"
+#include "TextStream.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::platformApplySoftware()
+{
+ ImageBuffer* resultImage = createImageBufferResult();
+ Filter* filter = this->filter();
+ if (!resultImage || !filter->sourceImage())
+ return;
+
+ setIsAlphaImage(true);
+
+ FloatRect imageRect(FloatPoint(), absolutePaintRect().size());
+ GraphicsContext* filterContext = resultImage->context();
+ GraphicsContextStateSaver stateSaver(*filterContext);
+ filterContext->clipToImageBuffer(filter->sourceImage(), imageRect);
+ filterContext->fillRect(imageRect, Color::black, ColorSpaceDeviceRGB);
+}
+
+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 000000000..62f19fc41
--- /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 platformApplySoftware();
+ 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 000000000..f46d87da8
--- /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 "Filter.h"
+#include "GraphicsContext.h"
+#include "PlatformString.h"
+#include "RenderTreeAsText.h"
+#include "TextStream.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::platformApplySoftware()
+{
+ 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 000000000..06e6d09ba
--- /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 platformApplySoftware();
+ 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.cpp b/Source/WebCore/platform/graphics/filters/SpotLightSource.cpp
new file mode 100644
index 000000000..648fcae6d
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/SpotLightSource.cpp
@@ -0,0 +1,198 @@
+/*
+ * 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>
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
+ *
+ * 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 "SpotLightSource.h"
+
+#include "TextStream.h"
+
+namespace WebCore {
+
+// 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);
+}
+
+bool SpotLightSource::setX(float x)
+{
+ if (m_position.x() == x)
+ return false;
+ m_position.setX(x);
+ return true;
+}
+
+bool SpotLightSource::setY(float y)
+{
+ if (m_position.y() == y)
+ return false;
+ m_position.setY(y);
+ return true;
+}
+
+bool SpotLightSource::setZ(float z)
+{
+ if (m_position.z() == z)
+ return false;
+ m_position.setZ(z);
+ return true;
+}
+
+bool SpotLightSource::setPointsAtX(float pointsAtX)
+{
+ if (m_direction.x() == pointsAtX)
+ return false;
+ m_direction.setX(pointsAtX);
+ return true;
+}
+
+bool SpotLightSource::setPointsAtY(float pointsAtY)
+{
+ if (m_direction.y() == pointsAtY)
+ return false;
+ m_direction.setY(pointsAtY);
+ return true;
+}
+
+bool SpotLightSource::setPointsAtZ(float pointsAtZ)
+{
+ if (m_direction.z() == pointsAtZ)
+ return false;
+ m_direction.setZ(pointsAtZ);
+ return true;
+}
+
+bool SpotLightSource::setSpecularExponent(float specularExponent)
+{
+ if (m_specularExponent == specularExponent)
+ return false;
+ m_specularExponent = specularExponent;
+ return true;
+}
+
+bool SpotLightSource::setLimitingConeAngle(float limitingConeAngle)
+{
+ if (m_limitingConeAngle == limitingConeAngle)
+ return false;
+ m_limitingConeAngle = limitingConeAngle;
+ return true;
+}
+
+static TextStream& operator<<(TextStream& ts, const FloatPoint3D& p)
+{
+ ts << "x=" << p.x() << " y=" << p.y() << " z=" << p.z();
+ 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;
+}
+
+}; // namespace WebCore
+
+#endif // ENABLE(FILTERS)
diff --git a/Source/WebCore/platform/graphics/filters/SpotLightSource.h b/Source/WebCore/platform/graphics/filters/SpotLightSource.h
new file mode 100644
index 000000000..b4f1b6182
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/SpotLightSource.h
@@ -0,0 +1,80 @@
+/*
+ * 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; }
+ bool setX(float);
+ bool setY(float);
+ bool setZ(float);
+ const FloatPoint3D& direction() const { return m_direction; }
+ bool setPointsAtX(float);
+ bool setPointsAtY(float);
+ bool setPointsAtZ(float);
+
+ float specularExponent() const { return m_specularExponent; }
+ bool setSpecularExponent(float);
+ float limitingConeAngle() const { return m_limitingConeAngle; }
+ bool setLimitingConeAngle(float);
+
+ 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
diff --git a/Source/WebCore/platform/graphics/filters/arm/FECompositeArithmeticNEON.cpp b/Source/WebCore/platform/graphics/filters/arm/FECompositeArithmeticNEON.cpp
new file mode 100644
index 000000000..22a845823
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/arm/FECompositeArithmeticNEON.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 Felician Marton
+ *
+ * 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 "FECompositeArithmeticNEON.h"
+
+#if CPU(ARM_NEON) && COMPILER(GCC)
+
+namespace WebCore {
+
+#define ASSTRING(str) #str
+#define TOSTRING(value) ASSTRING(value)
+
+#define NL "\n"
+
+#define SOURCE_R "r0"
+#define DEST_R "r1"
+#define END_R "r2"
+#define K_R "r3"
+#define NEXTPIXEL_R "r12"
+
+#define TEMP_Q "q0"
+#define TEMP_D0 "d0"
+#define TEMP_D00 "d0[0]"
+#define TEMP_D01 "d0[1]"
+#define TEMP_D10 "d1[0]"
+#define TEMP_D11 "d1[1]"
+#define PIXEL1_Q "q1"
+#define PIXEL1_D0 "d2"
+#define PIXEL1_D00 "d2[0]"
+#define PIXEL2_Q "q2"
+#define PIXEL2_D0 "d4"
+#define PIXEL2_D00 "d4[0]"
+#define BYTEMAX_Q "q3"
+#define K1_Q "q8"
+#define K2_Q "q9"
+#define K3_Q "q10"
+#define K4_Q "q11"
+
+asm ( // NOLINT
+".globl " TOSTRING(neonDrawCompositeArithmetic) NL
+TOSTRING(neonDrawCompositeArithmetic) ":" NL
+ "cmp " END_R ", #0" NL
+ "bxeq lr" NL
+ // Set the end of the source register.
+ "add " END_R ", " SOURCE_R ", " END_R NL
+
+ "vld1.f32 {" TEMP_Q "}, [" K_R "]" NL
+ "ldr " K_R ", [" K_R "]" NL
+ "vdup.f32 " K1_Q ", " TEMP_D00 NL
+ "vdup.f32 " K2_Q ", " TEMP_D01 NL
+ "vdup.f32 " K3_Q ", " TEMP_D10 NL
+ "vdup.f32 " K4_Q ", " TEMP_D11 NL
+
+ "vmov.i32 " BYTEMAX_Q ", #0xFF" NL
+ "vcvt.f32.u32 " TEMP_Q ", " BYTEMAX_Q NL
+ "vmul.f32 " K4_Q ", " K4_Q ", " TEMP_Q NL
+
+ "mov " NEXTPIXEL_R ", #4" NL
+ "cmp " K_R ", #0" NL
+ "beq .arithmeticK1IsZero" NL
+
+ "vrecpe.f32 " TEMP_Q ", " TEMP_Q NL
+ "vmul.f32 " K1_Q ", " K1_Q ", " TEMP_Q NL
+
+".arithmeticK1IsNonZero:" NL
+
+ "vld1.u32 " PIXEL1_D00 ", [ " SOURCE_R "], " NEXTPIXEL_R NL
+ "vld1.u32 " PIXEL2_D00 ", [" DEST_R "]" NL
+
+ "vmovl.u8 " PIXEL1_Q ", " PIXEL1_D0 NL
+ "vmovl.u16 " PIXEL1_Q ", " PIXEL1_D0 NL
+ "vcvt.f32.u32 " PIXEL1_Q ", " PIXEL1_Q NL
+ "vmovl.u8 " PIXEL2_Q ", " PIXEL2_D0 NL
+ "vmovl.u16 " PIXEL2_Q ", " PIXEL2_D0 NL
+ "vcvt.f32.u32 " PIXEL2_Q ", " PIXEL2_Q NL
+
+ "vmul.f32 " TEMP_Q ", " PIXEL1_Q ", " PIXEL2_Q NL
+ "vmul.f32 " TEMP_Q ", " TEMP_Q ", " K1_Q NL
+ "vmla.f32 " TEMP_Q ", " PIXEL1_Q ", " K2_Q NL
+ "vmla.f32 " TEMP_Q ", " PIXEL2_Q ", " K3_Q NL
+ "vadd.f32 " TEMP_Q ", " K4_Q NL
+
+ // Convert result to uint so negative values are converted to zero.
+ "vcvt.u32.f32 " TEMP_Q ", " TEMP_Q NL
+ "vmin.u32 " TEMP_Q ", " TEMP_Q ", " BYTEMAX_Q NL
+ "vmovn.u32 " TEMP_D0 ", " TEMP_Q NL
+ "vmovn.u16 " TEMP_D0 ", " TEMP_Q NL
+
+ "vst1.u32 " TEMP_D00 ", [" DEST_R "], " NEXTPIXEL_R NL
+
+ "cmp " SOURCE_R ", " END_R NL
+ "bcc .arithmeticK1IsNonZero" NL
+ "bx lr" NL
+
+".arithmeticK1IsZero:" NL
+
+ "vld1.u32 " PIXEL1_D00 ", [ " SOURCE_R "], " NEXTPIXEL_R NL
+ "vld1.u32 " PIXEL2_D00 ", [" DEST_R "]" NL
+
+ "vmovl.u8 " PIXEL1_Q ", " PIXEL1_D0 NL
+ "vmovl.u16 " PIXEL1_Q ", " PIXEL1_D0 NL
+ "vcvt.f32.u32 " PIXEL1_Q ", " PIXEL1_Q NL
+ "vmovl.u8 " PIXEL2_Q ", " PIXEL2_D0 NL
+ "vmovl.u16 " PIXEL2_Q ", " PIXEL2_D0 NL
+ "vcvt.f32.u32 " PIXEL2_Q ", " PIXEL2_Q NL
+
+ "vmul.f32 " TEMP_Q ", " PIXEL1_Q ", " K2_Q NL
+ "vmla.f32 " TEMP_Q ", " PIXEL2_Q ", " K3_Q NL
+ "vadd.f32 " TEMP_Q ", " K4_Q NL
+
+ // Convert result to uint so negative values are converted to zero.
+ "vcvt.u32.f32 " TEMP_Q ", " TEMP_Q NL
+ "vmin.u32 " TEMP_Q ", " TEMP_Q ", " BYTEMAX_Q NL
+ "vmovn.u32 " TEMP_D0 ", " TEMP_Q NL
+ "vmovn.u16 " TEMP_D0 ", " TEMP_Q NL
+
+ "vst1.u32 " TEMP_D00 ", [" DEST_R "], " NEXTPIXEL_R NL
+
+ "cmp " SOURCE_R ", " END_R NL
+ "bcc .arithmeticK1IsZero" NL
+ "bx lr" NL
+); // NOLINT
+
+} // namespace WebCore
+
+#endif // CPU(ARM_NEON) && COMPILER(GCC)
+
+#endif // ENABLE(FILTERS)
+
diff --git a/Source/WebCore/platform/graphics/filters/arm/FECompositeArithmeticNEON.h b/Source/WebCore/platform/graphics/filters/arm/FECompositeArithmeticNEON.h
new file mode 100644
index 000000000..a2b3f6f4d
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/arm/FECompositeArithmeticNEON.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 Felician Marton
+ *
+ * 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 FECompositeArithmeticNEON_h
+#define FECompositeArithmeticNEON_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(FILTERS)
+#if CPU(ARM_NEON) && COMPILER(GCC)
+
+#include "FEComposite.h"
+
+namespace WebCore {
+
+extern "C" {
+void neonDrawCompositeArithmetic(unsigned char* source, unsigned char* destination, unsigned pixelArrayLength, float* coefficients);
+}
+
+inline void FEComposite::platformArithmeticNeon(unsigned char* source, unsigned char* destination, unsigned pixelArrayLength, float* coefficients)
+{
+ neonDrawCompositeArithmetic(source, destination, pixelArrayLength, coefficients);
+}
+
+} // namespace WebCore
+
+#endif // CPU(ARM_NEON) && COMPILER(GCC)
+#endif // ENABLE(FILTERS)
+
+#endif // FECompositeArithmeticNEON_h
diff --git a/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.cpp b/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.cpp
new file mode 100644
index 000000000..d17f2caf4
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.cpp
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 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"
+#include "FEGaussianBlurNEON.h"
+
+#if CPU(ARM_NEON) && COMPILER(GCC)
+
+#include <wtf/Alignment.h>
+
+namespace WebCore {
+
+static WTF_ALIGNED(unsigned char, s_FEGaussianBlurConstantsForNeon[], 16) = {
+ // Mapping from NEON to ARM registers.
+ 0, 4, 8, 12, 16, 16, 16, 16
+};
+
+unsigned char* feGaussianBlurConstantsForNeon()
+{
+ return s_FEGaussianBlurConstantsForNeon;
+}
+
+#define ASSTRING(str) #str
+#define TOSTRING(value) ASSTRING(value)
+
+#define STRIDE_OFFSET TOSTRING(0)
+#define STRIDE_WIDTH_OFFSET TOSTRING(4)
+#define STRIDE_LINE_OFFSET TOSTRING(8)
+#define STRIDE_LINE_WIDTH_OFFSET TOSTRING(12)
+#define REMAINING_STRIDES_OFFSET TOSTRING(16)
+#define DISTANCE_LEFT_OFFSET TOSTRING(20)
+#define DISTANCE_RIGHT_OFFSET TOSTRING(24)
+#define INVERTED_KERNEL_SIZE_OFFSET TOSTRING(28)
+#define PAINTING_CONSTANTS_OFFSET TOSTRING(32)
+#define NL "\n"
+
+// Register allocation.
+#define SOURCE_R "r0"
+#define DESTINATION_R "r1"
+#define LEFT_R "r2"
+#define RIGHT_R "r3"
+#define SOURCE_END_R "r4"
+#define DESTINATION_END_R "r5"
+#define STRIDE_R "r6"
+#define STRIDE_WIDTH_R "r7"
+#define STRIDE_LINE_R "r8"
+#define SOURCE_LINE_END_R "r10"
+#define DISTANCE_LEFT_R "r11"
+#define DISTANCE_RIGHT_R "r12"
+#define MAX_KERNEL_SIZE_R "lr"
+
+// Alternate names.
+#define INIT_INVERTED_KERNEL_SIZE_R SOURCE_END_R
+#define INIT_PAINTING_CONSTANTS_R DESTINATION_END_R
+#define INIT_SUM_R LEFT_R
+#define REMAINING_STRIDES_R SOURCE_LINE_END_R
+
+#define INVERTED_KERNEL_SIZE_Q "q0"
+#define SUM_Q "q1"
+#define PIXEL_Q "q2"
+#define PIXEL_D0 "d4"
+#define PIXEL_D1 "d5"
+#define PIXEL_D00 "d4[0]"
+#define PIXEL_D01 "d4[1]"
+#define PIXEL_S1 "s9"
+#define PIXEL_D10 "d5[0]"
+#define PIXEL_S2 "s10"
+#define PIXEL_D11 "d5[1]"
+#define REMAINING_STRIDES_S0 "s12"
+
+#define REMAP_NEON_ARM_Q "d16"
+
+asm ( // NOLINT
+".globl " TOSTRING(neonDrawAllChannelGaussianBlur) NL
+TOSTRING(neonDrawAllChannelGaussianBlur) ":" NL
+ "stmdb sp!, {r4-r8, r10, r11, lr}" NL
+ "ldr " STRIDE_R ", [r2, #" STRIDE_OFFSET "]" NL
+ "ldr " STRIDE_WIDTH_R ", [r2, #" STRIDE_WIDTH_OFFSET "]" NL
+ "ldr " DISTANCE_LEFT_R ", [r2, #" DISTANCE_LEFT_OFFSET "]" NL
+ "ldr " DISTANCE_RIGHT_R ", [r2, #" DISTANCE_RIGHT_OFFSET "]" NL
+ "ldr " STRIDE_LINE_R ", [r2, #" STRIDE_LINE_OFFSET "]" NL
+ "ldr " SOURCE_LINE_END_R ", [r2, #" STRIDE_LINE_WIDTH_OFFSET "]" NL
+ "ldr " INIT_INVERTED_KERNEL_SIZE_R ", [r2, #" INVERTED_KERNEL_SIZE_OFFSET "]" NL
+ "ldr " INIT_PAINTING_CONSTANTS_R ", [r2, #" PAINTING_CONSTANTS_OFFSET "]" NL
+
+ // Initialize locals.
+ "mul " DISTANCE_LEFT_R ", " DISTANCE_LEFT_R ", " STRIDE_R NL
+ "mul " DISTANCE_RIGHT_R ", " DISTANCE_RIGHT_R ", " STRIDE_R NL
+ "mov " MAX_KERNEL_SIZE_R ", " DISTANCE_RIGHT_R NL
+ "cmp " MAX_KERNEL_SIZE_R ", " STRIDE_WIDTH_R NL
+ "movcs " MAX_KERNEL_SIZE_R ", " STRIDE_WIDTH_R NL
+ "add " SOURCE_LINE_END_R ", " SOURCE_LINE_END_R ", " SOURCE_R NL
+ "vdup.f32 " INVERTED_KERNEL_SIZE_Q ", " INIT_INVERTED_KERNEL_SIZE_R NL
+ "vld1.f32 { " REMAP_NEON_ARM_Q " }, [" INIT_PAINTING_CONSTANTS_R "]!" NL
+
+".allChannelMainLoop:" NL
+
+ // Initialize the sum variable.
+ "vmov.u32 " SUM_Q ", #0" NL
+ "mov " INIT_SUM_R ", " SOURCE_R NL
+ "add " SOURCE_END_R ", " SOURCE_R ", " MAX_KERNEL_SIZE_R NL
+ "cmp " INIT_SUM_R ", " SOURCE_END_R NL
+ "bcs .allChannelInitSumDone" NL
+".allChannelInitSum:" NL
+ "vld1.u32 " PIXEL_D00 ", [" INIT_SUM_R "], " STRIDE_R NL
+ "vmovl.u8 " PIXEL_Q ", " PIXEL_D0 NL
+ "vmovl.u16 " PIXEL_Q ", " PIXEL_D0 NL
+ "vadd.u32 " SUM_Q ", " SUM_Q ", " PIXEL_Q NL
+ "cmp " INIT_SUM_R ", " SOURCE_END_R NL
+ "bcc .allChannelInitSum" NL
+".allChannelInitSumDone:" NL
+
+ // Blurring.
+ "add " SOURCE_END_R ", " SOURCE_R ", " STRIDE_WIDTH_R NL
+ "add " DESTINATION_END_R ", " DESTINATION_R ", " STRIDE_WIDTH_R NL
+ "sub " LEFT_R ", " SOURCE_R ", " DISTANCE_LEFT_R NL
+ "add " RIGHT_R ", " SOURCE_R ", " DISTANCE_RIGHT_R NL
+
+".allChannelBlur:" NL
+ "vcvt.f32.u32 " PIXEL_Q ", " SUM_Q NL
+ "vmul.f32 " PIXEL_Q ", " PIXEL_Q ", " INVERTED_KERNEL_SIZE_Q NL
+ "vcvt.u32.f32 " PIXEL_Q ", " PIXEL_Q NL
+ "vtbl.8 " PIXEL_D0 ", {" PIXEL_D0 "-" PIXEL_D1 "}, " REMAP_NEON_ARM_Q NL
+ "vst1.u32 " PIXEL_D00 ", [" DESTINATION_R "], " STRIDE_R NL
+
+ "cmp " LEFT_R ", " SOURCE_R NL
+ "bcc .allChannelSkipLeft" NL
+ "vld1.u32 " PIXEL_D00 ", [" LEFT_R "]" NL
+ "vmovl.u8 " PIXEL_Q ", " PIXEL_D0 NL
+ "vmovl.u16 " PIXEL_Q ", " PIXEL_D0 NL
+ "vsub.u32 " SUM_Q ", " SUM_Q ", " PIXEL_Q NL
+".allChannelSkipLeft: " NL
+
+ "cmp " RIGHT_R ", " SOURCE_END_R NL
+ "bcs .allChannelSkipRight" NL
+ "vld1.u32 " PIXEL_D00 ", [" RIGHT_R "]" NL
+ "vmovl.u8 " PIXEL_Q ", " PIXEL_D0 NL
+ "vmovl.u16 " PIXEL_Q ", " PIXEL_D0 NL
+ "vadd.u32 " SUM_Q ", " SUM_Q ", " PIXEL_Q NL
+".allChannelSkipRight: " NL
+
+ "add " LEFT_R ", " LEFT_R ", " STRIDE_R NL
+ "add " RIGHT_R ", " RIGHT_R ", " STRIDE_R NL
+ "cmp " DESTINATION_R ", " DESTINATION_END_R NL
+ "bcc .allChannelBlur" NL
+ "sub " DESTINATION_R ", " DESTINATION_R ", " STRIDE_WIDTH_R NL
+
+ "add " SOURCE_R ", " SOURCE_R ", " STRIDE_LINE_R NL
+ "add " DESTINATION_R ", " DESTINATION_R ", " STRIDE_LINE_R NL
+ "cmp " SOURCE_R ", " SOURCE_LINE_END_R NL
+ "bcc .allChannelMainLoop" NL
+
+ "ldmia sp!, {r4-r8, r10, r11, pc}" NL
+); // NOLINT
+
+#define DATA_TRANSFER4(command, base) \
+ command " " PIXEL_D00 ", [" base "], " STRIDE_LINE_R NL \
+ command " " PIXEL_D01 ", [" base "], " STRIDE_LINE_R NL \
+ command " " PIXEL_D10 ", [" base "], " STRIDE_LINE_R NL \
+ command " " PIXEL_D11 ", [" base "], " STRIDE_LINE_R NL \
+ "sub " base ", " base ", " STRIDE_LINE_R ", lsl #2" NL
+
+// The number of reads depend on REMAINING_STRIDES_R, but it is always >= 1 and <= 3
+#define CONDITIONAL_DATA_TRANSFER4(command1, command2, base) \
+ command1 " " PIXEL_D00 ", [" base "], " STRIDE_LINE_R NL \
+ "cmp " REMAINING_STRIDES_R ", #2" NL \
+ command2 "cs " PIXEL_S1 ", [" base "]" NL \
+ "add " base ", " base ", " STRIDE_LINE_R NL \
+ "cmp " REMAINING_STRIDES_R ", #3" NL \
+ command2 "cs " PIXEL_S2 ", [" base "]" NL \
+ "sub " base ", " base ", " STRIDE_LINE_R ", lsl #1" NL
+
+asm ( // NOLINT
+".globl " TOSTRING(neonDrawAlphaChannelGaussianBlur) NL
+TOSTRING(neonDrawAlphaChannelGaussianBlur) ":" NL
+ "stmdb sp!, {r4-r8, r10, r11, lr}" NL
+ "ldr " STRIDE_R ", [r2, #" STRIDE_OFFSET "]" NL
+ "ldr " STRIDE_WIDTH_R ", [r2, #" STRIDE_WIDTH_OFFSET "]" NL
+ "ldr " DISTANCE_LEFT_R ", [r2, #" DISTANCE_LEFT_OFFSET "]" NL
+ "ldr " DISTANCE_RIGHT_R ", [r2, #" DISTANCE_RIGHT_OFFSET "]" NL
+ "ldr " STRIDE_LINE_R ", [r2, #" STRIDE_LINE_OFFSET "]" NL
+ "ldr " SOURCE_LINE_END_R ", [r2, #" STRIDE_LINE_WIDTH_OFFSET "]" NL
+ "ldr " INIT_INVERTED_KERNEL_SIZE_R ", [r2, #" INVERTED_KERNEL_SIZE_OFFSET "]" NL
+ "vldr.u32 " REMAINING_STRIDES_S0 ", [r2, #" REMAINING_STRIDES_OFFSET "]" NL
+
+ // Initialize locals.
+ "mul " DISTANCE_LEFT_R ", " DISTANCE_LEFT_R ", " STRIDE_R NL
+ "mul " DISTANCE_RIGHT_R ", " DISTANCE_RIGHT_R ", " STRIDE_R NL
+ "mov " MAX_KERNEL_SIZE_R ", " DISTANCE_RIGHT_R NL
+ "cmp " MAX_KERNEL_SIZE_R ", " STRIDE_WIDTH_R NL
+ "movcs " MAX_KERNEL_SIZE_R ", " STRIDE_WIDTH_R NL
+ "add " SOURCE_LINE_END_R ", " SOURCE_LINE_END_R ", " SOURCE_R NL
+ "vdup.f32 " INVERTED_KERNEL_SIZE_Q ", " INIT_INVERTED_KERNEL_SIZE_R NL
+ "cmp " SOURCE_LINE_END_R ", " SOURCE_R NL
+ "beq .alphaChannelEarlyLeave" NL
+
+ // Processing 4 strides parallelly.
+
+".alphaChannelMainLoop:" NL
+
+ // Initialize the sum variable.
+ "vmov.u32 " SUM_Q ", #0" NL
+ "mov " INIT_SUM_R ", " SOURCE_R NL
+ "add " SOURCE_END_R ", " SOURCE_R ", " MAX_KERNEL_SIZE_R NL
+ "cmp " INIT_SUM_R ", " SOURCE_END_R NL
+ "bcs .alphaChannelInitSumDone" NL
+".alphaChannelInitSum:" NL
+ DATA_TRANSFER4("vld1.u32", INIT_SUM_R)
+ "vshr.u32 " PIXEL_Q ", " PIXEL_Q ", #24" NL
+ "vadd.u32 " SUM_Q ", " SUM_Q ", " PIXEL_Q NL
+ "add " INIT_SUM_R ", " INIT_SUM_R ", " STRIDE_R NL
+ "cmp " INIT_SUM_R ", " SOURCE_END_R NL
+ "bcc .alphaChannelInitSum" NL
+".alphaChannelInitSumDone:" NL
+
+ // Blurring.
+ "add " SOURCE_END_R ", " SOURCE_R ", " STRIDE_WIDTH_R NL
+ "add " DESTINATION_END_R ", " DESTINATION_R ", " STRIDE_WIDTH_R NL
+ "sub " LEFT_R ", " SOURCE_R ", " DISTANCE_LEFT_R NL
+ "add " RIGHT_R ", " SOURCE_R ", " DISTANCE_RIGHT_R NL
+
+".alphaChannelBlur:" NL
+ "vcvt.f32.u32 " PIXEL_Q ", " SUM_Q NL
+ "vmul.f32 " PIXEL_Q ", " PIXEL_Q ", " INVERTED_KERNEL_SIZE_Q NL
+ "vcvt.u32.f32 " PIXEL_Q ", " PIXEL_Q NL
+ "vshl.u32 " PIXEL_Q ", " PIXEL_Q ", #24" NL
+ DATA_TRANSFER4("vst1.u32", DESTINATION_R)
+
+ "cmp " LEFT_R ", " SOURCE_R NL
+ "bcc .alphaChannelSkipLeft" NL
+ DATA_TRANSFER4("vld1.u32", LEFT_R)
+ "vshr.u32 " PIXEL_Q ", " PIXEL_Q ", #24" NL
+ "vsub.u32 " SUM_Q ", " SUM_Q ", " PIXEL_Q NL
+".alphaChannelSkipLeft: " NL
+
+ "cmp " RIGHT_R ", " SOURCE_END_R NL
+ "bcs .alphaChannelSkipRight" NL
+ DATA_TRANSFER4("vld1.u32", RIGHT_R)
+ "vshr.u32 " PIXEL_Q ", " PIXEL_Q ", #24" NL
+ "vadd.u32 " SUM_Q ", " SUM_Q ", " PIXEL_Q NL
+".alphaChannelSkipRight: " NL
+
+ "add " DESTINATION_R ", " DESTINATION_R ", " STRIDE_R NL
+ "add " LEFT_R ", " LEFT_R ", " STRIDE_R NL
+ "add " RIGHT_R ", " RIGHT_R ", " STRIDE_R NL
+ "cmp " DESTINATION_R ", " DESTINATION_END_R NL
+ "bcc .alphaChannelBlur" NL
+ "sub " DESTINATION_R ", " DESTINATION_R ", " STRIDE_WIDTH_R NL
+
+ "add " SOURCE_R ", " SOURCE_R ", " STRIDE_LINE_R ", lsl #2" NL
+ "add " DESTINATION_R ", " DESTINATION_R ", " STRIDE_LINE_R ", lsl #2" NL
+ "cmp " SOURCE_R ", " SOURCE_LINE_END_R NL
+ "bcc .alphaChannelMainLoop" NL
+
+ // Processing the remaining strides (0 - 3).
+".alphaChannelEarlyLeave:" NL
+ "vmov.u32 " REMAINING_STRIDES_R ", " REMAINING_STRIDES_S0 NL
+ // Early return for 0 strides.
+ "cmp " REMAINING_STRIDES_R ", #0" NL
+ "ldmeqia sp!, {r4-r8, r10, r11, pc}" NL
+
+ // Initialize the sum variable.
+ "vmov.u32 " SUM_Q ", #0" NL
+ "mov " INIT_SUM_R ", " SOURCE_R NL
+ "add " SOURCE_END_R ", " SOURCE_R ", " MAX_KERNEL_SIZE_R NL
+ "cmp " INIT_SUM_R ", " SOURCE_END_R NL
+ "bcs .alphaChannelSecondInitSumDone" NL
+".alphaChannelSecondInitSum:" NL
+ CONDITIONAL_DATA_TRANSFER4("vld1.u32", "vldr", INIT_SUM_R)
+ "vshr.u32 " PIXEL_Q ", " PIXEL_Q ", #24" NL
+ "vadd.u32 " SUM_Q ", " SUM_Q ", " PIXEL_Q NL
+ "add " INIT_SUM_R ", " INIT_SUM_R ", " STRIDE_R NL
+ "cmp " INIT_SUM_R ", " SOURCE_END_R NL
+ "bcc .alphaChannelSecondInitSum" NL
+".alphaChannelSecondInitSumDone:" NL
+
+ // Blurring.
+ "add " SOURCE_END_R ", " SOURCE_R ", " STRIDE_WIDTH_R NL
+ "add " DESTINATION_END_R ", " DESTINATION_R ", " STRIDE_WIDTH_R NL
+ "sub " LEFT_R ", " SOURCE_R ", " DISTANCE_LEFT_R NL
+ "add " RIGHT_R ", " SOURCE_R ", " DISTANCE_RIGHT_R NL
+
+".alphaChannelSecondBlur:" NL
+ "vcvt.f32.u32 " PIXEL_Q ", " SUM_Q NL
+ "vmul.f32 " PIXEL_Q ", " PIXEL_Q ", " INVERTED_KERNEL_SIZE_Q NL
+ "vcvt.u32.f32 " PIXEL_Q ", " PIXEL_Q NL
+ "vshl.u32 " PIXEL_Q ", " PIXEL_Q ", #24" NL
+ CONDITIONAL_DATA_TRANSFER4("vst1.u32", "vstr", DESTINATION_R)
+
+ "cmp " LEFT_R ", " SOURCE_R NL
+ "bcc .alphaChannelSecondSkipLeft" NL
+ CONDITIONAL_DATA_TRANSFER4("vld1.u32", "vldr", LEFT_R)
+ "vshr.u32 " PIXEL_Q ", " PIXEL_Q ", #24" NL
+ "vsub.u32 " SUM_Q ", " SUM_Q ", " PIXEL_Q NL
+".alphaChannelSecondSkipLeft: " NL
+
+ "cmp " RIGHT_R ", " SOURCE_END_R NL
+ "bcs .alphaChannelSecondSkipRight" NL
+ CONDITIONAL_DATA_TRANSFER4("vld1.u32", "vldr", RIGHT_R)
+ "vshr.u32 " PIXEL_Q ", " PIXEL_Q ", #24" NL
+ "vadd.u32 " SUM_Q ", " SUM_Q ", " PIXEL_Q NL
+".alphaChannelSecondSkipRight: " NL
+
+ "add " DESTINATION_R ", " DESTINATION_R ", " STRIDE_R NL
+ "add " LEFT_R ", " LEFT_R ", " STRIDE_R NL
+ "add " RIGHT_R ", " RIGHT_R ", " STRIDE_R NL
+ "cmp " DESTINATION_R ", " DESTINATION_END_R NL
+ "bcc .alphaChannelSecondBlur" NL
+
+ "ldmia sp!, {r4-r8, r10, r11, pc}" NL
+); // NOLINT
+
+} // namespace WebCore
+
+#endif // CPU(ARM_NEON) && COMPILER(GCC)
diff --git a/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h b/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h
new file mode 100644
index 000000000..96037aab9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 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 FEGaussianBlurNEON_h
+#define FEGaussianBlurNEON_h
+
+#include <wtf/Platform.h>
+
+#if CPU(ARM_NEON) && COMPILER(GCC)
+
+#include "FEGaussianBlur.h"
+
+namespace WebCore {
+
+struct FEGaussianBlurPaintingDataForNeon {
+ int stride;
+ int strideWidth;
+ int strideLine;
+ int strideLineWidth;
+ int remainingStrides;
+ int distanceLeft;
+ int distanceRight;
+ float invertedKernelSize;
+ unsigned char* paintingConstants;
+};
+
+unsigned char* feGaussianBlurConstantsForNeon();
+
+extern "C" {
+void neonDrawAllChannelGaussianBlur(unsigned char* source, unsigned char* destination, FEGaussianBlurPaintingDataForNeon*);
+void neonDrawAlphaChannelGaussianBlur(unsigned char* source, unsigned char* destination, FEGaussianBlurPaintingDataForNeon*);
+}
+
+inline void FEGaussianBlur::platformApplyNeon(ByteArray* srcPixelArray, ByteArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize)
+{
+ const int widthMultipliedByFour = 4 * paintSize.width();
+ FEGaussianBlurPaintingDataForNeon argumentsX = {
+ 4,
+ widthMultipliedByFour,
+ widthMultipliedByFour,
+ (isAlphaImage() ? ((paintSize.height() >> 2) << 2) : paintSize.height()) * widthMultipliedByFour,
+ isAlphaImage() ? (paintSize.height() & 0x3) : 0,
+ 0,
+ 0,
+ 0,
+ isAlphaImage() ? 0 : feGaussianBlurConstantsForNeon()
+ };
+ FEGaussianBlurPaintingDataForNeon argumentsY = {
+ widthMultipliedByFour,
+ widthMultipliedByFour * paintSize.height(),
+ 4,
+ (isAlphaImage() ? ((paintSize.width() >> 2) << 2) : paintSize.width()) * 4,
+ isAlphaImage() ? (paintSize.width() & 0x3) : 0,
+ 0,
+ 0,
+ 0,
+ isAlphaImage() ? 0 : feGaussianBlurConstantsForNeon()
+ };
+
+ for (int i = 0; i < 3; ++i) {
+ if (kernelSizeX) {
+ kernelPosition(i, kernelSizeX, argumentsX.distanceLeft, argumentsX.distanceRight);
+ argumentsX.invertedKernelSize = 1 / static_cast<float>(kernelSizeX);
+ if (isAlphaImage())
+ neonDrawAlphaChannelGaussianBlur(srcPixelArray->data(), tmpPixelArray->data(), &argumentsX);
+ else
+ neonDrawAllChannelGaussianBlur(srcPixelArray->data(), tmpPixelArray->data(), &argumentsX);
+ } else {
+ ByteArray* auxPixelArray = tmpPixelArray;
+ tmpPixelArray = srcPixelArray;
+ srcPixelArray = auxPixelArray;
+ }
+
+ if (kernelSizeY) {
+ kernelPosition(i, kernelSizeY, argumentsY.distanceLeft, argumentsY.distanceRight);
+ argumentsY.invertedKernelSize = 1 / static_cast<float>(kernelSizeY);
+ if (isAlphaImage())
+ neonDrawAlphaChannelGaussianBlur(tmpPixelArray->data(), srcPixelArray->data(), &argumentsY);
+ else
+ neonDrawAllChannelGaussianBlur(tmpPixelArray->data(), srcPixelArray->data(), &argumentsY);
+ } else {
+ ByteArray* auxPixelArray = tmpPixelArray;
+ tmpPixelArray = srcPixelArray;
+ srcPixelArray = auxPixelArray;
+ }
+ }
+}
+
+} // namespace WebCore
+
+#endif // CPU(ARM_NEON) && COMPILER(GCC)
+
+#endif // FEGaussianBlurNEON_h
diff --git a/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.cpp b/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.cpp
new file mode 100644
index 000000000..110b528c4
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.cpp
@@ -0,0 +1,504 @@
+/*
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 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"
+#include "FELightingNEON.h"
+
+#if CPU(ARM_NEON) && COMPILER(GCC)
+
+#include <wtf/Alignment.h>
+
+namespace WebCore {
+
+// These constants are copied to the following SIMD registers:
+// ALPHAX_Q ALPHAY_Q REMAPX_D REMAPY_D
+
+static WTF_ALIGNED(short, s_FELightingConstantsForNeon[], 16) = {
+ // Alpha coefficients.
+ -2, 1, 0, -1, 2, 1, 0, -1,
+ 0, -1, -2, -1, 0, 1, 2, 1,
+ // Remapping indicies.
+ 0x0f0e, 0x0302, 0x0504, 0x0706,
+ 0x0b0a, 0x1312, 0x1514, 0x1716,
+};
+
+short* feLightingConstantsForNeon()
+{
+ return s_FELightingConstantsForNeon;
+}
+
+void FELighting::platformApplyNeonWorker(FELightingPaintingDataForNeon* parameters)
+{
+ neonDrawLighting(parameters);
+}
+
+#define ASSTRING(str) #str
+#define TOSTRING(value) ASSTRING(value)
+
+#define PIXELS_OFFSET TOSTRING(0)
+#define YSTART_OFFSET TOSTRING(4)
+#define WIDTH_OFFSET TOSTRING(8)
+#define HEIGHT_OFFSET TOSTRING(12)
+#define FLAGS_OFFSET TOSTRING(16)
+#define SPECULAR_EXPONENT_OFFSET TOSTRING(20)
+#define CONE_EXPONENT_OFFSET TOSTRING(24)
+#define FLOAT_ARGUMENTS_OFFSET TOSTRING(28)
+#define PAINTING_CONSTANTS_OFFSET TOSTRING(32)
+#define NL "\n"
+
+// Register allocation
+#define PAINTING_DATA_R "r11"
+#define RESET_WIDTH_R PAINTING_DATA_R
+#define PIXELS_R "r4"
+#define WIDTH_R "r5"
+#define HEIGHT_R "r6"
+#define FLAGS_R "r7"
+#define SPECULAR_EXPONENT_R "r8"
+#define CONE_EXPONENT_R "r10"
+#define SCANLINE_R "r12"
+
+#define TMP1_Q "q0"
+#define TMP1_D0 "d0"
+#define TMP1_S0 "s0"
+#define TMP1_S1 "s1"
+#define TMP1_D1 "d1"
+#define TMP1_S2 "s2"
+#define TMP1_S3 "s3"
+#define TMP2_Q "q1"
+#define TMP2_D0 "d2"
+#define TMP2_S0 "s4"
+#define TMP2_S1 "s5"
+#define TMP2_D1 "d3"
+#define TMP2_S2 "s6"
+#define TMP2_S3 "s7"
+#define TMP3_Q "q2"
+#define TMP3_D0 "d4"
+#define TMP3_S0 "s8"
+#define TMP3_S1 "s9"
+#define TMP3_D1 "d5"
+#define TMP3_S2 "s10"
+#define TMP3_S3 "s11"
+
+#define COSINE_OF_ANGLE "s12"
+#define POWF_INT_S "s13"
+#define POWF_FRAC_S "s14"
+#define SPOT_COLOR_Q "q4"
+
+// Because of VMIN and VMAX CONST_ZERO_S and CONST_ONE_S
+// must be placed on the same side of the double vector
+
+// Current pixel position
+#define POSITION_Q "q5"
+#define POSITION_X_S "s20"
+#define POSITION_Y_S "s21"
+#define POSITION_Z_S "s22"
+#define CONST_ZERO_HI_D "d11"
+#define CONST_ZERO_S "s23"
+
+// -------------------------------
+// Variable arguments
+// Misc arguments
+#define READ1_RANGE "d12-d15"
+#define READ2_RANGE "d16-d19"
+#define READ3_RANGE "d20-d21"
+
+#define SCALE_S "s24"
+#define SCALE_DIV4_S "s25"
+#define DIFFUSE_CONST_S "s26"
+
+// Light source position
+#define CONE_CUT_OFF_S "s28"
+#define CONE_FULL_LIGHT_S "s29"
+#define CONE_CUT_OFF_RANGE_S "s30"
+#define CONST_ONE_HI_D "d15"
+#define CONST_ONE_S "s31"
+
+#define LIGHT_Q "q8"
+#define DIRECTION_Q "q9"
+#define COLOR_Q "q10"
+// -------------------------------
+// Constant coefficients
+#define READ4_RANGE "d22-d25"
+#define READ5_RANGE "d26-d27"
+
+#define ALPHAX_Q "q11"
+#define ALPHAY_Q "q12"
+#define REMAPX_D "d26"
+#define REMAPY_D "d27"
+// -------------------------------
+
+#define ALL_ROWS_D "{d28,d29,d30}"
+#define TOP_ROW_D "d28"
+#define MIDDLE_ROW_D "d29"
+#define BOTTOM_ROW_D "d30"
+
+#define GET_LENGTH(source, temp) \
+ "vmul.f32 " temp##_Q ", " source##_Q ", " source##_Q NL \
+ "vadd.f32 " source##_S3 ", " temp##_S0 ", " temp##_S1 NL \
+ "vadd.f32 " source##_S3 ", " source##_S3 ", " temp##_S2 NL \
+ "vsqrt.f32 " source##_S3 ", " source##_S3 NL
+
+// destination##_S3 can contain the multiply of length.
+#define DOT_PRODUCT(destination, source1, source2) \
+ "vmul.f32 " destination##_Q ", " source1##_Q ", " source2##_Q NL \
+ "vadd.f32 " destination##_S0 ", " destination##_S0 ", " destination##_S1 NL \
+ "vadd.f32 " destination##_S0 ", " destination##_S0 ", " destination##_S2 NL
+
+#define MULTIPLY_BY_DIFFUSE_CONST(normalVectorLength, dotProductLength) \
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_DIFFUSE_CONST_IS_1) NL \
+ "vmuleq.f32 " TMP2_S1 ", " DIFFUSE_CONST_S ", " normalVectorLength NL \
+ "vdiveq.f32 " TMP2_S1 ", " TMP2_S1 ", " dotProductLength NL \
+ "vdivne.f32 " TMP2_S1 ", " normalVectorLength ", " dotProductLength NL
+
+#define POWF_SQR(value, exponent, current, remaining) \
+ "tst " exponent ", #" ASSTRING(current) NL \
+ "vmulne.f32 " value ", " value ", " POWF_INT_S NL \
+ "tst " exponent ", #" ASSTRING(remaining) NL \
+ "vmulne.f32 " POWF_INT_S ", " POWF_INT_S ", " POWF_INT_S NL
+
+#define POWF_SQRT(value, exponent, current, remaining) \
+ "tst " exponent ", #" ASSTRING(remaining) NL \
+ "vsqrtne.f32 " POWF_FRAC_S ", " POWF_FRAC_S NL \
+ "tst " exponent ", #" ASSTRING(current) NL \
+ "vmulne.f32 " value ", " value ", " POWF_FRAC_S NL
+
+// This simplified powf function is sufficiently accurate.
+#define POWF(value, exponent) \
+ "tst " exponent ", #0xfc0" NL \
+ "vmovne.f32 " POWF_INT_S ", " value NL \
+ "tst " exponent ", #0x03f" NL \
+ "vmovne.f32 " POWF_FRAC_S ", " value NL \
+ "vmov.f32 " value ", " CONST_ONE_S NL \
+ \
+ POWF_SQR(value, exponent, 0x040, 0xf80) \
+ POWF_SQR(value, exponent, 0x080, 0xf00) \
+ POWF_SQR(value, exponent, 0x100, 0xe00) \
+ POWF_SQR(value, exponent, 0x200, 0xc00) \
+ POWF_SQR(value, exponent, 0x400, 0x800) \
+ "tst " exponent ", #0x800" NL \
+ "vmulne.f32 " value ", " value ", " POWF_INT_S NL \
+ \
+ POWF_SQRT(value, exponent, 0x20, 0x3f) \
+ POWF_SQRT(value, exponent, 0x10, 0x1f) \
+ POWF_SQRT(value, exponent, 0x08, 0x0f) \
+ POWF_SQRT(value, exponent, 0x04, 0x07) \
+ POWF_SQRT(value, exponent, 0x02, 0x03) \
+ POWF_SQRT(value, exponent, 0x01, 0x01)
+
+// The following algorithm is an ARM-NEON optimized version of
+// the main loop found in FELighting.cpp. Since the whole code
+// is redesigned to be as effective as possible (ARM specific
+// thinking), it is four times faster than its C++ counterpart.
+
+asm ( // NOLINT
+".globl " TOSTRING(neonDrawLighting) NL
+TOSTRING(neonDrawLighting) ":" NL
+ // Because of the clever register allocation, nothing is stored on the stack
+ // except the saved registers.
+ // Stack must be aligned to 8 bytes.
+ "stmdb sp!, {r4-r8, r10, r11, lr}" NL
+ "vstmdb sp!, {d8-d15}" NL
+ "mov " PAINTING_DATA_R ", r0" NL
+
+ // The following two arguments are loaded to SIMD registers.
+ "ldr r0, [" PAINTING_DATA_R ", #" FLOAT_ARGUMENTS_OFFSET "]" NL
+ "ldr r1, [" PAINTING_DATA_R ", #" PAINTING_CONSTANTS_OFFSET "]" NL
+ "ldr " PIXELS_R ", [" PAINTING_DATA_R ", #" PIXELS_OFFSET "]" NL
+ "vldr.f32 " POSITION_Y_S ", [" PAINTING_DATA_R ", #" YSTART_OFFSET "]" NL
+ "ldr " WIDTH_R ", [" PAINTING_DATA_R ", #" WIDTH_OFFSET "]" NL
+ "ldr " HEIGHT_R ", [" PAINTING_DATA_R ", #" HEIGHT_OFFSET "]" NL
+ "ldr " FLAGS_R ", [" PAINTING_DATA_R ", #" FLAGS_OFFSET "]" NL
+ "ldr " SPECULAR_EXPONENT_R ", [" PAINTING_DATA_R ", #" SPECULAR_EXPONENT_OFFSET "]" NL
+ "ldr " CONE_EXPONENT_R ", [" PAINTING_DATA_R ", #" CONE_EXPONENT_OFFSET "]" NL
+
+ // Load all data to the SIMD registers with the least number of instructions.
+ "vld1.f32 { " READ1_RANGE " }, [r0]!" NL
+ "vld1.f32 { " READ2_RANGE " }, [r0]!" NL
+ "vld1.f32 { " READ3_RANGE " }, [r0]!" NL
+ "vld1.s16 {" READ4_RANGE "}, [r1]!" NL
+ "vld1.s16 {" READ5_RANGE "}, [r1]!" NL
+
+ // Initializing local variables.
+ "mov " SCANLINE_R ", " WIDTH_R ", lsl #2" NL
+ "add " SCANLINE_R ", " SCANLINE_R ", #8" NL
+ "add " PIXELS_R ", " PIXELS_R ", " SCANLINE_R NL
+ "add " PIXELS_R ", " PIXELS_R ", #3" NL
+ "mov r0, #0" NL
+ "vmov.f32 " CONST_ZERO_S ", r0" NL
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_SPOT_LIGHT) NL
+ "vmov.f32 " SPOT_COLOR_Q ", " COLOR_Q NL
+ "mov " RESET_WIDTH_R ", " WIDTH_R NL
+
+".mainLoop:" NL
+ "mov r3, #3" NL
+ "vmov.f32 " POSITION_X_S ", " CONST_ONE_S NL
+
+".scanline:" NL
+ // The ROW registers are storing the alpha channel of the last three pixels.
+ // The alpha channel is stored as signed short (sint16) values. The fourth value
+ // is garbage. The following instructions are shifting out the unnecessary alpha
+ // values and load the next ones.
+ "ldrb r0, [" PIXELS_R ", -" SCANLINE_R "]" NL
+ "ldrb r1, [" PIXELS_R ", +" SCANLINE_R "]" NL
+ "ldrb r2, [" PIXELS_R "], #4" NL
+ "vext.s16 " TOP_ROW_D ", " TOP_ROW_D ", " TOP_ROW_D ", #3" NL
+ "vext.s16 " MIDDLE_ROW_D ", " MIDDLE_ROW_D ", " MIDDLE_ROW_D ", #3" NL
+ "vext.s16 " BOTTOM_ROW_D ", " BOTTOM_ROW_D ", " BOTTOM_ROW_D ", #3" NL
+ "vmov.s16 " TOP_ROW_D "[1], r0" NL
+ "vmov.s16 " MIDDLE_ROW_D "[1], r2" NL
+ "vmov.s16 " BOTTOM_ROW_D "[1], r1" NL
+
+ // The two border pixels (rightmost and leftmost) are skipped when
+ // the next scanline is reached. It also jumps, when the algorithm
+ // is started, and the first free alpha values are loaded to each row.
+ "subs r3, r3, #1" NL
+ "bne .scanline" NL
+
+ // The light vector goes to TMP1_Q. It is constant in case of distant light.
+ // The fourth value contains the length of the light vector.
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_POINT_LIGHT | FLAG_SPOT_LIGHT) NL
+ "beq .distantLight" NL
+
+ "vmov.s16 r3, " MIDDLE_ROW_D "[2]" NL
+ "vmov.f32 " POSITION_Z_S ", r3" NL
+ "vcvt.f32.s32 " POSITION_Z_S ", " POSITION_Z_S NL
+ "vmul.f32 " POSITION_Z_S ", " POSITION_Z_S ", " SCALE_S NL
+
+ "vsub.f32 " TMP1_Q ", " LIGHT_Q ", " POSITION_Q NL
+ GET_LENGTH(TMP1, TMP2)
+
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_SPOT_LIGHT) NL
+ "bne .cosineOfAngle" NL
+".visiblePixel:" NL
+
+ // | -1 0 1 | | -1 -2 -1 |
+ // X = | -2 0 2 | Y = | 0 0 0 |
+ // | -1 0 1 | | 1 2 1 |
+
+ // Multiply the alpha values by the X and Y matrices.
+
+ // Moving the 8 alpha value to TMP3.
+ "vtbl.8 " TMP3_D0 ", " ALL_ROWS_D ", " REMAPX_D NL
+ "vtbl.8 " TMP3_D1 ", " ALL_ROWS_D ", " REMAPY_D NL
+
+ "vmul.s16 " TMP2_Q ", " TMP3_Q ", " ALPHAX_Q NL
+ "vpadd.s16 " TMP2_D0 ", " TMP2_D0 ", " TMP2_D1 NL
+ "vpadd.s16 " TMP2_D0 ", " TMP2_D0 ", " TMP2_D0 NL
+ "vpadd.s16 " TMP2_D0 ", " TMP2_D0 ", " TMP2_D0 NL
+ "vmov.s16 r0, " TMP2_D0 "[0]" NL
+
+ "vmul.s16 " TMP2_Q ", " TMP3_Q ", " ALPHAY_Q NL
+ "vpadd.s16 " TMP2_D0 ", " TMP2_D0 ", " TMP2_D1 NL
+ "vpadd.s16 " TMP2_D0 ", " TMP2_D0 ", " TMP2_D0 NL
+ "vpadd.s16 " TMP2_D0 ", " TMP2_D0 ", " TMP2_D0 NL
+ "vmov.s16 r1, " TMP2_D0 "[0]" NL
+
+ // r0 and r1 contains the X and Y coordinates of the
+ // normal vector, respectively.
+
+ // Calculating the spot light strength.
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_SPOT_LIGHT) NL
+ "beq .endLight" NL
+
+ "vneg.f32 " TMP3_S1 ", " COSINE_OF_ANGLE NL
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_CONE_EXPONENT_IS_1) NL
+ "beq .coneExpPowf" NL
+".coneExpPowfFinished:" NL
+
+ // Smoothing the cone edge if necessary.
+ "vcmp.f32 " COSINE_OF_ANGLE ", " CONE_FULL_LIGHT_S NL
+ "fmstat" NL
+ "bhi .cutOff" NL
+".cutOffFinished:" NL
+
+ "vmin.f32 " TMP3_D0 ", " TMP3_D0 ", " CONST_ONE_HI_D NL
+ "vmul.f32 " COLOR_Q ", " SPOT_COLOR_Q ", " TMP3_D0 "[1]" NL
+
+".endLight:" NL
+ // Summarize:
+ // r0 and r1 contains the normalVector.
+ // TMP1_Q contains the light vector and its length.
+ // COLOR_Q contains the color of the light vector.
+
+ // Test whether both r0 and r1 are zero (Normal vector is (0, 0, 1)).
+ "orrs r2, r0, r1" NL
+ "bne .normalVectorIsNonZero" NL
+
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_SPECULAR_LIGHT) NL
+ "bne .specularLight1" NL
+
+ // Calculate diffuse light strength.
+ MULTIPLY_BY_DIFFUSE_CONST(TMP1_S2, TMP1_S3)
+ "b .lightStrengthCalculated" NL
+
+".specularLight1:" NL
+ // Calculating specular light strength.
+ "vadd.f32 " TMP1_S2 ", " TMP1_S2 ", " TMP1_S3 NL
+ GET_LENGTH(TMP1, TMP2)
+
+ // When the exponent is 1, we don't need to call an expensive powf function.
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_SPECULAR_EXPONENT_IS_1) NL
+ "vdiveq.f32 " TMP2_S1 ", " TMP1_S2 ", " TMP1_S3 NL
+ "beq .specularExpPowf" NL
+
+ MULTIPLY_BY_DIFFUSE_CONST(TMP1_S2, TMP1_S3)
+ "b .lightStrengthCalculated" NL
+
+".normalVectorIsNonZero:" NL
+ // Normal vector goes to TMP2, and its length is calculated as well.
+ "vmov.s32 " TMP2_S0 ", r0" NL
+ "vcvt.f32.s32 " TMP2_S0 ", " TMP2_S0 NL
+ "vmul.f32 " TMP2_S0 ", " TMP2_S0 ", " SCALE_DIV4_S NL
+ "vmov.s32 " TMP2_S1 ", r1" NL
+ "vcvt.f32.s32 " TMP2_S1 ", " TMP2_S1 NL
+ "vmul.f32 " TMP2_S1 ", " TMP2_S1 ", " SCALE_DIV4_S NL
+ "vmov.f32 " TMP2_S2 ", " CONST_ONE_S NL
+ GET_LENGTH(TMP2, TMP3)
+
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_SPECULAR_LIGHT) NL
+ "bne .specularLight2" NL
+
+ // Calculating diffuse light strength.
+ DOT_PRODUCT(TMP3, TMP2, TMP1)
+ MULTIPLY_BY_DIFFUSE_CONST(TMP3_S0, TMP3_S3)
+ "b .lightStrengthCalculated" NL
+
+".specularLight2:" NL
+ // Calculating specular light strength.
+ "vadd.f32 " TMP1_S2 ", " TMP1_S2 ", " TMP1_S3 NL
+ GET_LENGTH(TMP1, TMP3)
+ DOT_PRODUCT(TMP3, TMP2, TMP1)
+
+ // When the exponent is 1, we don't need to call an expensive powf function.
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_SPECULAR_EXPONENT_IS_1) NL
+ "vdiveq.f32 " TMP2_S1 ", " TMP3_S0 ", " TMP3_S3 NL
+ "beq .specularExpPowf" NL
+ MULTIPLY_BY_DIFFUSE_CONST(TMP3_S0, TMP3_S3)
+
+".lightStrengthCalculated:" NL
+ // TMP2_S1 contains the light strength. Clamp it to [0, 1]
+ "vmax.f32 " TMP2_D0 ", " TMP2_D0 ", " CONST_ZERO_HI_D NL
+ "vmin.f32 " TMP2_D0 ", " TMP2_D0 ", " CONST_ONE_HI_D NL
+ "vmul.f32 " TMP3_Q ", " COLOR_Q ", " TMP2_D0 "[1]" NL
+ "vcvt.u32.f32 " TMP3_Q ", " TMP3_Q NL
+ "vmov.u32 r2, r3, " TMP3_S0 ", " TMP3_S1 NL
+ // The color values are stored in-place.
+ "strb r2, [" PIXELS_R ", #-11]" NL
+ "strb r3, [" PIXELS_R ", #-10]" NL
+ "vmov.u32 r2, " TMP3_S2 NL
+ "strb r2, [" PIXELS_R ", #-9]" NL
+
+ // Continue to the next pixel.
+".blackPixel:" NL
+ "vadd.f32 " POSITION_X_S ", " CONST_ONE_S NL
+ "mov r3, #1" NL
+ "subs " WIDTH_R ", " WIDTH_R ", #1" NL
+ "bne .scanline" NL
+
+ // If the end of the scanline is reached, we continue
+ // to the next scanline.
+ "vadd.f32 " POSITION_Y_S ", " CONST_ONE_S NL
+ "mov " WIDTH_R ", " RESET_WIDTH_R NL
+ "subs " HEIGHT_R ", " HEIGHT_R ", #1" NL
+ "bne .mainLoop" NL
+
+ // Return.
+ "vldmia sp!, {d8-d15}" NL
+ "ldmia sp!, {r4-r8, r10, r11, pc}" NL
+
+".distantLight:" NL
+ // In case of distant light, the light vector is constant,
+ // we simply copy it.
+ "vmov.f32 " TMP1_Q ", " LIGHT_Q NL
+ "b .visiblePixel" NL
+
+".cosineOfAngle:" NL
+ // If the pixel is outside of the cone angle, it is simply a black pixel.
+ DOT_PRODUCT(TMP3, TMP1, DIRECTION)
+ "vdiv.f32 " COSINE_OF_ANGLE ", " TMP3_S0 ", " TMP1_S3 NL
+ "vcmp.f32 " COSINE_OF_ANGLE ", " CONE_CUT_OFF_S NL
+ "fmstat" NL
+ "bls .visiblePixel" NL
+ "mov r0, #0" NL
+ "strh r0, [" PIXELS_R ", #-11]" NL
+ "strb r0, [" PIXELS_R ", #-9]" NL
+ "b .blackPixel" NL
+
+".cutOff:" NL
+ // Smoothing the light strength on the cone edge.
+ "vsub.f32 " TMP3_S0 ", " CONE_CUT_OFF_S ", " COSINE_OF_ANGLE NL
+ "vdiv.f32 " TMP3_S0 ", " TMP3_S0 ", " CONE_CUT_OFF_RANGE_S NL
+ "vmul.f32 " TMP3_S1 ", " TMP3_S1 ", " TMP3_S0 NL
+ "b .cutOffFinished" NL
+
+".coneExpPowf:" NL
+ POWF(TMP3_S1, CONE_EXPONENT_R)
+ "b .coneExpPowfFinished" NL
+
+".specularExpPowf:" NL
+ POWF(TMP2_S1, SPECULAR_EXPONENT_R)
+ "tst " FLAGS_R ", #" TOSTRING(FLAG_DIFFUSE_CONST_IS_1) NL
+ "vmuleq.f32 " TMP2_S1 ", " TMP2_S1 ", " DIFFUSE_CONST_S NL
+ "b .lightStrengthCalculated" NL
+); // NOLINT
+
+int FELighting::getPowerCoefficients(float exponent)
+{
+ // Calling a powf function from the assembly code would require to save
+ // and reload a lot of NEON registers. Since the base is in range [0..1]
+ // and only 8 bit precision is required, we use our own powf function.
+ // This is probably not the best, but it uses only a few registers and
+ // gives us enough precision (modifying the exponent field directly would
+ // also be possible).
+
+ // First, we limit the exponent to maximum of 64, which gives us enough
+ // precision. We split the exponent to an integer and fraction part,
+ // since a^x = (a^y)*(a^z) where x = y+z. The integer exponent of the
+ // power is estimated by square, and the fraction exponent of the power
+ // is estimated by square root assembly instructions.
+ int i, result;
+
+ if (exponent < 0)
+ exponent = 1 / (-exponent);
+
+ if (exponent > 63.99)
+ exponent = 63.99;
+
+ exponent /= 64;
+ result = 0;
+ for (i = 11; i >= 0; --i) {
+ exponent *= 2;
+ if (exponent >= 1) {
+ result |= 1 << i;
+ exponent -= 1;
+ }
+ }
+ return result;
+}
+
+} // namespace WebCore
+
+#endif // CPU(ARM_NEON) && COMPILER(GCC)
diff --git a/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.h b/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.h
new file mode 100644
index 000000000..9094153d7
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 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 FELightingNeon_h
+#define FELightingNeon_h
+
+#include <wtf/Platform.h>
+
+#if CPU(ARM_NEON) && COMPILER(GCC)
+
+#include "FELighting.h"
+#include <wtf/Alignment.h>
+#include <wtf/ParallelJobs.h>
+
+namespace WebCore {
+
+// Otherwise: Distant Light.
+#define FLAG_POINT_LIGHT 0x01
+#define FLAG_SPOT_LIGHT 0x02
+#define FLAG_CONE_EXPONENT_IS_1 0x04
+
+// Otherwise: Diffuse light.
+#define FLAG_SPECULAR_LIGHT 0x10
+#define FLAG_DIFFUSE_CONST_IS_1 0x20
+#define FLAG_SPECULAR_EXPONENT_IS_1 0x40
+
+// Must be aligned to 16 bytes.
+struct FELightingFloatArgumentsForNeon {
+ float surfaceScale;
+ float minusSurfaceScaleDividedByFour;
+ float diffuseConstant;
+ float padding1;
+
+ float coneCutOffLimit;
+ float coneFullLight;
+ float coneCutOffRange;
+ float constOne;
+
+ float lightX;
+ float lightY;
+ float lightZ;
+ float padding2;
+
+ float directionX;
+ float directionY;
+ float directionZ;
+ float padding3;
+
+ float colorRed;
+ float colorGreen;
+ float colorBlue;
+ float padding4;
+};
+
+struct FELightingPaintingDataForNeon {
+ unsigned char* pixels;
+ float yStart;
+ int widthDecreasedByTwo;
+ int absoluteHeight;
+ // Combination of FLAG constants above.
+ int flags;
+ int specularExponent;
+ int coneExponent;
+ FELightingFloatArgumentsForNeon* floatArguments;
+ short* paintingConstants;
+};
+
+short* feLightingConstantsForNeon();
+
+extern "C" {
+void neonDrawLighting(FELightingPaintingDataForNeon*);
+}
+
+inline void FELighting::platformApplyNeon(LightingData& data, LightSource::PaintingData& paintingData)
+{
+ WTF_ALIGNED(FELightingFloatArgumentsForNeon, floatArguments, 16);
+
+ FELightingPaintingDataForNeon neonData = {
+ data.pixels->data(),
+ 1,
+ data.widthDecreasedByOne - 1,
+ data.heightDecreasedByOne - 1,
+ 0,
+ 0,
+ 0,
+ &floatArguments,
+ feLightingConstantsForNeon()
+ };
+
+ // Set light source arguments.
+ floatArguments.constOne = 1;
+
+ floatArguments.colorRed = m_lightingColor.red();
+ floatArguments.colorGreen = m_lightingColor.green();
+ floatArguments.colorBlue = m_lightingColor.blue();
+ floatArguments.padding4 = 0;
+
+ if (m_lightSource->type() == LS_POINT) {
+ neonData.flags |= FLAG_POINT_LIGHT;
+ PointLightSource* pointLightSource = static_cast<PointLightSource*>(m_lightSource.get());
+ floatArguments.lightX = pointLightSource->position().x();
+ floatArguments.lightY = pointLightSource->position().y();
+ floatArguments.lightZ = pointLightSource->position().z();
+ floatArguments.padding2 = 0;
+ } else if (m_lightSource->type() == LS_SPOT) {
+ neonData.flags |= FLAG_SPOT_LIGHT;
+ SpotLightSource* spotLightSource = static_cast<SpotLightSource*>(m_lightSource.get());
+ floatArguments.lightX = spotLightSource->position().x();
+ floatArguments.lightY = spotLightSource->position().y();
+ floatArguments.lightZ = spotLightSource->position().z();
+ floatArguments.padding2 = 0;
+
+ floatArguments.directionX = paintingData.directionVector.x();
+ floatArguments.directionY = paintingData.directionVector.y();
+ floatArguments.directionZ = paintingData.directionVector.z();
+ floatArguments.padding3 = 0;
+
+ floatArguments.coneCutOffLimit = paintingData.coneCutOffLimit;
+ floatArguments.coneFullLight = paintingData.coneFullLight;
+ floatArguments.coneCutOffRange = paintingData.coneCutOffLimit - paintingData.coneFullLight;
+ neonData.coneExponent = getPowerCoefficients(spotLightSource->specularExponent());
+ if (spotLightSource->specularExponent() == 1)
+ neonData.flags |= FLAG_CONE_EXPONENT_IS_1;
+ } else {
+ ASSERT(m_lightSource->type() == LS_DISTANT);
+ floatArguments.lightX = paintingData.lightVector.x();
+ floatArguments.lightY = paintingData.lightVector.y();
+ floatArguments.lightZ = paintingData.lightVector.z();
+ floatArguments.padding2 = 1;
+ }
+
+ // Set lighting arguments.
+ floatArguments.surfaceScale = data.surfaceScale;
+ floatArguments.minusSurfaceScaleDividedByFour = -data.surfaceScale / 4;
+ if (m_lightingType == FELighting::DiffuseLighting)
+ floatArguments.diffuseConstant = m_diffuseConstant;
+ else {
+ neonData.flags |= FLAG_SPECULAR_LIGHT;
+ floatArguments.diffuseConstant = m_specularConstant;
+ neonData.specularExponent = getPowerCoefficients(m_specularExponent);
+ if (m_specularExponent == 1)
+ neonData.flags |= FLAG_SPECULAR_EXPONENT_IS_1;
+ }
+ if (floatArguments.diffuseConstant == 1)
+ neonData.flags |= FLAG_DIFFUSE_CONST_IS_1;
+
+ int optimalThreadNumber = ((data.widthDecreasedByOne - 1) * (data.heightDecreasedByOne - 1)) / s_minimalRectDimension;
+ if (optimalThreadNumber > 1) {
+ // Initialize parallel jobs
+ ParallelJobs<FELightingPaintingDataForNeon> parallelJobs(&WebCore::FELighting::platformApplyNeonWorker, optimalThreadNumber);
+
+ // Fill the parameter array
+ int job = parallelJobs.numberOfJobs();
+ if (job > 1) {
+ int yStart = 1;
+ int yStep = (data.heightDecreasedByOne - 1) / job;
+ for (--job; job >= 0; --job) {
+ FELightingPaintingDataForNeon& params = parallelJobs.parameter(job);
+ params = neonData;
+ params.yStart = yStart;
+ params.pixels += (yStart - 1) * (data.widthDecreasedByOne + 1) * 4;
+ if (job > 0) {
+ params.absoluteHeight = yStep;
+ yStart += yStep;
+ } else
+ params.absoluteHeight = data.heightDecreasedByOne - yStart;
+ }
+ parallelJobs.execute();
+ return;
+ }
+ }
+
+ neonDrawLighting(&neonData);
+}
+
+} // namespace WebCore
+
+#endif // CPU(ARM_NEON) && COMPILER(GCC)
+
+#endif // FELightingNeon_h
diff --git a/Source/WebCore/platform/graphics/filters/skia/FEGaussianBlurSkia.cpp b/Source/WebCore/platform/graphics/filters/skia/FEGaussianBlurSkia.cpp
new file mode 100644
index 000000000..ceb1146c7
--- /dev/null
+++ b/Source/WebCore/platform/graphics/filters/skia/FEGaussianBlurSkia.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS 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 USE(SKIA)
+#include "FEGaussianBlur.h"
+
+#include "BitmapImageSingleFrameSkia.h"
+#include "SkBlurImageFilter.h"
+
+namespace WebCore {
+
+void FEGaussianBlur::platformApplySkia()
+{
+ ImageBuffer* resultImage = createImageBufferResult();
+ if (!resultImage)
+ return;
+
+ FilterEffect* in = inputEffect(0);
+
+ IntRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());
+
+ setIsAlphaImage(in->isAlphaImage());
+
+ float stdX = filter()->applyHorizontalScale(m_stdX);
+ float stdY = filter()->applyVerticalScale(m_stdY);
+
+ RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore);
+
+ SkPaint paint;
+ GraphicsContext* dstContext = resultImage->context();
+ SkCanvas* canvas = dstContext->platformContext()->canvas();
+ paint.setImageFilter(new SkBlurImageFilter(stdX, stdY))->unref();
+ canvas->saveLayer(0, &paint);
+ paint.setColor(0xFFFFFFFF);
+ dstContext->drawImage(image.get(), ColorSpaceDeviceRGB, drawingRegion.location(), CompositeCopy);
+ canvas->restore();
+ return;
+}
+
+};
+#endif