Changeset 154948 in webkit


Ignore:
Timestamp:
Sep 1, 2013 9:53:46 PM (11 years ago)
Author:
krit@webkit.org
Message:

Source/WebCore: Add 'edgeMode' attribute to SVGFEGaussianBlur
https://bugs.webkit.org/show_bug.cgi?id=120582

Add 'edgeMode' attribute to the SVGFEGaussianBlur element. This attribute
allows users to define the behavior on edges with the values 'none' where
pixel values outside the input image are treated as transparent black. (The
current blurring behavior.) 'duplicate' which repeats the values on the
nearest edge and 'warp', which takes the pixel of the opposite site of
the input image.
Beside the attribute, this patch implements the behavior of 'duplicate'.

http://dev.w3.org/fxtf/filters/#feGaussianBlurEdgeModeAttribute

Reviewed by Rob Buis.

Tests: svg/dynamic-updates/SVGFEGaussianBlurElement-dom-edgeMode-attr.html

svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop.html
svg/filters/svg-gaussianblur-edgeMode-duplicate-expected.svg
svg/filters/svg-gaussianblur-edgeMode-duplicate.svg

  • platform/graphics/filters/FEGaussianBlur.cpp:

(WebCore::FEGaussianBlur::FEGaussianBlur):
(WebCore::FEGaussianBlur::create):
(WebCore::FEGaussianBlur::edgeMode):
(WebCore::FEGaussianBlur::setEdgeMode):
(WebCore::boxBlur):
(WebCore::FEGaussianBlur::platformApplyGeneric):
(WebCore::FEGaussianBlur::determineAbsolutePaintRect):

  • platform/graphics/filters/FEGaussianBlur.h:
  • rendering/FilterEffectRenderer.cpp:

(WebCore::FilterEffectRenderer::build):

  • svg/SVGFEGaussianBlurElement.cpp:

(WebCore::SVGFEGaussianBlurElement::SVGFEGaussianBlurElement):
(WebCore::SVGFEGaussianBlurElement::isSupportedAttribute):
(WebCore::SVGFEGaussianBlurElement::parseAttribute):
(WebCore::SVGFEGaussianBlurElement::svgAttributeChanged):
(WebCore::SVGFEGaussianBlurElement::build):

  • svg/SVGFEGaussianBlurElement.h:
  • svg/SVGFEGaussianBlurElement.idl:

LayoutTests: Add edgeMode attribtue.

Add 'edgeMode' attribute to SVGFEGaussianBlur
https://bugs.webkit.org/show_bug.cgi?id=120582

Added DOM and SVGDOM tests for the attribute 'edgeMode'.
Also added a reftest to test edgeMode='duplicate'.

Reviewed by Rob Buis.

  • platform/mac/svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop-expected.png: Added.
  • svg/dynamic-updates/SVGFEGaussianBlurElement-dom-edgeMode-attr-expected.txt: Added.
  • svg/dynamic-updates/SVGFEGaussianBlurElement-dom-edgeMode-attr.html: Added.
  • svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop-expected.txt: Added.
  • svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop.html: Added.
  • svg/dynamic-updates/script-tests/SVGFEGaussianBlurElement-dom-edgeMode-attr.js: Added.

(repaintTest):

  • svg/dynamic-updates/script-tests/SVGFEGaussianBlurElement-svgdom-edgeMode-prop.js: Added.

(repaintTest):

  • svg/filters/svg-gaussianblur-edgeMode-duplicate-expected.svg: Added.
  • svg/filters/svg-gaussianblur-edgeMode-duplicate.svg: Added.
