summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/filters
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2009-10-08 17:19:54 +0100
committerSteve Block <steveblock@google.com>2009-10-20 00:41:58 +0100
commit231d4e3152a9c27a73b6ac7badbe6be673aa3ddf (patch)
treea6c7e2d6cd7bfa7011cc39abbb436142d7a4a7c8 /WebCore/platform/graphics/filters
parente196732677050bd463301566a68a643b6d14b907 (diff)
downloadexternal_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.zip
external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.tar.gz
external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.tar.bz2
Merge webkit.org at R49305 : Automatic merge by git.
Change-Id: I8968561bc1bfd72b8923b7118d3728579c6dbcc7
Diffstat (limited to 'WebCore/platform/graphics/filters')
-rw-r--r--WebCore/platform/graphics/filters/FEBlend.cpp78
-rw-r--r--WebCore/platform/graphics/filters/FEBlend.h2
-rw-r--r--WebCore/platform/graphics/filters/FEColorMatrix.cpp4
-rw-r--r--WebCore/platform/graphics/filters/FEComponentTransfer.cpp92
-rw-r--r--WebCore/platform/graphics/filters/FEComposite.cpp72
-rw-r--r--WebCore/platform/graphics/filters/FilterEffect.cpp7
-rw-r--r--WebCore/platform/graphics/filters/FilterEffect.h1
-rw-r--r--WebCore/platform/graphics/filters/SourceAlpha.cpp23
-rw-r--r--WebCore/platform/graphics/filters/SourceAlpha.h2
9 files changed, 273 insertions, 8 deletions
diff --git a/WebCore/platform/graphics/filters/FEBlend.cpp b/WebCore/platform/graphics/filters/FEBlend.cpp
index 86b702f..2364cc4 100644
--- a/WebCore/platform/graphics/filters/FEBlend.cpp
+++ b/WebCore/platform/graphics/filters/FEBlend.cpp
@@ -2,6 +2,7 @@
Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005 Rob Buis <buis@kde.org>
2005 Eric Seidel <eric@webkit.org>
+ 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
@@ -24,7 +25,13 @@
#if ENABLE(FILTERS)
#include "FEBlend.h"
+#include "CanvasPixelArray.h"
#include "Filter.h"
+#include "FloatPoint.h"
+#include "GraphicsContext.h"
+#include "ImageData.h"
+
+typedef unsigned char (*BlendType)(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB);
namespace WebCore {
@@ -61,8 +68,77 @@ void FEBlend::setBlendMode(BlendModeType mode)
m_mode = mode;
}
-void FEBlend::apply(Filter*)
+static unsigned char unknown(unsigned char, unsigned char, unsigned char, unsigned char)
+{
+ return 0;
+}
+
+static unsigned char normal(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char)
+{
+ return (((255 - alphaA) * colorB + colorA * 255) / 255);
+}
+
+static unsigned char multiply(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
+{
+ return (((255 - alphaA) * colorB + (255 - alphaB + colorB) * colorA) / 255);
+}
+
+static unsigned char screen(unsigned char colorA, unsigned char colorB, unsigned char, unsigned char)
+{
+ return (((colorB + colorA) * 255 - colorA * colorB) / 255);
+}
+
+static unsigned char darken(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
+{
+ return ((std::min((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255)) / 255);
+}
+
+static unsigned char lighten(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
{
+ return ((std::max((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255)) / 255);
+}
+
+void FEBlend::apply(Filter* filter)
+{
+ m_in->apply(filter);
+ m_in2->apply(filter);
+ if (!m_in->resultImage() || !m_in2->resultImage())
+ return;
+
+ if (m_mode == FEBLEND_MODE_UNKNOWN)
+ return;
+
+ if (!getEffectContext())
+ return;
+
+ IntRect effectADrawingRect = calculateDrawingIntRect(m_in->subRegion());
+ RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
+
+ IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->subRegion());
+ RefPtr<CanvasPixelArray> srcPixelArrayB(m_in2->resultImage()->getPremultipliedImageData(effectBDrawingRect)->data());
+
+ IntRect imageRect(IntPoint(), resultImage()->size());
+ RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height());
+
+ // Keep synchronized with BlendModeType
+ static const BlendType callEffect[] = {unknown, normal, multiply, screen, darken, lighten};
+
+ ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length());
+ for (unsigned pixelOffset = 0; pixelOffset < srcPixelArrayA->length(); pixelOffset += 4) {
+ unsigned char alphaA = srcPixelArrayA->get(pixelOffset + 3);
+ unsigned char alphaB = srcPixelArrayB->get(pixelOffset + 3);
+ for (unsigned channel = 0; channel < 3; ++channel) {
+ unsigned char colorA = srcPixelArrayA->get(pixelOffset + channel);
+ unsigned char colorB = srcPixelArrayB->get(pixelOffset + channel);
+
+ unsigned char result = (*callEffect[m_mode])(colorA, colorB, alphaA, alphaB);
+ imageData->data()->set(pixelOffset + channel, result);
+ }
+ unsigned char alphaR = 255 - ((255 - alphaA) * (255 - alphaB)) / 255;
+ imageData->data()->set(pixelOffset + 3, alphaR);
+ }
+
+ resultImage()->putPremultipliedImageData(imageData.get(), imageRect, IntPoint());
}
void FEBlend::dump()
diff --git a/WebCore/platform/graphics/filters/FEBlend.h b/WebCore/platform/graphics/filters/FEBlend.h
index b09cd72..31c625f 100644
--- a/WebCore/platform/graphics/filters/FEBlend.h
+++ b/WebCore/platform/graphics/filters/FEBlend.h
@@ -41,7 +41,7 @@ namespace WebCore {
class FEBlend : public FilterEffect {
public:
static PassRefPtr<FEBlend> create(FilterEffect*, FilterEffect*, BlendModeType);
-
+
FilterEffect* in2() const;
void setIn2(FilterEffect*);
diff --git a/WebCore/platform/graphics/filters/FEColorMatrix.cpp b/WebCore/platform/graphics/filters/FEColorMatrix.cpp
index fb0a194..1e2e552 100644
--- a/WebCore/platform/graphics/filters/FEColorMatrix.cpp
+++ b/WebCore/platform/graphics/filters/FEColorMatrix.cpp
@@ -166,7 +166,7 @@ void FEColorMatrix::apply(Filter* filter)
filterContext->drawImage(m_in->resultImage()->image(), calculateDrawingRect(m_in->subRegion()));
IntRect imageRect(IntPoint(), resultImage()->size());
- PassRefPtr<ImageData> imageData(resultImage()->getImageData(imageRect));
+ PassRefPtr<ImageData> imageData(resultImage()->getUnmultipliedImageData(imageRect));
PassRefPtr<CanvasPixelArray> srcPixelArray(imageData->data());
switch (m_type) {
@@ -186,7 +186,7 @@ void FEColorMatrix::apply(Filter* filter)
break;
}
- resultImage()->putImageData(imageData.get(), imageRect, IntPoint());
+ resultImage()->putUnmultipliedImageData(imageData.get(), imageRect, IntPoint());
}
void FEColorMatrix::dump()
diff --git a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
index 54ac123..43e5edd 100644
--- a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
+++ b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
@@ -2,6 +2,7 @@
Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005 Rob Buis <buis@kde.org>
2005 Eric Seidel <eric@webkit.org>
+ 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
@@ -24,10 +25,16 @@
#if ENABLE(FILTERS)
#include "FEComponentTransfer.h"
+#include "CanvasPixelArray.h"
#include "Filter.h"
+#include "GraphicsContext.h"
+#include "ImageData.h"
+#include <math.h>
namespace WebCore {
+typedef void (*TransferType)(unsigned char*, const ComponentTransferFunction&);
+
FEComponentTransfer::FEComponentTransfer(FilterEffect* in, const ComponentTransferFunction& redFunc,
const ComponentTransferFunction& greenFunc, const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc)
: FilterEffect()
@@ -85,8 +92,91 @@ void FEComponentTransfer::setAlphaFunction(const ComponentTransferFunction& func
m_alphaFunc = func;
}
-void FEComponentTransfer::apply(Filter*)
+void identity(unsigned char*, const ComponentTransferFunction&)
+{
+}
+
+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);
+ }
+}
+
+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);
+ }
+}
+
+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);
+ }
+}
+
+void gamma(unsigned char* values, const ComponentTransferFunction& transferFunction)
+{
+ for (unsigned i = 0; i < 256; ++i) {
+ double val = 255.0 * (transferFunction.amplitude * pow((i / 255.0), transferFunction.exponent) + transferFunction.offset);
+ val = std::max(0.0, std::min(255.0, val));
+ values[i] = static_cast<unsigned char>(val);
+ }
+}
+
+void FEComponentTransfer::apply(Filter* filter)
{
+ m_in->apply(filter);
+ if (!m_in->resultImage())
+ return;
+
+ if (!getEffectContext())
+ return;
+
+ unsigned char rValues[256], gValues[256], bValues[256], aValues[256];
+ for (unsigned i = 0; i < 256; ++i)
+ rValues[i] = gValues[i] = bValues[i] = aValues[i] = i;
+ unsigned char* tables[] = { rValues, gValues, bValues, aValues };
+ ComponentTransferFunction transferFunction[] = {m_redFunc, m_greenFunc, m_blueFunc, m_alphaFunc};
+ TransferType callEffect[] = {identity, identity, table, discrete, linear, gamma};
+
+ for (unsigned channel = 0; channel < 4; channel++)
+ (*callEffect[transferFunction[channel].type])(tables[channel], transferFunction[channel]);
+
+ IntRect drawingRect = calculateDrawingIntRect(m_in->subRegion());
+ RefPtr<ImageData> imageData(m_in->resultImage()->getUnmultipliedImageData(drawingRect));
+ CanvasPixelArray* srcPixelArray(imageData->data());
+
+ for (unsigned pixelOffset = 0; pixelOffset < srcPixelArray->length(); pixelOffset += 4) {
+ for (unsigned channel = 0; channel < 4; ++channel) {
+ unsigned char c = srcPixelArray->get(pixelOffset + channel);
+ imageData->data()->set(pixelOffset + channel, tables[channel][c]);
+ }
+ }
+
+ resultImage()->putUnmultipliedImageData(imageData.get(), IntRect(IntPoint(), resultImage()->size()), IntPoint());
}
void FEComponentTransfer::dump()
diff --git a/WebCore/platform/graphics/filters/FEComposite.cpp b/WebCore/platform/graphics/filters/FEComposite.cpp
index 0706358..1b41165 100644
--- a/WebCore/platform/graphics/filters/FEComposite.cpp
+++ b/WebCore/platform/graphics/filters/FEComposite.cpp
@@ -2,6 +2,7 @@
Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005 Rob Buis <buis@kde.org>
2005 Eric Seidel <eric@webkit.org>
+ 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
@@ -24,7 +25,10 @@
#if ENABLE(FILTERS)
#include "FEComposite.h"
+#include "CanvasPixelArray.h"
#include "Filter.h"
+#include "GraphicsContext.h"
+#include "ImageData.h"
namespace WebCore {
@@ -97,8 +101,74 @@ void FEComposite::setK4(float k4)
m_k4 = k4;
}
-void FEComposite::apply(Filter*)
+inline void arithmetic(const RefPtr<CanvasPixelArray>& srcPixelArrayA, CanvasPixelArray*& srcPixelArrayB,
+ float k1, float k2, float k3, float k4)
{
+ float scaledK1 = k1 / 255.f;
+ float scaledK4 = k4 * 255.f;
+ for (unsigned pixelOffset = 0; pixelOffset < srcPixelArrayA->length(); pixelOffset += 4) {
+ for (unsigned channel = 0; channel < 4; ++channel) {
+ unsigned char i1 = srcPixelArrayA->get(pixelOffset + channel);
+ unsigned char i2 = srcPixelArrayB->get(pixelOffset + channel);
+
+ unsigned char result = scaledK1 * i1 * i2 + k2 * i1 + k3 * i2 + scaledK4;
+ if (channel == 3 && i1 == 0 && i2 == 0)
+ result = 0;
+ srcPixelArrayB->set(pixelOffset + channel, result);
+ }
+ }
+}
+
+void FEComposite::apply(Filter* filter)
+{
+ m_in->apply(filter);
+ m_in2->apply(filter);
+ if (!m_in->resultImage() || !m_in2->resultImage())
+ return;
+
+ GraphicsContext* filterContext = getEffectContext();
+ if (!filterContext)
+ return;
+
+ FloatRect srcRect = FloatRect(0.f, 0.f, -1.f, -1.f);
+ switch (m_type) {
+ case FECOMPOSITE_OPERATOR_OVER:
+ filterContext->drawImage(m_in2->resultImage()->image(), calculateDrawingRect(m_in2->subRegion()));
+ filterContext->drawImage(m_in->resultImage()->image(), calculateDrawingRect(m_in->subRegion()));
+ break;
+ case FECOMPOSITE_OPERATOR_IN:
+ filterContext->save();
+ filterContext->clipToImageBuffer(calculateDrawingRect(m_in2->subRegion()), m_in2->resultImage());
+ filterContext->drawImage(m_in->resultImage()->image(), calculateDrawingRect(m_in->subRegion()));
+ filterContext->restore();
+ break;
+ case FECOMPOSITE_OPERATOR_OUT:
+ filterContext->drawImage(m_in->resultImage()->image(), calculateDrawingRect(m_in->subRegion()));
+ filterContext->drawImage(m_in2->resultImage()->image(), calculateDrawingRect(m_in2->subRegion()), srcRect, CompositeDestinationOut);
+ break;
+ case FECOMPOSITE_OPERATOR_ATOP:
+ filterContext->drawImage(m_in2->resultImage()->image(), calculateDrawingRect(m_in2->subRegion()));
+ filterContext->drawImage(m_in->resultImage()->image(), calculateDrawingRect(m_in->subRegion()), srcRect, CompositeSourceAtop);
+ break;
+ case FECOMPOSITE_OPERATOR_XOR:
+ filterContext->drawImage(m_in2->resultImage()->image(), calculateDrawingRect(m_in2->subRegion()));
+ filterContext->drawImage(m_in->resultImage()->image(), calculateDrawingRect(m_in->subRegion()), srcRect, CompositeXOR);
+ break;
+ case FECOMPOSITE_OPERATOR_ARITHMETIC: {
+ IntRect effectADrawingRect = calculateDrawingIntRect(m_in->subRegion());
+ RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
+
+ IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->subRegion());
+ RefPtr<ImageData> imageData(m_in2->resultImage()->getPremultipliedImageData(effectBDrawingRect));
+ CanvasPixelArray* srcPixelArrayB(imageData->data());
+
+ arithmetic(srcPixelArrayA, srcPixelArrayB, m_k1, m_k2, m_k3, m_k4);
+ resultImage()->putPremultipliedImageData(imageData.get(), IntRect(IntPoint(), resultImage()->size()), IntPoint());
+ }
+ break;
+ default:
+ break;
+ }
}
void FEComposite::dump()
diff --git a/WebCore/platform/graphics/filters/FilterEffect.cpp b/WebCore/platform/graphics/filters/FilterEffect.cpp
index 41e8a39..5818e50 100644
--- a/WebCore/platform/graphics/filters/FilterEffect.cpp
+++ b/WebCore/platform/graphics/filters/FilterEffect.cpp
@@ -59,6 +59,13 @@ FloatRect FilterEffect::calculateEffectRect(Filter* filter)
return subRegion();
}
+IntRect FilterEffect::calculateDrawingIntRect(const FloatRect& effectRect)
+{
+ IntPoint location = roundedIntPoint(FloatPoint(subRegion().x() - effectRect.x(),
+ subRegion().y() - effectRect.y()));
+ return IntRect(location, resultImage()->size());
+}
+
FloatRect FilterEffect::calculateDrawingRect(const FloatRect& srcRect)
{
FloatPoint startPoint = FloatPoint(srcRect.x() - subRegion().x(), srcRect.y() - subRegion().y());
diff --git a/WebCore/platform/graphics/filters/FilterEffect.h b/WebCore/platform/graphics/filters/FilterEffect.h
index 8dc6233..e2b8a0e 100644
--- a/WebCore/platform/graphics/filters/FilterEffect.h
+++ b/WebCore/platform/graphics/filters/FilterEffect.h
@@ -77,6 +77,7 @@ namespace WebCore {
GraphicsContext* getEffectContext();
FloatRect calculateDrawingRect(const FloatRect&);
+ IntRect calculateDrawingIntRect(const FloatRect&);
virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return filter->filterRegion(); }
virtual FloatRect calculateEffectRect(Filter*);
diff --git a/WebCore/platform/graphics/filters/SourceAlpha.cpp b/WebCore/platform/graphics/filters/SourceAlpha.cpp
index 646a57b..57436be 100644
--- a/WebCore/platform/graphics/filters/SourceAlpha.cpp
+++ b/WebCore/platform/graphics/filters/SourceAlpha.cpp
@@ -22,6 +22,7 @@
#if ENABLE(FILTERS)
#include "SourceAlpha.h"
+#include "Color.h"
#include "GraphicsContext.h"
#include "PlatformString.h"
#include "Filter.h"
@@ -41,8 +42,28 @@ const AtomicString& SourceAlpha::effectName()
return s_effectName;
}
-void SourceAlpha::apply(Filter*)
+FloatRect SourceAlpha::calculateEffectRect(Filter* filter)
{
+ FloatRect clippedSourceRect = filter->sourceImageRect();
+ if (filter->sourceImageRect().x() < filter->filterRegion().x())
+ clippedSourceRect.setX(filter->filterRegion().x());
+ if (filter->sourceImageRect().y() < filter->filterRegion().y())
+ clippedSourceRect.setY(filter->filterRegion().y());
+ setSubRegion(clippedSourceRect);
+ return filter->filterRegion();
+}
+
+void SourceAlpha::apply(Filter* filter)
+{
+ GraphicsContext* filterContext = getEffectContext();
+ if (!filterContext)
+ return;
+
+ FloatRect imageRect(FloatPoint(), filter->sourceImage()->image()->size());
+ filterContext->save();
+ filterContext->clipToImageBuffer(imageRect, filter->sourceImage());
+ filterContext->fillRect(imageRect, Color::black);
+ filterContext->restore();
}
void SourceAlpha::dump()
diff --git a/WebCore/platform/graphics/filters/SourceAlpha.h b/WebCore/platform/graphics/filters/SourceAlpha.h
index 5341562..172d05a 100644
--- a/WebCore/platform/graphics/filters/SourceAlpha.h
+++ b/WebCore/platform/graphics/filters/SourceAlpha.h
@@ -35,7 +35,7 @@ namespace WebCore {
static const AtomicString& effectName();
virtual bool isSourceInput() { return true; }
- virtual FloatRect calculateEffectRect(Filter* filter) { return filter->sourceImageRect(); }
+ virtual FloatRect calculateEffectRect(Filter*);
void apply(Filter*);
void dump();