Changeset 49582 in webkit


Ignore:
Timestamp:
Oct 14, 2009 1:30:35 PM (15 years ago)
Author:
krit@webkit.org
Message:

2009-10-14 Dirk Schulze <krit@webkit.org>

Reviewed by Nikolas Zimmermann.

SVG wrong filterRegions for userSpaceOnUse and percentage values
https://bugs.webkit.org/show_bug.cgi?id=30330

Some clean-up of the SVG filter calculation code. This clean-up
also fixes the problem with percentage and userSpaceInUse mode.

Test: svg/filters/subRegion-in-userSpace.svg

  • platform/graphics/filters/FilterEffect.cpp: (WebCore::FilterEffect::FilterEffect):
  • platform/graphics/filters/FilterEffect.h:
  • rendering/SVGRenderSupport.cpp: (WebCore::SVGRenderBase::filterBoundingBoxForRenderer):
  • svg/SVGFilterElement.cpp: (WebCore::SVGFilterElement::buildFilter): (WebCore::SVGFilterElement::canvasResource):
  • svg/SVGFilterElement.h:
  • svg/SVGFilterPrimitiveStandardAttributes.cpp: (WebCore::SVGFilterPrimitiveStandardAttributes::setStandardAttributes):
  • svg/graphics/SVGResourceFilter.cpp: (WebCore::SVGResourceFilter::SVGResourceFilter): (WebCore::SVGResourceFilter::~SVGResourceFilter): (WebCore::SVGResourceFilter::addFilterEffect): (WebCore::SVGResourceFilter::prepareFilter):
  • svg/graphics/SVGResourceFilter.h: (WebCore::SVGResourceFilter::create):
  • svg/graphics/filters/SVGFilter.cpp: (WebCore::SVGFilter::SVGFilter): (WebCore::SVGFilter::calculateEffectSubRegion): (WebCore::SVGFilter::create):
  • svg/graphics/filters/SVGFilter.h:

Reviewed by Nikolas Zimmermann.

Check if the percentage of effect values takes user space as reference and
not the FilterRect.

  • platform/mac/svg/filters/subRegion-in-userSpace-expected.checksum: Added.
  • platform/mac/svg/filters/subRegion-in-userSpace-expected.png: Added.
  • platform/mac/svg/filters/subRegion-in-userSpace-expected.txt: Added.
  • svg/filters/subRegion-in-userSpace.svg: Added.
