diff options
author | Steve Block <steveblock@google.com> | 2009-10-08 17:19:54 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2009-10-20 00:41:58 +0100 |
commit | 231d4e3152a9c27a73b6ac7badbe6be673aa3ddf (patch) | |
tree | a6c7e2d6cd7bfa7011cc39abbb436142d7a4a7c8 /WebCore/platform/graphics/filters | |
parent | e196732677050bd463301566a68a643b6d14b907 (diff) | |
download | external_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.cpp | 78 | ||||
-rw-r--r-- | WebCore/platform/graphics/filters/FEBlend.h | 2 | ||||
-rw-r--r-- | WebCore/platform/graphics/filters/FEColorMatrix.cpp | 4 | ||||
-rw-r--r-- | WebCore/platform/graphics/filters/FEComponentTransfer.cpp | 92 | ||||
-rw-r--r-- | WebCore/platform/graphics/filters/FEComposite.cpp | 72 | ||||
-rw-r--r-- | WebCore/platform/graphics/filters/FilterEffect.cpp | 7 | ||||
-rw-r--r-- | WebCore/platform/graphics/filters/FilterEffect.h | 1 | ||||
-rw-r--r-- | WebCore/platform/graphics/filters/SourceAlpha.cpp | 23 | ||||
-rw-r--r-- | WebCore/platform/graphics/filters/SourceAlpha.h | 2 |
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(); |