Location:
trunk
Files:
9 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r154944 r154948  
     12013-09-01  Dirk Schulze  <krit@webkit.org>
     2
     3        Add edgeMode attribtue.
     4
     5        Add 'edgeMode' attribute to SVGFEGaussianBlur
     6        https://bugs.webkit.org/show_bug.cgi?id=120582
     7
     8        Added DOM and SVGDOM tests for the attribute 'edgeMode'.
     9        Also added a reftest to test edgeMode='duplicate'.
     10
     11        Reviewed by Rob Buis.
     12
     13        * platform/mac/svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop-expected.png: Added.
     14        * svg/dynamic-updates/SVGFEGaussianBlurElement-dom-edgeMode-attr-expected.txt: Added.
     15        * svg/dynamic-updates/SVGFEGaussianBlurElement-dom-edgeMode-attr.html: Added.
     16        * svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop-expected.txt: Added.
     17        * svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop.html: Added.
     18        * svg/dynamic-updates/script-tests/SVGFEGaussianBlurElement-dom-edgeMode-attr.js: Added.
     19        (repaintTest):
     20        * svg/dynamic-updates/script-tests/SVGFEGaussianBlurElement-svgdom-edgeMode-prop.js: Added.
     21        (repaintTest):
     22        * svg/filters/svg-gaussianblur-edgeMode-duplicate-expected.svg: Added.
     23        * svg/filters/svg-gaussianblur-edgeMode-duplicate.svg: Added.
     24
    1252013-09-01  Xabier Rodriguez Calvar  <calvaris@igalia.com>
    226
  • trunk/Source/WebCore/ChangeLog

    r154947 r154948  
     12013-09-01  Dirk Schulze  <krit@webkit.org>
     2
     3        Add 'edgeMode' attribute to SVGFEGaussianBlur
     4        https://bugs.webkit.org/show_bug.cgi?id=120582
     5
     6        Add 'edgeMode' attribute to the SVGFEGaussianBlur element. This attribute
     7        allows users to define the behavior on edges with the values 'none' where
     8        pixel values outside the input image are treated as transparent black. (The
     9        current blurring behavior.) 'duplicate' which repeats the values on the
     10        nearest edge and 'warp', which takes the pixel of the opposite site of
     11        the input image.
     12        Beside the attribute, this patch implements the behavior of 'duplicate'.
     13
     14        http://dev.w3.org/fxtf/filters/#feGaussianBlurEdgeModeAttribute
     15
     16        Reviewed by Rob Buis.
     17
     18        Tests: svg/dynamic-updates/SVGFEGaussianBlurElement-dom-edgeMode-attr.html
     19               svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop.html
     20               svg/filters/svg-gaussianblur-edgeMode-duplicate-expected.svg
     21               svg/filters/svg-gaussianblur-edgeMode-duplicate.svg
     22
     23        * platform/graphics/filters/FEGaussianBlur.cpp:
     24        (WebCore::FEGaussianBlur::FEGaussianBlur):
     25        (WebCore::FEGaussianBlur::create):
     26        (WebCore::FEGaussianBlur::edgeMode):
     27        (WebCore::FEGaussianBlur::setEdgeMode):
     28        (WebCore::boxBlur):
     29        (WebCore::FEGaussianBlur::platformApplyGeneric):
     30        (WebCore::FEGaussianBlur::determineAbsolutePaintRect):
     31        * platform/graphics/filters/FEGaussianBlur.h:
     32        * rendering/FilterEffectRenderer.cpp:
     33        (WebCore::FilterEffectRenderer::build):
     34        * svg/SVGFEGaussianBlurElement.cpp:
     35        (WebCore::SVGFEGaussianBlurElement::SVGFEGaussianBlurElement):
     36        (WebCore::SVGFEGaussianBlurElement::isSupportedAttribute):
     37        (WebCore::SVGFEGaussianBlurElement::parseAttribute):
     38        (WebCore::SVGFEGaussianBlurElement::svgAttributeChanged):
     39        (WebCore::SVGFEGaussianBlurElement::build):
     40        * svg/SVGFEGaussianBlurElement.h:
     41        * svg/SVGFEGaussianBlurElement.idl:
     42
    1432013-09-01  Andreas Kling  <akling@apple.com>
    244
  • trunk/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp

    r154127 r154948  
    5151namespace WebCore {
    5252
    53 FEGaussianBlur::FEGaussianBlur(Filter* filter, float x, float y)
     53FEGaussianBlur::FEGaussianBlur(Filter* filter, float x, float y, EdgeModeType edgeMode)
    5454    : FilterEffect(filter)
    5555    , m_stdX(x)
    5656    , m_stdY(y)
    57 {
    58 }
    59 
    60 PassRefPtr<FEGaussianBlur> FEGaussianBlur::create(Filter* filter, float x, float y)
    61 {
    62     return adoptRef(new FEGaussianBlur(filter, x, y));
     57    , m_edgeMode(edgeMode)
     58{
     59}
     60
     61PassRefPtr<FEGaussianBlur> FEGaussianBlur::create(Filter* filter, float x, float y, EdgeModeType edgeMode)
     62{
     63    return adoptRef(new FEGaussianBlur(filter, x, y, edgeMode));
    6364}
    6465
     
    8384}
    8485
     86EdgeModeType FEGaussianBlur::edgeMode() const
     87{
     88    return m_edgeMode;
     89}
     90
     91void FEGaussianBlur::setEdgeMode(EdgeModeType edgeMode)
     92{
     93    m_edgeMode = edgeMode;
     94}
     95
    8596inline void boxBlur(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* dstPixelArray,
    86                     unsigned dx, int dxLeft, int dxRight, int stride, int strideLine, int effectWidth, int effectHeight, bool alphaImage)
     97    unsigned dx, int dxLeft, int dxRight, int stride, int strideLine, int effectWidth, int effectHeight, bool alphaImage, EdgeModeType edgeMode)
    8798{
    8899    for (int y = 0; y < effectHeight; ++y) {
     
    90101        for (int channel = 3; channel >= 0; --channel) {
    91102            int sum = 0;
    92             // Fill the kernel
    93             int maxKernelSize = min(dxRight, effectWidth);
    94             for (int i = 0; i < maxKernelSize; ++i)
    95                 sum += srcPixelArray->item(line + i * stride + channel);
    96 
    97             // Blurring
    98             for (int x = 0; x < effectWidth; ++x) {
    99                 int pixelByteOffset = line + x * stride + channel;
    100                 dstPixelArray->set(pixelByteOffset, static_cast<unsigned char>(sum / dx));
    101                 if (x >= dxLeft)
    102                     sum -= srcPixelArray->item(pixelByteOffset - dxLeft * stride);
    103                 if (x + dxRight < effectWidth)
    104                     sum += srcPixelArray->item(pixelByteOffset + dxRight * stride);
     103            // The code for edgeMode='none' is the common case and highly optimized.
     104            // Furthermore, this code path affects more than just the input area.
     105            if (edgeMode == EDGEMODE_NONE) {
     106                // Fill the kernel
     107                int maxKernelSize = min(dxRight, effectWidth);
     108                for (int i = 0; i < maxKernelSize; ++i)
     109                    sum += srcPixelArray->item(line + i * stride + channel);
     110
     111                // Blurring
     112                for (int x = 0; x < effectWidth; ++x) {
     113                    int pixelByteOffset = line + x * stride + channel;
     114                    dstPixelArray->set(pixelByteOffset, static_cast<unsigned char>(sum / dx));
     115                    // Shift kernel.
     116                    if (x >= dxLeft)
     117                        sum -= srcPixelArray->item(pixelByteOffset - dxLeft * stride);
     118                    if (x + dxRight < effectWidth)
     119                        sum += srcPixelArray->item(pixelByteOffset + dxRight * stride);
     120                }
     121            } else {
     122                // FIXME: Add support for 'wrap' here.
     123                // Get edge values for edgeMode 'duplicate'.
     124                int edgeValueLeft = srcPixelArray->item(line + channel);
     125                int edgeValueRight = srcPixelArray->item(line + (effectWidth - 1) * stride + channel);
     126                // Fill the kernel
     127                for (int i = dxLeft * -1; i < dxRight; ++i) {
     128                    if (i < 0)
     129                        sum += edgeValueLeft;
     130                    else if (i >= effectWidth)
     131                        sum += edgeValueRight;
     132                    else
     133                        sum += srcPixelArray->item(line + i * stride + channel);
     134                }
     135                // Blurring
     136                for (int x = 0; x < effectWidth; ++x) {
     137                    int pixelByteOffset = line + x * stride + channel;
     138                    dstPixelArray->set(pixelByteOffset, static_cast<unsigned char>(sum / dx));
     139                    // Shift kernel.
     140                    if (x < dxLeft)
     141                        sum -= edgeValueLeft;
     142                    else
     143                        sum -= srcPixelArray->item(pixelByteOffset - dxLeft * stride);
     144                    if (x + dxRight >= effectWidth)
     145                        sum += edgeValueRight;
     146                    else
     147                        sum += srcPixelArray->item(pixelByteOffset + dxRight * stride);
     148                }
    105149            }
    106150            if (alphaImage) // Source image is black, it just has different alpha values
     
    127171                boxBlurNEON(src, dst, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height());
    128172            else
    129                 boxBlur(src, dst, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height(), true);
     173                boxBlur(src, dst, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height(), true, m_edgeMode);
    130174#else
    131             boxBlur(src, dst, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height(), isAlphaImage());
     175            boxBlur(src, dst, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height(), isAlphaImage(), m_edgeMode);
    132176#endif
    133177            swap(src, dst);
     
    140184                boxBlurNEON(src, dst, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width());
    141185            else
    142                 boxBlur(src, dst, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width(), true);
     186                boxBlur(src, dst, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width(), true, m_edgeMode);
    143187#else
    144             boxBlur(src, dst, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width(), isAlphaImage());
     188            boxBlur(src, dst, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width(), isAlphaImage(), m_edgeMode);
    145189#endif
    146190            swap(src, dst);
     
    265309
    266310    FloatRect absolutePaintRect = inputEffect(0)->absolutePaintRect();
     311    // Edge modes other than 'none' do not inflate the affected paint rect.
     312    if (m_edgeMode != EDGEMODE_NONE) {
     313        setAbsolutePaintRect(enclosingIntRect(absolutePaintRect));
     314        return;
     315    }
    267316
    268317    // We take the half kernel size and multiply it with three, because we run box blur three times.
  • trunk/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h

    r149193 r154948  
    2424
    2525#if ENABLE(FILTERS)
     26#include "FEConvolveMatrix.h"
     27#include "Filter.h"
    2628#include "FilterEffect.h"
    27 #include "Filter.h"
    2829
    2930namespace WebCore {
     
    3132class FEGaussianBlur : public FilterEffect {
    3233public:
    33     static PassRefPtr<FEGaussianBlur> create(Filter*, float, float);
     34    static PassRefPtr<FEGaussianBlur> create(Filter*, float, float, EdgeModeType);
    3435
    3536    float stdDeviationX() const;
     
    3839    float stdDeviationY() const;
    3940    void setStdDeviationY(float);
     41
     42    EdgeModeType edgeMode() const;
     43    void setEdgeMode(EdgeModeType);
    4044
    4145    static float calculateStdDeviation(float);
     
    6872    static void platformApplyWorker(PlatformApplyParameters*);
    6973
    70     FEGaussianBlur(Filter*, float, float);
     74    FEGaussianBlur(Filter*, float, float, EdgeModeType);
    7175
    7276    static inline void kernelPosition(int boxBlur, unsigned& std, int& dLeft, int& dRight);
     
    7781    float m_stdX;
    7882    float m_stdY;
     83    EdgeModeType m_edgeMode;
    7984};
    8085
  • trunk/Source/WebCore/rendering/FilterEffectRenderer.cpp

    r154928 r154948  
    327327            BlurFilterOperation* blurOperation = static_cast<BlurFilterOperation*>(filterOperation);
    328328            float stdDeviation = floatValueForLength(blurOperation->stdDeviation(), 0);
    329             effect = FEGaussianBlur::create(this, stdDeviation, stdDeviation);
     329            effect = FEGaussianBlur::create(this, stdDeviation, stdDeviation, EDGEMODE_NONE);
    330330            break;
    331331        }
  • trunk/Source/WebCore/svg/SVGFEGaussianBlurElement.cpp

    r151800 r154948  
    3737DEFINE_ANIMATED_NUMBER_MULTIPLE_WRAPPERS(SVGFEGaussianBlurElement, SVGNames::stdDeviationAttr, stdDeviationXIdentifier(), StdDeviationX, stdDeviationX)
    3838DEFINE_ANIMATED_NUMBER_MULTIPLE_WRAPPERS(SVGFEGaussianBlurElement, SVGNames::stdDeviationAttr, stdDeviationYIdentifier(), StdDeviationY, stdDeviationY)
     39DEFINE_ANIMATED_ENUMERATION(SVGFEGaussianBlurElement, SVGNames::edgeModeAttr, EdgeMode, edgeMode, EdgeModeType)
    3940
    4041BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGFEGaussianBlurElement)
     
    4243    REGISTER_LOCAL_ANIMATED_PROPERTY(stdDeviationX)
    4344    REGISTER_LOCAL_ANIMATED_PROPERTY(stdDeviationY)
     45    REGISTER_LOCAL_ANIMATED_PROPERTY(edgeMode)
    4446    REGISTER_PARENT_ANIMATED_PROPERTIES(SVGFilterPrimitiveStandardAttributes)
    4547END_REGISTER_ANIMATED_PROPERTIES
     
    4749inline SVGFEGaussianBlurElement::SVGFEGaussianBlurElement(const QualifiedName& tagName, Document* document)
    4850    : SVGFilterPrimitiveStandardAttributes(tagName, document)
     51    , m_edgeMode(EDGEMODE_NONE)
    4952{
    5053    ASSERT(hasTagName(SVGNames::feGaussianBlurTag));
     
    8285        supportedAttributes.add(SVGNames::inAttr);
    8386        supportedAttributes.add(SVGNames::stdDeviationAttr);
     87        supportedAttributes.add(SVGNames::edgeModeAttr);
    8488    }
    8589    return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
     
    107111    }
    108112
     113    if (name == SVGNames::edgeModeAttr) {
     114        EdgeModeType propertyValue = SVGPropertyTraits<EdgeModeType>::fromString(value);
     115        if (propertyValue > 0)
     116            setEdgeModeBaseValue(propertyValue);
     117        else
     118            document().accessSVGExtensions()->reportWarning(
     119                "feGaussianBlur: problem parsing edgeMode=\"" + value
     120                + "\". Filtered element will not be displayed.");
     121        return;
     122    }
     123
    109124    ASSERT_NOT_REACHED();
    110125}
     
    119134    SVGElementInstance::InvalidationGuard invalidationGuard(this);
    120135   
    121     if (attrName == SVGNames::inAttr || attrName == SVGNames::stdDeviationAttr) {
     136    if (attrName == SVGNames::inAttr
     137        || attrName == SVGNames::stdDeviationAttr
     138        || attrName == SVGNames::edgeModeAttr) {
    122139        invalidate();
    123140        return;
     
    137154        return 0;
    138155
    139     RefPtr<FilterEffect> effect = FEGaussianBlur::create(filter, stdDeviationX(), stdDeviationY());
     156    RefPtr<FilterEffect> effect = FEGaussianBlur::create(filter, stdDeviationX(), stdDeviationY(), edgeMode());
    140157    effect->inputEffects().append(input1);
    141158    return effect.release();
  • trunk/Source/WebCore/svg/SVGFEGaussianBlurElement.h

    r149960 r154948  
    2424#if ENABLE(SVG) && ENABLE(FILTERS)
    2525#include "FEGaussianBlur.h"
     26#include "SVGAnimatedEnumeration.h"
    2627#include "SVGAnimatedNumber.h"
     28#include "SVGFEConvolveMatrixElement.h"
    2729#include "SVGFilterPrimitiveStandardAttributes.h"
    2830
     
    5052        DECLARE_ANIMATED_NUMBER(StdDeviationX, stdDeviationX)
    5153        DECLARE_ANIMATED_NUMBER(StdDeviationY, stdDeviationY)
     54        DECLARE_ANIMATED_ENUMERATION(EdgeMode, edgeMode, EdgeModeType)
    5255    END_DECLARE_ANIMATED_PROPERTIES
    5356};
  • trunk/Source/WebCore/svg/SVGFEGaussianBlurElement.idl

    r154462 r154948  
    2525
    2626[
    27     Conditional=SVG&FILTERS
     27    Conditional=SVG&FILTERS,
     28    DoNotCheckConstants
    2829] interface SVGFEGaussianBlurElement : SVGElement {
     30    // Edge Mode Values
     31    const unsigned short SVG_EDGEMODE_UNKNOWN   = 0;
     32    const unsigned short SVG_EDGEMODE_DUPLICATE = 1;
     33    const unsigned short SVG_EDGEMODE_WRAP      = 2;
     34    const unsigned short SVG_EDGEMODE_NONE      = 3;
     35
    2936    readonly attribute SVGAnimatedString in1;
    3037    readonly attribute SVGAnimatedNumber stdDeviationX;
    3138    readonly attribute SVGAnimatedNumber stdDeviationY;
     39    readonly attribute SVGAnimatedEnumeration edgeMode;
    3240
    3341    void setStdDeviation([Default=Undefined] optional float stdDeviationX,
Note: See TracChangeset for help on using the changeset viewer.