Location:
trunk
Files:
4 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r49581 r49582  
     12009-10-14  Dirk Schulze  <krit@webkit.org>
     2
     3        Reviewed by Nikolas Zimmermann.
     4
     5        Check if the percentage of effect values takes user space as reference and
     6        not the FilterRect.
     7
     8        * platform/mac/svg/filters/subRegion-in-userSpace-expected.checksum: Added.
     9        * platform/mac/svg/filters/subRegion-in-userSpace-expected.png: Added.
     10        * platform/mac/svg/filters/subRegion-in-userSpace-expected.txt: Added.
     11        * svg/filters/subRegion-in-userSpace.svg: Added.
     12
    1132009-10-14  Brady Eidson  <beidson@apple.com>
    214
  • trunk/WebCore/ChangeLog

    r49578 r49582  
     12009-10-14  Dirk Schulze  <krit@webkit.org>
     2
     3        Reviewed by Nikolas Zimmermann.
     4
     5        SVG wrong filterRegions for userSpaceOnUse and percentage values
     6        [https://bugs.webkit.org/show_bug.cgi?id=30330]
     7
     8        Some clean-up of the SVG filter calculation code. This clean-up
     9        also fixes the problem with percentage and userSpaceInUse mode.
     10
     11        Test: svg/filters/subRegion-in-userSpace.svg
     12
     13        * platform/graphics/filters/FilterEffect.cpp:
     14        (WebCore::FilterEffect::FilterEffect):
     15        * platform/graphics/filters/FilterEffect.h:
     16        * rendering/SVGRenderSupport.cpp:
     17        (WebCore::SVGRenderBase::filterBoundingBoxForRenderer):
     18        * svg/SVGFilterElement.cpp:
     19        (WebCore::SVGFilterElement::buildFilter):
     20        (WebCore::SVGFilterElement::canvasResource):
     21        * svg/SVGFilterElement.h:
     22        * svg/SVGFilterPrimitiveStandardAttributes.cpp:
     23        (WebCore::SVGFilterPrimitiveStandardAttributes::setStandardAttributes):
     24        * svg/graphics/SVGResourceFilter.cpp:
     25        (WebCore::SVGResourceFilter::SVGResourceFilter):
     26        (WebCore::SVGResourceFilter::~SVGResourceFilter):
     27        (WebCore::SVGResourceFilter::addFilterEffect):
     28        (WebCore::SVGResourceFilter::prepareFilter):
     29        * svg/graphics/SVGResourceFilter.h:
     30        (WebCore::SVGResourceFilter::create):
     31        * svg/graphics/filters/SVGFilter.cpp:
     32        (WebCore::SVGFilter::SVGFilter):
     33        (WebCore::SVGFilter::calculateEffectSubRegion):
     34        (WebCore::SVGFilter::create):
     35        * svg/graphics/filters/SVGFilter.h:
     36
    1372009-10-14  Chris Marrin  <cmarrin@apple.com>
    238
  • trunk/WebCore/platform/graphics/filters/FilterEffect.cpp

    r49402 r49582  
    2626
    2727FilterEffect::FilterEffect()
    28     : m_xBBoxMode(false)
    29     , m_yBBoxMode(false)
    30     , m_widthBBoxMode(false)
    31     , m_heightBBoxMode(false)
    32     , m_hasX(false)
     28    : m_hasX(false)
    3329    , m_hasY(false)
    3430    , m_hasWidth(false)
  • trunk/WebCore/platform/graphics/filters/FilterEffect.h

    r49402 r49582  
    3838    public:
    3939        virtual ~FilterEffect();
    40 
    41         bool xBoundingBoxMode() const { return m_xBBoxMode; }
    42         void setXBoundingBoxMode(bool bboxMode) { m_xBBoxMode = bboxMode; }
    43 
    44         bool yBoundingBoxMode() const { return m_yBBoxMode; }
    45         void setYBoundingBoxMode(bool bboxMode) { m_yBBoxMode = bboxMode; }
    46 
    47         bool widthBoundingBoxMode() const { return m_widthBBoxMode; }
    48         void setWidthBoundingBoxMode(bool bboxMode) { m_widthBBoxMode = bboxMode; }
    49 
    50         bool heightBoundingBoxMode() const { return m_heightBBoxMode; }
    51         void setHeightBoundingBoxMode(bool bboxMode) { m_heightBBoxMode = bboxMode; }
    5240
    5341        void setUnionOfChildEffectSubregions(const FloatRect& uniteRect) { m_unionOfChildEffectSubregions = uniteRect; }
  • trunk/WebCore/rendering/SVGRenderSupport.cpp

    r46815 r49582  
    221221    SVGResourceFilter* filter = getFilterById(object->document(), object->style()->svgStyle()->filter());
    222222    if (filter)
    223         return filter->filterBBoxForItemBBox(object->objectBoundingBox());
     223        return filter->filterBoundingBox();
    224224#else
    225225    UNUSED_PARAM(object);
  • trunk/WebCore/svg/SVGFilterElement.cpp

    r49306 r49582  
    33    Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org>
    44    Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
     5    Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
    56
    67    This file is part of the KDE project
     
    103104}
    104105
    105 SVGResource* SVGFilterElement::canvasResource()
     106void SVGFilterElement::buildFilter(const FloatRect& targetRect) const
    106107{
    107     if (!attached())
    108         return 0;
     108    bool filterBBoxMode = filterUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
     109    bool primitiveBBoxMode = primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
    109110
    110     if (!m_filter)
    111         m_filter = new SVGResourceFilter();
     111    FloatRect filterBBox;
     112    if (filterBBoxMode)
     113        filterBBox = FloatRect(x().valueAsPercentage(),
     114                               y().valueAsPercentage(),
     115                               width().valueAsPercentage(),
     116                               height().valueAsPercentage());
     117    else
     118        filterBBox = FloatRect(x().value(this),
     119                               y().value(this),
     120                               width().value(this),
     121                               height().value(this));
    112122
    113     bool filterBBoxMode = filterUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
     123    FloatRect filterRect = filterBBox;
     124    if (filterBBoxMode)
     125        filterRect = FloatRect(targetRect.x() + filterRect.x() * targetRect.width(),
     126                               targetRect.y() + filterRect.y() * targetRect.height(),
     127                               filterRect.width() * targetRect.width(),
     128                               filterRect.height() * targetRect.height());
     129
     130    m_filter->setFilterBoundingBox(filterRect);
     131    m_filter->setFilterRect(filterBBox);
     132    m_filter->setEffectBoundingBoxMode(primitiveBBoxMode);
    114133    m_filter->setFilterBoundingBoxMode(filterBBoxMode);
    115134
    116     float _x, _y, _width, _height;
    117 
    118     if (filterBBoxMode) {
    119         _x = x().valueAsPercentage();
    120         _y = y().valueAsPercentage();
    121         _width = width().valueAsPercentage();
    122         _height = height().valueAsPercentage();
    123     } else {
    124         m_filter->setXBoundingBoxMode(x().unitType() == LengthTypePercentage);
    125         m_filter->setYBoundingBoxMode(y().unitType() == LengthTypePercentage);
    126 
    127         _x = x().value(this);
    128         _y = y().value(this);
    129         _width = width().value(this);
    130         _height = height().value(this);
    131     }
    132 
    133     m_filter->setFilterRect(FloatRect(_x, _y, _width, _height));
    134 
    135     bool primitiveBBoxMode = primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
    136     m_filter->setEffectBoundingBoxMode(primitiveBBoxMode);
    137 
     135    // Add effects to the filter
    138136    m_filter->builder()->clearEffects();
    139137    for (Node* n = firstChild(); n != 0; n = n->nextSibling()) {
     
    150148        }
    151149    }
     150}
    152151
     152SVGResource* SVGFilterElement::canvasResource()
     153{
     154    if (!attached())
     155        return 0;
     156
     157    if (!m_filter)
     158        m_filter = SVGResourceFilter::create(this);
    153159    return m_filter.get();
    154160}
     
    156162}
    157163
    158 #endif // ENABLE(SVG)
    159 
    160 // vim:ts=4:noet
     164#endif // ENABLE(SVG) && ENABLE(FILTERS)
  • trunk/WebCore/svg/SVGFilterElement.h

    r49306 r49582  
    7373                                       ExternalResourcesRequired, externalResourcesRequired)
    7474
    75         RefPtr<SVGResourceFilter> m_filter;
     75        mutable RefPtr<SVGResourceFilter> m_filter;
     76
     77    private:
     78        friend class SVGResourceFilter;
     79        void buildFilter(const FloatRect& targetRect) const;
    7680    };
    7781
  • trunk/WebCore/svg/SVGFilterPrimitiveStandardAttributes.cpp

    r44655 r49582  
    22    Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
    33                  2004, 2005, 2006 Rob Buis <buis@kde.org>
    4 
    5     This file is part of the KDE project
     4                  2009 Dirk Schulze <krit@webkit.org>
    65
    76    This library is free software; you can redistribute it and/or
     
    7877    ASSERT(resourceFilter);
    7978
    80     float _x, _y, _width, _height;
    81 
    8279    if (this->hasAttribute(SVGNames::xAttr))
    8380        filterEffect->setHasX(true);
     
    8986        filterEffect->setHasHeight(true);
    9087
    91     if (resourceFilter->effectBoundingBoxMode()) {
    92         _x = x().valueAsPercentage();
    93         _y = y().valueAsPercentage();
    94         _width = width().valueAsPercentage();
    95         _height = height().valueAsPercentage();
    96     } else {
    97         // We need to resolve any percentages in filter rect space.
    98         if (x().unitType() == LengthTypePercentage) {
    99             filterEffect->setXBoundingBoxMode(true);
    100             _x = x().valueAsPercentage();
    101         } else {
    102             filterEffect->setXBoundingBoxMode(false);
    103             _x = x().value(this);
    104         }
     88    FloatRect effectBBox;
     89    if (resourceFilter->effectBoundingBoxMode())
     90        effectBBox = FloatRect(x().valueAsPercentage(),
     91                               y().valueAsPercentage(),
     92                               width().valueAsPercentage(),
     93                               height().valueAsPercentage());
     94    else
     95        effectBBox = FloatRect(x().value(this),
     96                               y().value(this),
     97                               width().value(this),
     98                               height().value(this));
    10599
    106         if (y().unitType() == LengthTypePercentage) {
    107             filterEffect->setYBoundingBoxMode(true);
    108             _y = y().valueAsPercentage();
    109         } else {
    110             filterEffect->setYBoundingBoxMode(false);
    111             _y = y().value(this);
    112         }
    113 
    114         if (width().unitType() == LengthTypePercentage) {
    115             filterEffect->setWidthBoundingBoxMode(true);
    116             _width = width().valueAsPercentage();
    117         } else {
    118             filterEffect->setWidthBoundingBoxMode(false);
    119             _width = width().value(this);
    120         }
    121 
    122         if (height().unitType() == LengthTypePercentage) {
    123             filterEffect->setHeightBoundingBoxMode(true);
    124             _height = height().valueAsPercentage();
    125         } else {
    126             filterEffect->setHeightBoundingBoxMode(false);
    127             _height = height().value(this);
    128         }
    129     }
    130 
    131     filterEffect->setSubRegion(FloatRect(_x, _y, _width, _height));
     100    filterEffect->setSubRegion(effectBBox);
    132101}
    133102
  • trunk/WebCore/svg/graphics/SVGResourceFilter.cpp

    r46956 r49582  
    3232#include "SVGFilter.h"
    3333#include "SVGFilterBuilder.h"
     34#include "SVGFilterElement.h"
    3435#include "SVGRenderTreeAsText.h"
    3536#include "SVGFilterPrimitiveStandardAttributes.h"
     
    3738namespace WebCore {
    3839
    39 SVGResourceFilter::SVGResourceFilter()
    40     : m_filterBBoxMode(false)
     40SVGResourceFilter::SVGResourceFilter(const SVGFilterElement* ownerElement)
     41    : SVGResource()
     42    , m_ownerElement(ownerElement)
     43    , m_filterBBoxMode(false)
    4144    , m_effectBBoxMode(false)
    42     , m_xBBoxMode(false)
    43     , m_yBBoxMode(false)
    4445    , m_savedContext(0)
    4546    , m_sourceGraphicBuffer(0)
    4647{
    4748    m_filterBuilder.set(new SVGFilterBuilder());
     49}
     50
     51SVGResourceFilter::~SVGResourceFilter()
     52{
    4853}
    4954
     
    5459}
    5560
    56 FloatRect SVGResourceFilter::filterBBoxForItemBBox(const FloatRect& itemBBox) const
    57 {
    58     FloatRect filterBBox = filterRect();
    59 
    60     if (filterBoundingBoxMode())
    61         filterBBox = FloatRect(itemBBox.x() + filterBBox.x() * itemBBox.width(),
    62                                itemBBox.y() + filterBBox.y() * itemBBox.height(),
    63                                filterBBox.width() * itemBBox.width(),
    64                                filterBBox.height() * itemBBox.height());
    65 
    66     return filterBBox;
    67 }
    68 
    6961void SVGResourceFilter::prepareFilter(GraphicsContext*& context, const RenderObject* object)
    7062{
    71     m_itemBBox = object->objectBoundingBox();
    72     m_filterBBox = filterBBoxForItemBBox(m_itemBBox);
     63    FloatRect targetRect = object->objectBoundingBox();
     64    m_ownerElement->buildFilter(targetRect);
    7365
    7466    // clip sourceImage to filterRegion
    75     FloatRect clippedSourceRect = m_itemBBox;
     67    FloatRect clippedSourceRect = targetRect;
    7668    clippedSourceRect.intersect(m_filterBBox);
    7769
    7870    // prepare Filters
    79     m_filter = SVGFilter::create(m_itemBBox, m_filterBBox, m_effectBBoxMode, m_filterBBoxMode);
     71    m_filter = SVGFilter::create(targetRect, m_filterBBox, m_effectBBoxMode);
    8072
    8173    FilterEffect* lastEffect = m_filterBuilder->lastEffect();
     
    9284
    9385    GraphicsContext* sourceGraphicContext = sourceGraphic->context();
    94     sourceGraphicContext->translate(-m_itemBBox.x(), -m_itemBBox.y());
    95     sourceGraphicContext->clearRect(FloatRect(FloatPoint(), m_itemBBox.size()));
     86    sourceGraphicContext->translate(-targetRect.x(), -targetRect.y());
     87    sourceGraphicContext->clearRect(FloatRect(FloatPoint(), targetRect.size()));
    9688    m_sourceGraphicBuffer.set(sourceGraphic.release());
    9789    m_savedContext = context;
  • trunk/WebCore/svg/graphics/SVGResourceFilter.h

    r44655 r49582  
    4444class GraphicsContext;
    4545class SVGFilterBuilder;
     46class SVGFilterElement;
    4647class SVGFilterPrimitiveStandardAttributes;
    4748
    4849class SVGResourceFilter : public SVGResource {
    4950public:
    50     SVGResourceFilter();
     51    static PassRefPtr<SVGResourceFilter> create(const SVGFilterElement* ownerElement) { return adoptRef(new SVGResourceFilter(ownerElement)); }
     52    virtual ~SVGResourceFilter();
    5153   
    5254    virtual SVGResourceType resourceType() const { return FilterResourceType; }
     
    5860    void setEffectBoundingBoxMode(bool bboxMode) { m_effectBBoxMode = bboxMode; }
    5961
    60     bool xBoundingBoxMode() const { return m_xBBoxMode; }
    61     void setXBoundingBoxMode(bool bboxMode) { m_xBBoxMode = bboxMode; }
    62 
    63     bool yBoundingBoxMode() const { return m_yBBoxMode; }
    64     void setYBoundingBoxMode(bool bboxMode) { m_yBBoxMode = bboxMode; }
    65 
    6662    FloatRect filterRect() const { return m_filterRect; }
    6763    void setFilterRect(const FloatRect& rect) { m_filterRect = rect; }
     
    6965    FloatRect filterBoundingBox() { return m_filterBBox; }
    7066    void setFilterBoundingBox(const FloatRect& rect) { m_filterBBox = rect; }
    71 
    72     FloatRect itemBoundingBox() { return m_itemBBox; }
    73     void setItemBoundingBox(const FloatRect& rect) { m_itemBBox = rect; }
    74 
    75     FloatRect filterBBoxForItemBBox(const FloatRect& itemBBox) const;
    76 
    77     virtual TextStream& externalRepresentation(TextStream&) const;
    7867
    7968    void prepareFilter(GraphicsContext*&, const RenderObject*);
     
    8372
    8473    SVGFilterBuilder* builder() { return m_filterBuilder.get(); }
     74
     75    virtual TextStream& externalRepresentation(TextStream&) const;
    8576   
    8677private:
     78    SVGResourceFilter(const SVGFilterElement*);
     79
     80    const SVGFilterElement* m_ownerElement;
    8781
    8882    bool m_filterBBoxMode : 1;
    8983    bool m_effectBBoxMode : 1;
    9084
    91     bool m_xBBoxMode : 1;
    92     bool m_yBBoxMode : 1;
    93 
    9485    FloatRect m_filterRect;
    95 
    9686    FloatRect m_filterBBox;
    97     FloatRect m_itemBBox;
    9887
    9988    OwnPtr<SVGFilterBuilder> m_filterBuilder;
  • trunk/WebCore/svg/graphics/filters/SVGFilter.cpp

    r44655 r49582  
    2525namespace WebCore {
    2626
    27 SVGFilter::SVGFilter(const FloatRect& itemBox, const FloatRect& filterRect, bool effectBBoxMode, bool filterBBoxMode)
     27SVGFilter::SVGFilter(const FloatRect& itemBox, const FloatRect& filterRect, bool effectBBoxMode)
    2828    : Filter()
    2929    , m_itemBox(itemBox)
    3030    , m_filterRect(filterRect)
    3131    , m_effectBBoxMode(effectBBoxMode)
    32     , m_filterBBoxMode(filterBBoxMode)
    3332{
    3433}
     
    3837    FloatRect subRegionBBox = effect->subRegion();
    3938    FloatRect useBBox = effect->unionOfChildEffectSubregions();
    40 
    4139    FloatRect newSubRegion = subRegionBBox;
    4240
     
    5654            newSubRegion.setHeight(subRegionBBox.height() * m_itemBox.height());
    5755    } else {
    58         if (effect->xBoundingBoxMode())
    59             newSubRegion.setX(useBBox.x() + subRegionBBox.x() * useBBox.width());
     56        if (!effect->hasX())
     57            newSubRegion.setX(useBBox.x());
    6058
    61         if (effect->yBoundingBoxMode())
    62             newSubRegion.setY(useBBox.y() + subRegionBBox.y() * useBBox.height());
     59        if (!effect->hasY())
     60            newSubRegion.setY(useBBox.y());
    6361
    64         if (effect->widthBoundingBoxMode())
    65             newSubRegion.setWidth(subRegionBBox.width() * useBBox.width());
     62        if (!effect->hasWidth())
     63            newSubRegion.setWidth(useBBox.width());
    6664
    67         if (effect->heightBoundingBoxMode())
    68             newSubRegion.setHeight(subRegionBBox.height() * useBBox.height());
     65        if (!effect->hasHeight())
     66            newSubRegion.setHeight(useBBox.height());
    6967    }
    7068
     
    7573}
    7674
    77 PassRefPtr<SVGFilter> SVGFilter::create(const FloatRect& itemBox, const FloatRect& filterRect, bool effectBBoxMode, bool filterBBoxMode)
     75PassRefPtr<SVGFilter> SVGFilter::create(const FloatRect& itemBox, const FloatRect& filterRect, bool effectBBoxMode)
    7876{
    79     return adoptRef(new SVGFilter(itemBox, filterRect, effectBBoxMode, filterBBoxMode));
     77    return adoptRef(new SVGFilter(itemBox, filterRect, effectBBoxMode));
    8078}
    8179
  • trunk/WebCore/svg/graphics/filters/SVGFilter.h

    r44655 r49582  
    3434    class SVGFilter : public Filter {
    3535    public:
    36         static PassRefPtr<SVGFilter> create(const FloatRect&, const FloatRect&, bool, bool);
     36        static PassRefPtr<SVGFilter> create(const FloatRect&, const FloatRect&, bool);
    3737
    3838        bool effectBoundingBoxMode() { return m_effectBBoxMode; }
     
    4343
    4444    private:
    45         SVGFilter(const FloatRect& itemBox, const FloatRect& filterRect, bool itemBBoxMode, bool filterBBoxMode);
     45        SVGFilter(const FloatRect& itemBox, const FloatRect& filterRect, bool effectBBoxMode);
    4646
    4747        FloatRect m_itemBox;
    4848        FloatRect m_filterRect;
    4949        bool m_effectBBoxMode;
    50         bool m_filterBBoxMode;
    5150    };
    5251
Note: See TracChangeset for help on using the changeset viewer.