Changeset 51310 in webkit


Ignore:
Timestamp:
Nov 23, 2009, 8:15:24 AM (16 years ago)
Author:
krit@webkit.org
Message:

2009-11-23 Dirk Schulze <krit@webkit.org>

Reviewed by Nikolas Zimmermann.

This is the implementation of the filterRes attribute. It
helps the SVG developer to set the quality of a filter by
giving the width or height of filter.
This patch also sets the filter resolution to lower values
if a intermediate ImageBuffer size is bigger than the given
maximal size.
The maximal size is set to 5000x5000 by default. This is a
subjectiv decission. Everthing greater than this values gets
sensible slower. Values of 10000x10000 crashed on WebKitGtk.
For mobil devices a maximum size of 100x100 or 200x200 seems
to be reasonable.
The important fact on filter resolution is, that the output
size is still the size given by the <filter> element.

Tests: svg/filters/big-sized-filter-2.svg

svg/filters/big-sized-filter.svg
svg/filters/filterRes.svg

  • platform/graphics/FloatRect.cpp: (WebCore::FloatRect::scale): Add the abbility to scale a rect by x and y.
  • platform/graphics/FloatRect.h: (WebCore::FloatRect::scale): Add the abbility to scale a rect by x and y.
  • platform/graphics/cairo/GraphicsContextCairo.cpp: (WebCore::GraphicsContext::createPlatformShadow): Use scaledSubRegion for calculation.
  • platform/graphics/filters/FEBlend.cpp: (WebCore::FEBlend::apply): Use scaledSubRegion for effect intern calculations.
  • platform/graphics/filters/FEColorMatrix.cpp: (WebCore::FEColorMatrix::apply): Use scaledSubRegion for effect intern calculations.
  • platform/graphics/filters/FEComponentTransfer.cpp: (WebCore::FEComponentTransfer::apply): Use scaledSubRegion for effect intern calculations.
  • platform/graphics/filters/FEComposite.cpp: (WebCore::FEComposite::apply): Use scaledSubRegion for effect intern calculations.
  • platform/graphics/filters/FEGaussianBlur.cpp: (WebCore::FEGaussianBlur::apply): Use scaledSubRegion for effect intern calculations.
  • platform/graphics/filters/Filter.h: Add the abbility to change the quality of a filter output. (WebCore::Filter::filterResolution): (WebCore::Filter::setFilterResolution): (WebCore::Filter::calculateEffectSubRegion): Calculates the correct subRegion as well as the scaledSubRegion. It also searches for the biggest effect size. We have to change the filter resolution, if one intermediate ImageBuffer size doesn't fit in the maximal image size.
  • platform/graphics/filters/FilterEffect.cpp: (WebCore::FilterEffect::calculateDrawingIntRect): Use scaledSubRegion to get the right part of a previous effect result. (WebCore::FilterEffect::calculateDrawingRect): Use scaledSubRegion to get the right part of a previous effect result. (WebCore::FilterEffect::getEffectContext): Use scaledSubRegion to create a new intermediate ImageBuffer for the result of the current effect.
  • platform/graphics/filters/FilterEffect.h: (WebCore::FilterEffect::scaledSubRegion): The scaled subRegion of a the filter effect. (WebCore::FilterEffect::setScaledSubRegion): (WebCore::FilterEffect::effectBoundaries): The original values of the EffectElement for a second subRegion calculation. (WebCore::FilterEffect::setEffectBoundaries):
  • platform/graphics/filters/ImageBufferFilter.cpp: (WebCore::ImageBufferFilter::ImageBufferFilter): Set the scale factor to one.
  • platform/graphics/filters/ImageBufferFilter.h: (WebCore::ImageBufferFilter::maxImageSize): (WebCore::ImageBufferFilter::calculateEffectSubRegion):
  • platform/graphics/filters/SourceAlpha.cpp: (WebCore::SourceAlpha::calculateEffectRect): Use scaledSubRegion for effect intern calculations.
  • platform/graphics/filters/SourceGraphic.cpp: (WebCore::SourceGraphic::calculateEffectRect): Use scaledSubRegion for effect intern calculations.
  • svg/SVGFilterElement.cpp: (WebCore::SVGFilterElement::parseMappedAttribute): Parse filterRes attribute. (WebCore::SVGFilterElement::buildFilter): Give SVGResourceFilter the current filterResolution.
  • svg/SVGFilterPrimitiveStandardAttributes.cpp: (WebCore::SVGFilterPrimitiveStandardAttributes::setStandardAttributes): Save values to effectBoundaries of the filter effect
  • svg/graphics/SVGResourceFilter.cpp: (WebCore::SVGResourceFilter::SVGResourceFilter): (WebCore::shouldProcessFilter): Return signal if a neccessary value is zero. (WebCore::SVGResourceFilter::fitsInMaximumImageSize): Checks if the given size fits into the maximal image size, modifys scale factors if not and return a bool: fits. (WebCore::SVGResourceFilter::prepareFilter): Scale the SourceImage to filterResolution (given by FilterElement or calculated on to big image sizes). Set the scale level to SVGFilter. (WebCore::SVGResourceFilter::applyFilter): Don't apply filters if shouldProcessFilter is wrong.
  • svg/graphics/SVGResourceFilter.h: (WebCore::SVGResourceFilter::setFilterResolution): FilterResolution of FilterElement. (WebCore::SVGResourceFilter::setHasFilterResolution): Does FilterElement provides a FilterResolution? (WebCore::SVGResourceFilter::scaleX): Current scale factor for horizontal. (WebCore::SVGResourceFilter::scaleY): Current scale factor for vertical.
  • svg/graphics/filters/SVGFEDisplacementMap.cpp: (WebCore::FEDisplacementMap::apply): Use scaledSubRegion for effect intern calculations. Kernel values are scaled to current filter resolution too.
  • svg/graphics/filters/SVGFEFlood.cpp: (WebCore::FEFlood::apply): Use scaledSubRegion for effect intern calculations.
  • svg/graphics/filters/SVGFEMerge.cpp: (WebCore::FEMerge::apply): Use scaledSubRegion for effect intern calculations. Kernel values are scaled to current filter resolution too.
  • svg/graphics/filters/SVGFEMorphology.cpp: (WebCore::FEMorphology::apply): Use scaledSubRegion for effect intern calculations. Kernel values are scaled to current filter resolution too.
  • svg/graphics/filters/SVGFEOffset.cpp: (WebCore::FEOffset::apply): Use scaledSubRegion for effect intern calculations.
  • svg/graphics/filters/SVGFETile.cpp: (WebCore::FETile::apply): Use scaledSubRegion for effect intern calculations.
  • svg/graphics/filters/SVGFilter.cpp: (WebCore::SVGFilter::calculateEffectSubRegion): Calculate subRegion for LayoutTests, scaledSubRegion according to the current filterResolution and get the maximal image size.
  • svg/graphics/filters/SVGFilter.h: (WebCore::SVGFilter::effectBoundingBoxMode): Original values of the FilterElement. (WebCore::SVGFilter::filterRegion): Use virtual for clarification. (WebCore::SVGFilter::sourceImageRect): Use virtual for clarification. (WebCore::SVGFilter::maxImageSize): Get the maximal image size.
Location:
trunk/WebCore
Files:
28 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r51306 r51310  
     12009-11-23  Dirk Schulze  <krit@webkit.org>
     2
     3        Reviewed by Nikolas Zimmermann.
     4
     5        This is the implementation of the filterRes attribute. It
     6        helps the SVG developer to set the quality of a filter by
     7        giving the width or height of filter.
     8        This patch also sets the filter resolution to lower values
     9        if a intermediate ImageBuffer size is bigger than the given
     10        maximal size.
     11        The maximal size is set to 5000x5000 by default. This is a
     12        subjectiv decission. Everthing greater than this values gets
     13        sensible slower. Values of 10000x10000 crashed on WebKitGtk.
     14        For mobil devices a maximum size of 100x100 or 200x200 seems
     15        to be reasonable.
     16        The important fact on filter resolution is, that the output
     17        size is still the size given by the <filter> element.
     18
     19        Tests: svg/filters/big-sized-filter-2.svg
     20               svg/filters/big-sized-filter.svg
     21               svg/filters/filterRes.svg
     22
     23        * platform/graphics/FloatRect.cpp:
     24        (WebCore::FloatRect::scale): Add the abbility to scale a rect by x and y.
     25        * platform/graphics/FloatRect.h:
     26        (WebCore::FloatRect::scale): Add the abbility to scale a rect by x and y.
     27        * platform/graphics/cairo/GraphicsContextCairo.cpp:
     28        (WebCore::GraphicsContext::createPlatformShadow): Use scaledSubRegion for
     29        calculation.
     30        * platform/graphics/filters/FEBlend.cpp:
     31        (WebCore::FEBlend::apply): Use scaledSubRegion for effect intern calculations.
     32        * platform/graphics/filters/FEColorMatrix.cpp:
     33        (WebCore::FEColorMatrix::apply): Use scaledSubRegion for effect intern calculations.
     34        * platform/graphics/filters/FEComponentTransfer.cpp:
     35        (WebCore::FEComponentTransfer::apply): Use scaledSubRegion for effect intern
     36        calculations.
     37        * platform/graphics/filters/FEComposite.cpp:
     38        (WebCore::FEComposite::apply): Use scaledSubRegion for effect intern calculations.
     39        * platform/graphics/filters/FEGaussianBlur.cpp:
     40        (WebCore::FEGaussianBlur::apply): Use scaledSubRegion for effect intern calculations.
     41        * platform/graphics/filters/Filter.h: Add the abbility to change the quality
     42        of a filter output.
     43        (WebCore::Filter::filterResolution):
     44        (WebCore::Filter::setFilterResolution):
     45        (WebCore::Filter::calculateEffectSubRegion): Calculates the correct subRegion
     46        as well as the scaledSubRegion. It also searches for the biggest effect size.
     47        We have to change the filter resolution, if one intermediate ImageBuffer size
     48        doesn't fit in the maximal image size.
     49        * platform/graphics/filters/FilterEffect.cpp:
     50        (WebCore::FilterEffect::calculateDrawingIntRect): Use scaledSubRegion to get
     51        the right part of a previous effect result.
     52        (WebCore::FilterEffect::calculateDrawingRect): Use scaledSubRegion to get
     53        the right part of a previous effect result.
     54        (WebCore::FilterEffect::getEffectContext): Use scaledSubRegion to create
     55        a new intermediate ImageBuffer for the result of the current effect.
     56        * platform/graphics/filters/FilterEffect.h:
     57        (WebCore::FilterEffect::scaledSubRegion): The scaled subRegion of a the
     58        filter effect.
     59        (WebCore::FilterEffect::setScaledSubRegion):
     60        (WebCore::FilterEffect::effectBoundaries): The original values of the
     61        EffectElement for a second subRegion calculation.
     62        (WebCore::FilterEffect::setEffectBoundaries):
     63        * platform/graphics/filters/ImageBufferFilter.cpp:
     64        (WebCore::ImageBufferFilter::ImageBufferFilter): Set the scale factor to one.
     65        * platform/graphics/filters/ImageBufferFilter.h:
     66        (WebCore::ImageBufferFilter::maxImageSize):
     67        (WebCore::ImageBufferFilter::calculateEffectSubRegion):
     68        * platform/graphics/filters/SourceAlpha.cpp:
     69        (WebCore::SourceAlpha::calculateEffectRect): Use scaledSubRegion for effect
     70        intern calculations.
     71        * platform/graphics/filters/SourceGraphic.cpp:
     72        (WebCore::SourceGraphic::calculateEffectRect): Use scaledSubRegion for effect
     73        intern calculations.
     74        * svg/SVGFilterElement.cpp:
     75        (WebCore::SVGFilterElement::parseMappedAttribute): Parse filterRes attribute.
     76        (WebCore::SVGFilterElement::buildFilter): Give SVGResourceFilter the current
     77        filterResolution.
     78        * svg/SVGFilterPrimitiveStandardAttributes.cpp:
     79        (WebCore::SVGFilterPrimitiveStandardAttributes::setStandardAttributes): Save
     80        values to effectBoundaries of the filter effect
     81        * svg/graphics/SVGResourceFilter.cpp:
     82        (WebCore::SVGResourceFilter::SVGResourceFilter):
     83        (WebCore::shouldProcessFilter): Return signal if a neccessary value is zero.
     84        (WebCore::SVGResourceFilter::fitsInMaximumImageSize): Checks if the given size
     85        fits into the maximal image size, modifys scale factors if not and return a
     86        bool: fits.
     87        (WebCore::SVGResourceFilter::prepareFilter): Scale the SourceImage to
     88        filterResolution (given by FilterElement or calculated on to big image sizes).
     89        Set the scale level to SVGFilter.
     90        (WebCore::SVGResourceFilter::applyFilter): Don't apply filters if shouldProcessFilter
     91        is wrong.
     92        * svg/graphics/SVGResourceFilter.h:
     93        (WebCore::SVGResourceFilter::setFilterResolution): FilterResolution of FilterElement.
     94        (WebCore::SVGResourceFilter::setHasFilterResolution): Does FilterElement provides
     95        a FilterResolution?
     96        (WebCore::SVGResourceFilter::scaleX): Current scale factor for horizontal.
     97        (WebCore::SVGResourceFilter::scaleY): Current scale factor for vertical.
     98        * svg/graphics/filters/SVGFEDisplacementMap.cpp:
     99        (WebCore::FEDisplacementMap::apply): Use scaledSubRegion for effect intern calculations.
     100        Kernel values are scaled to current filter resolution too.
     101        * svg/graphics/filters/SVGFEFlood.cpp:
     102        (WebCore::FEFlood::apply): Use scaledSubRegion for effect intern calculations.
     103        * svg/graphics/filters/SVGFEMerge.cpp:
     104        (WebCore::FEMerge::apply): Use scaledSubRegion for effect intern calculations.
     105        Kernel values are scaled to current filter resolution too.
     106        * svg/graphics/filters/SVGFEMorphology.cpp:
     107        (WebCore::FEMorphology::apply): Use scaledSubRegion for effect intern calculations.
     108        Kernel values are scaled to current filter resolution too.
     109        * svg/graphics/filters/SVGFEOffset.cpp:
     110        (WebCore::FEOffset::apply): Use scaledSubRegion for effect intern calculations.
     111        * svg/graphics/filters/SVGFETile.cpp:
     112        (WebCore::FETile::apply): Use scaledSubRegion for effect intern calculations.
     113        * svg/graphics/filters/SVGFilter.cpp:
     114        (WebCore::SVGFilter::calculateEffectSubRegion): Calculate subRegion for LayoutTests,
     115        scaledSubRegion according to the current filterResolution and get the maximal image size.
     116        * svg/graphics/filters/SVGFilter.h:
     117        (WebCore::SVGFilter::effectBoundingBoxMode): Original values of the FilterElement.
     118        (WebCore::SVGFilter::filterRegion): Use virtual for clarification.
     119        (WebCore::SVGFilter::sourceImageRect): Use virtual for clarification.
     120        (WebCore::SVGFilter::maxImageSize): Get the maximal image size.
     121
    11222009-11-23  Simon Hausmann  <simon.hausmann@nokia.com>
    2123
  • trunk/WebCore/platform/graphics/FloatRect.cpp

    r39538 r51310  
    103103}
    104104
    105 void FloatRect::scale(float s)
     105void FloatRect::scale(float sx, float sy)
    106106{
    107     m_location.setX(x() * s);
    108     m_location.setY(y() * s);
    109     m_size.setWidth(width() * s);
    110     m_size.setHeight(height() * s);
     107    m_location.setX(x() * sx);
     108    m_location.setY(y() * sy);
     109    m_size.setWidth(width() * sx);
     110    m_size.setHeight(height() * sy);
    111111}
    112112
  • trunk/WebCore/platform/graphics/FloatRect.h

    r48469 r51310  
    121121    }
    122122    void inflate(float d) { inflateX(d); inflateY(d); }
    123     void scale(float s);
     123    void scale(float s) { scale(s, s); }
     124    void scale(float sx, float sy);
    124125
    125126#if PLATFORM(CG)
  • trunk/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp

    r51161 r51310  
    861861    filter->setSourceImage(buffer.release());
    862862    RefPtr<FilterEffect> source = SourceGraphic::create();
    863     source->setSubRegion(FloatRect(FloatPoint(), shadowRect.size()));
     863    source->setScaledSubRegion(FloatRect(FloatPoint(), shadowRect.size()));
    864864    source->setIsAlphaImage(true);
    865865    RefPtr<FilterEffect> blur = FEGaussianBlur::create(source.get(), kernelSize, kernelSize);
    866     blur->setSubRegion(FloatRect(FloatPoint(), shadowRect.size()));
     866    blur->setScaledSubRegion(FloatRect(FloatPoint(), shadowRect.size()));
    867867    blur->apply(filter.get());
    868868
  • trunk/WebCore/platform/graphics/filters/FEBlend.cpp

    r47456 r51310  
    112112        return;
    113113
    114     IntRect effectADrawingRect = calculateDrawingIntRect(m_in->subRegion());
     114    IntRect effectADrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
    115115    RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
    116116
    117     IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->subRegion());
     117    IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->scaledSubRegion());
    118118    RefPtr<CanvasPixelArray> srcPixelArrayB(m_in2->resultImage()->getPremultipliedImageData(effectBDrawingRect)->data());
    119119
  • trunk/WebCore/platform/graphics/filters/FEColorMatrix.cpp

    r51240 r51310  
    165165        return;
    166166
    167     filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->subRegion()));
     167    filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
    168168
    169169    IntRect imageRect(IntPoint(), resultImage()->size());
  • trunk/WebCore/platform/graphics/filters/FEComponentTransfer.cpp

    r50016 r51310  
    166166        (*callEffect[transferFunction[channel].type])(tables[channel], transferFunction[channel]);
    167167
    168     IntRect drawingRect = calculateDrawingIntRect(m_in->subRegion());
     168    IntRect drawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
    169169    RefPtr<ImageData> imageData(m_in->resultImage()->getUnmultipliedImageData(drawingRect));
    170170    CanvasPixelArray* srcPixelArray(imageData->data());
  • trunk/WebCore/platform/graphics/filters/FEComposite.cpp

    r51240 r51310  
    134134    switch (m_type) {
    135135    case FECOMPOSITE_OPERATOR_OVER:
    136         filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->subRegion()));
    137         filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->subRegion()));
     136        filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
     137        filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
    138138        break;
    139139    case FECOMPOSITE_OPERATOR_IN:
    140140        filterContext->save();
    141         filterContext->clipToImageBuffer(calculateDrawingRect(m_in2->subRegion()), m_in2->resultImage());
    142         filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->subRegion()));
     141        filterContext->clipToImageBuffer(calculateDrawingRect(m_in2->scaledSubRegion()), m_in2->resultImage());
     142        filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
    143143        filterContext->restore();
    144144        break;
    145145    case FECOMPOSITE_OPERATOR_OUT:
    146         filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->subRegion()));
    147         filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->subRegion()), srcRect, CompositeDestinationOut);
     146        filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
     147        filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()), srcRect, CompositeDestinationOut);
    148148        break;
    149149    case FECOMPOSITE_OPERATOR_ATOP:
    150         filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->subRegion()));
    151         filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->subRegion()), srcRect, CompositeSourceAtop);
     150        filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
     151        filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeSourceAtop);
    152152        break;
    153153    case FECOMPOSITE_OPERATOR_XOR:
    154         filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->subRegion()));
    155         filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->subRegion()), srcRect, CompositeXOR);
     154        filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
     155        filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeXOR);
    156156        break;
    157157    case FECOMPOSITE_OPERATOR_ARITHMETIC: {
    158         IntRect effectADrawingRect = calculateDrawingIntRect(m_in->subRegion());
     158        IntRect effectADrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
    159159        RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
    160160
    161         IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->subRegion());
     161        IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->scaledSubRegion());
    162162        RefPtr<ImageData> imageData(m_in2->resultImage()->getPremultipliedImageData(effectBDrawingRect));
    163163        CanvasPixelArray* srcPixelArrayB(imageData->data());
  • trunk/WebCore/platform/graphics/filters/FEGaussianBlur.cpp

    r50118 r51310  
    3232#include <math.h>
    3333#include <wtf/MathExtras.h>
     34
     35using std::max;
    3436
    3537namespace WebCore {
     
    112114        return;
    113115
    114     unsigned sdx = static_cast<unsigned>(floor(m_x * 3 * sqrt(2 * piDouble) / 4.f + 0.5f));
    115     unsigned sdy = static_cast<unsigned>(floor(m_y * 3 * sqrt(2 * piDouble) / 4.f + 0.5f));
     116    unsigned sdx = static_cast<unsigned>(floor(m_x * filter->filterResolution().width() * 3 * sqrt(2 * piDouble) / 4.f + 0.5f));
     117    unsigned sdy = static_cast<unsigned>(floor(m_y * filter->filterResolution().height() * 3 * sqrt(2 * piDouble) / 4.f + 0.5f));
     118    sdx = max(sdx, static_cast<unsigned>(1));
     119    sdy = max(sdy, static_cast<unsigned>(1));
    116120
    117     IntRect effectDrawingRect = calculateDrawingIntRect(m_in->subRegion());
     121    IntRect effectDrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
    118122    RefPtr<ImageData> srcImageData(m_in->resultImage()->getPremultipliedImageData(effectDrawingRect));
    119123    CanvasPixelArray* srcPixelArray(srcImageData->data());
  • trunk/WebCore/platform/graphics/filters/Filter.h

    r50920 r51310  
    2323#if ENABLE(FILTERS)
    2424#include "FloatRect.h"
     25#include "FloatSize.h"
    2526#include "ImageBuffer.h"
    2627#include "StringHash.h"
     
    4142        ImageBuffer* sourceImage() { return m_sourceImage.get(); }
    4243
     44        FloatSize filterResolution() const { return m_filterResolution; }
     45        void setFilterResolution(const FloatSize& filterResolution) { m_filterResolution = filterResolution; }
     46
    4347        virtual FloatRect sourceImageRect() const = 0;
    4448        virtual FloatRect filterRegion() const = 0;
    4549
    4650        // SVG specific
    47         virtual void calculateEffectSubRegion(FilterEffect*) const = 0;
     51        virtual void calculateEffectSubRegion(FilterEffect*) { }
     52
     53        virtual FloatSize maxImageSize() const = 0;
    4854        virtual bool effectBoundingBoxMode() const = 0;
    4955
    5056    private:
    5157        OwnPtr<ImageBuffer> m_sourceImage;
     58        FloatSize m_filterResolution;
    5259    };
    5360
  • trunk/WebCore/platform/graphics/filters/FilterEffect.cpp

    r49582 r51310  
    5959IntRect FilterEffect::calculateDrawingIntRect(const FloatRect& effectRect)
    6060{
    61     IntPoint location = roundedIntPoint(FloatPoint(subRegion().x() - effectRect.x(),
    62                                                    subRegion().y() - effectRect.y()));
     61    IntPoint location = roundedIntPoint(FloatPoint(scaledSubRegion().x() - effectRect.x(),
     62                                                   scaledSubRegion().y() - effectRect.y()));
    6363    return IntRect(location, resultImage()->size());
    6464}
     
    6666FloatRect FilterEffect::calculateDrawingRect(const FloatRect& srcRect)
    6767{
    68     FloatPoint startPoint = FloatPoint(srcRect.x() - subRegion().x(), srcRect.y() - subRegion().y());
     68    FloatPoint startPoint = FloatPoint(srcRect.x() - scaledSubRegion().x(), srcRect.y() - scaledSubRegion().y());
    6969    FloatRect drawingRect = FloatRect(startPoint, srcRect.size());
    7070    return drawingRect;
     
    7373GraphicsContext* FilterEffect::getEffectContext()
    7474{
    75     IntRect bufferRect = enclosingIntRect(subRegion());
     75    IntRect bufferRect = enclosingIntRect(scaledSubRegion());
    7676    m_effectBuffer = ImageBuffer::create(bufferRect.size(), LinearRGB);
    7777    return m_effectBuffer->context();
  • trunk/WebCore/platform/graphics/filters/FilterEffect.h

    r49582 r51310  
    4444        FloatRect subRegion() const { return m_subRegion; }
    4545        void setSubRegion(const FloatRect& subRegion) { m_subRegion = subRegion; }
     46
     47        FloatRect scaledSubRegion() const { return m_scaledSubRegion; }
     48        void setScaledSubRegion(const FloatRect& scaledSubRegion) { m_scaledSubRegion = scaledSubRegion; }
     49
     50        FloatRect effectBoundaries() const { return m_effectBoundaries; }
     51        void setEffectBoundaries(const FloatRect& effectBoundaries) { m_effectBoundaries = effectBoundaries; }
    4652
    4753        bool hasX() { return m_hasX; }
     
    97103        bool m_alphaImage;
    98104
     105        FloatRect m_effectBoundaries;
    99106        FloatRect m_subRegion;
     107        FloatRect m_scaledSubRegion;
    100108        FloatRect m_unionOfChildEffectSubregions;
    101109
  • trunk/WebCore/platform/graphics/filters/ImageBufferFilter.cpp

    r50920 r51310  
    2424#include "ImageBufferFilter.h"
    2525
     26#include "FloatSize.h"
     27
    2628namespace WebCore {
    2729
     
    2931    : Filter()
    3032{
     33    setFilterResolution(FloatSize(1.f, 1.f));
    3134}
    3235
  • trunk/WebCore/platform/graphics/filters/ImageBufferFilter.h

    r50920 r51310  
    2626#include "FilterEffect.h"
    2727#include "FloatRect.h"
     28#include "FloatSize.h"
    2829
    2930#include <wtf/PassRefPtr.h>
     
    4243    // SVG specific
    4344    virtual bool effectBoundingBoxMode() const { return false; }
    44     virtual void calculateEffectSubRegion(FilterEffect*) const { }
     45
     46    virtual FloatSize maxImageSize() const { return FloatSize(); }
     47    virtual void calculateEffectSubRegion(FilterEffect*) { }
    4548
    4649private:
  • trunk/WebCore/platform/graphics/filters/SourceAlpha.cpp

    r50864 r51310  
    5151        clippedSourceRect.setY(filter->filterRegion().y());
    5252    setSubRegion(clippedSourceRect);
     53    clippedSourceRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
     54    setScaledSubRegion(clippedSourceRect);
    5355    return filter->filterRegion();
    5456}
  • trunk/WebCore/platform/graphics/filters/SourceGraphic.cpp

    r51240 r51310  
    5050        clippedSourceRect.setY(filter->filterRegion().y());
    5151    setSubRegion(clippedSourceRect);
     52    clippedSourceRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
     53    setScaledSubRegion(clippedSourceRect);
    5254    return filter->filterRegion();
    5355}
  • trunk/WebCore/svg/SVGFilterElement.cpp

    r50583 r51310  
    2727
    2828#include "Attr.h"
    29 #include "SVGFilterBuilder.h"
     29#include "FloatSize.h"
    3030#include "MappedAttribute.h"
    3131#include "PlatformString.h"
     32#include "SVGFilterBuilder.h"
    3233#include "SVGFilterPrimitiveStandardAttributes.h"
    3334#include "SVGLength.h"
    3435#include "SVGNames.h"
     36#include "SVGParserUtilities.h"
    3537#include "SVGResourceFilter.h"
    3638#include "SVGUnitTypes.h"
     
    9092    else if (attr->name() == SVGNames::heightAttr)
    9193        setHeightBaseValue(SVGLength(LengthModeHeight, value));
    92     else {
     94    else if (attr->name() == SVGNames::filterResAttr) {
     95        float x, y;
     96        if (parseNumberOptionalNumber(value, x, y)) {
     97            setFilterResXBaseValue(x);
     98            setFilterResYBaseValue(y);
     99        }
     100    } else {
    93101        if (SVGURIReference::parseMappedAttribute(attr))
    94102            return;
     
    131139    m_filter->setFilterBoundingBoxMode(filterBBoxMode);
    132140
     141    if (hasAttribute(SVGNames::filterResAttr)) {
     142        m_filter->setHasFilterResolution(true);
     143        m_filter->setFilterResolution(FloatSize(filterResX(), filterResY()));
     144    }
     145
    133146    // Add effects to the filter
    134147    m_filter->builder()->clearEffects();
  • trunk/WebCore/svg/SVGFilterPrimitiveStandardAttributes.cpp

    r49582 r51310  
    9898                               height().value(this));
    9999
    100     filterEffect->setSubRegion(effectBBox);
     100    filterEffect->setEffectBoundaries(effectBBox);
    101101}
    102102
  • trunk/WebCore/svg/graphics/SVGResourceFilter.cpp

    r51240 r51310  
    3636#include "SVGFilterPrimitiveStandardAttributes.h"
    3737
     38static const float kMaxFilterSize = 5000.0f;
     39
     40using std::min;
     41
    3842namespace WebCore {
    3943
     
    4347    , m_filterBBoxMode(false)
    4448    , m_effectBBoxMode(false)
     49    , m_filterRes(false)
     50    , m_scaleX(1.f)
     51    , m_scaleY(1.f)
    4552    , m_savedContext(0)
    4653    , m_sourceGraphicBuffer(0)
     
    5360}
    5461
     62static inline bool shouldProcessFilter(SVGResourceFilter* filter)
     63{
     64    return (!filter->scaleX() || !filter->scaleY() || !filter->filterBoundingBox().width()
     65            || !filter->filterBoundingBox().height());
     66}
     67
    5568void SVGResourceFilter::addFilterEffect(SVGFilterPrimitiveStandardAttributes* effectAttributes, PassRefPtr<FilterEffect> effect)
    5669{
     
    5972}
    6073
     74bool SVGResourceFilter::fitsInMaximumImageSize(const FloatSize& size)
     75{
     76    bool matchesFilterSize = true;
     77    if (size.width() > kMaxFilterSize) {
     78        m_scaleX *= kMaxFilterSize / size.width();
     79        matchesFilterSize = false;
     80    }
     81    if (size.height() > kMaxFilterSize) {
     82        m_scaleY *= kMaxFilterSize / size.height();
     83        matchesFilterSize = false;
     84    }
     85
     86    return matchesFilterSize;
     87}
     88
    6189void SVGResourceFilter::prepareFilter(GraphicsContext*& context, const RenderObject* object)
    6290{
    6391    FloatRect targetRect = object->objectBoundingBox();
    6492    m_ownerElement->buildFilter(targetRect);
     93
     94    if (shouldProcessFilter(this))
     95        return;
    6596
    6697    // clip sourceImage to filterRegion
     
    6899    clippedSourceRect.intersect(m_filterBBox);
    69100
     101    // scale filter size to filterRes
     102    FloatRect tempSourceRect = clippedSourceRect;
     103    if (m_filterRes) {
     104        m_scaleX = m_filterResSize.width() / m_filterBBox.width();
     105        m_scaleY = m_filterResSize.height() / m_filterBBox.height();
     106    }
     107
     108    // scale to big sourceImage size to kMaxFilterSize
     109    tempSourceRect.scale(m_scaleX, m_scaleY);
     110    fitsInMaximumImageSize(tempSourceRect.size());
     111
    70112    // prepare Filters
    71113    m_filter = SVGFilter::create(targetRect, m_filterBBox, m_effectBBoxMode);
     114    m_filter->setFilterResolution(FloatSize(m_scaleX, m_scaleY));
    72115
    73116    FilterEffect* lastEffect = m_filterBuilder->lastEffect();
    74     if (lastEffect)
     117    if (lastEffect) {
    75118        lastEffect->calculateEffectRect(m_filter.get());
     119        // at least one FilterEffect has a too big image size,
     120        // recalculate the effect sizes with new scale factors
     121        if (!fitsInMaximumImageSize(m_filter->maxImageSize())) {
     122            m_filter->setFilterResolution(FloatSize(m_scaleX, m_scaleY));
     123            lastEffect->calculateEffectRect(m_filter.get());
     124        }
     125    }
     126
     127    clippedSourceRect.scale(m_scaleX, m_scaleY);
    76128
    77129    // Draw the content of the current element and it's childs to a imageBuffer to get the SourceGraphic.
     
    84136
    85137    GraphicsContext* sourceGraphicContext = sourceGraphic->context();
     138    sourceGraphicContext->scale(FloatSize(m_scaleX, m_scaleY));
    86139    sourceGraphicContext->translate(-targetRect.x(), -targetRect.y());
    87140    sourceGraphicContext->clearRect(FloatRect(FloatPoint(), targetRect.size()));
     
    94147void SVGResourceFilter::applyFilter(GraphicsContext*& context, const RenderObject* object)
    95148{
     149    if (shouldProcessFilter(this))
     150        return;
     151
    96152    if (!m_savedContext)
    97153        return;
  • trunk/WebCore/svg/graphics/SVGResourceFilter.h

    r49582 r51310  
    5454    virtual SVGResourceType resourceType() const { return FilterResourceType; }
    5555
     56    void setFilterResolution(const FloatSize& filterResSize) { m_filterResSize = filterResSize; }
     57    void setHasFilterResolution(bool filterRes) { m_filterRes = filterRes; }
     58
    5659    bool filterBoundingBoxMode() const { return m_filterBBoxMode; }
    5760    void setFilterBoundingBoxMode(bool bboxMode) { m_filterBBoxMode = bboxMode; }
     
    6366    void setFilterRect(const FloatRect& rect) { m_filterRect = rect; }
    6467
     68    float scaleX() const { return m_scaleX; }
     69    float scaleY() const { return m_scaleY; }
     70
    6571    FloatRect filterBoundingBox() { return m_filterBBox; }
    6672    void setFilterBoundingBox(const FloatRect& rect) { m_filterBBox = rect; }
     
    6874    void prepareFilter(GraphicsContext*&, const RenderObject*);
    6975    void applyFilter(GraphicsContext*&, const RenderObject*);
     76
     77    bool fitsInMaximumImageSize(const FloatSize&);
    7078
    7179    void addFilterEffect(SVGFilterPrimitiveStandardAttributes*, PassRefPtr<FilterEffect>);
     
    8290    bool m_filterBBoxMode : 1;
    8391    bool m_effectBBoxMode : 1;
     92    bool m_filterRes : 1;
     93    float m_scaleX;
     94    float m_scaleY;
    8495
    8596    FloatRect m_filterRect;
    8697    FloatRect m_filterBBox;
     98    FloatSize m_filterResSize;
    8799
    88100    OwnPtr<SVGFilterBuilder> m_filterBuilder;
  • trunk/WebCore/svg/graphics/filters/SVGFEDisplacementMap.cpp

    r50718 r51310  
    9494        return;
    9595
    96     IntRect effectADrawingRect = calculateDrawingIntRect(m_in->subRegion());
     96    IntRect effectADrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
    9797    RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
    9898
    99     IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->subRegion());
     99    IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->scaledSubRegion());
    100100    RefPtr<CanvasPixelArray> srcPixelArrayB(m_in2->resultImage()->getUnmultipliedImageData(effectBDrawingRect)->data());
    101101
     
    105105    ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length());
    106106
    107     float scale = m_scale / 255.f;
    108     float scaleAdjustment = 0.5f - 0.5f * m_scale;
     107    float scaleX = m_scale / 255.f * filter->filterResolution().width();
     108    float scaleY = m_scale / 255.f * filter->filterResolution().height();
     109    float scaleAdjustmentX = (0.5f - 0.5f * m_scale) * filter->filterResolution().width();
     110    float scaleAdjustmentY = (0.5f - 0.5f * m_scale) * filter->filterResolution().height();
    109111    int stride = imageRect.width() * 4;
    110112    for (int y = 0; y < imageRect.height(); ++y) {
     
    112114        for (int x = 0; x < imageRect.width(); ++x) {
    113115            int dstIndex = line + x * 4;
    114             int srcX = x + static_cast<int>(scale * srcPixelArrayB->get(dstIndex + m_xChannelSelector - 1) + scaleAdjustment);
    115             int srcY = y + static_cast<int>(scale * srcPixelArrayB->get(dstIndex + m_yChannelSelector - 1) + scaleAdjustment);
     116            int srcX = x + static_cast<int>(scaleX * srcPixelArrayB->get(dstIndex + m_xChannelSelector - 1) + scaleAdjustmentX);
     117            int srcY = y + static_cast<int>(scaleY * srcPixelArrayB->get(dstIndex + m_yChannelSelector - 1) + scaleAdjustmentY);
    116118            for (unsigned channel = 0; channel < 4; ++channel) {
    117119                if (srcX < 0 || srcX >= imageRect.width() || srcY < 0 || srcY >= imageRect.height())
  • trunk/WebCore/svg/graphics/filters/SVGFEFlood.cpp

    r50864 r51310  
    7171
    7272    Color color = colorWithOverrideAlpha(floodColor().rgb(), floodOpacity());
    73     filterContext->fillRect(FloatRect(FloatPoint(), subRegion().size()), color, DeviceColorSpace);
     73    filterContext->fillRect(FloatRect(FloatPoint(), scaledSubRegion().size()), color, DeviceColorSpace);
    7474}
    7575
  • trunk/WebCore/svg/graphics/filters/SVGFEMerge.cpp

    r51240 r51310  
    7979
    8080    for (unsigned i = 0; i < m_mergeInputs.size(); i++) {
    81         FloatRect destRect = calculateDrawingRect(m_mergeInputs[i]->subRegion());
     81        FloatRect destRect = calculateDrawingRect(m_mergeInputs[i]->scaledSubRegion());
    8282        filterContext->drawImage(m_mergeInputs[i]->resultImage()->image(), DeviceColorSpace, destRect);
    8383    }
  • trunk/WebCore/svg/graphics/filters/SVGFEMorphology.cpp

    r50604 r51310  
    9595
    9696    IntRect imageRect(IntPoint(), resultImage()->size());
    97     IntRect effectDrawingRect = calculateDrawingIntRect(m_in->subRegion());
     97    IntRect effectDrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
    9898    RefPtr<CanvasPixelArray> srcPixelArray(m_in->resultImage()->getPremultipliedImageData(effectDrawingRect)->data());
    9999    RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height());
    100100
    101     int radiusX = static_cast<int>(m_radiusX);
    102     int radiusY = static_cast<int>(m_radiusY);
     101    int radiusX = static_cast<int>(m_radiusX * filter->filterResolution().width());
     102    int radiusY = static_cast<int>(m_radiusY * filter->filterResolution().height());
    103103    int effectWidth = effectDrawingRect.width() * 4;
    104104   
  • trunk/WebCore/svg/graphics/filters/SVGFEOffset.cpp

    r51240 r51310  
    7575        return;
    7676
     77    FloatRect sourceImageRect = filter->sourceImageRect();
     78    sourceImageRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
     79
    7780    if (filter->effectBoundingBoxMode()) {
    78         setDx(dx() * filter->sourceImageRect().width());
    79         setDy(dy() * filter->sourceImageRect().height());
     81        m_dx *= sourceImageRect.width();
     82        m_dy *= sourceImageRect.height();
    8083    }
     84    m_dx *= filter->filterResolution().width();
     85    m_dy *= filter->filterResolution().height();
    8186
    82     FloatRect dstRect = FloatRect(dx() + m_in->subRegion().x() - subRegion().x(),
    83                                   dy() + m_in->subRegion().y() - subRegion().y(),
    84                                   m_in->subRegion().width(),
    85                                   m_in->subRegion().height());
     87    FloatRect dstRect = FloatRect(m_dx + m_in->scaledSubRegion().x() - scaledSubRegion().x(),
     88                                  m_dy + m_in->scaledSubRegion().y() - scaledSubRegion().y(),
     89                                  m_in->scaledSubRegion().width(),
     90                                  m_in->scaledSubRegion().height());
    8691
    8792    filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, dstRect);
  • trunk/WebCore/svg/graphics/filters/SVGFETile.cpp

    r51240 r51310  
    5959        return;
    6060
    61     IntRect tileRect = enclosingIntRect(m_in->subRegion());
     61    IntRect tileRect = enclosingIntRect(m_in->scaledSubRegion());
    6262
    6363    // Source input needs more attention. It has the size of the filterRegion but gives the
    6464    // size of the cutted sourceImage back. This is part of the specification and optimization.
    65     if (m_in->isSourceInput())
    66         tileRect = enclosingIntRect(filter->filterRegion());
     65    if (m_in->isSourceInput()) {
     66        FloatRect filterRegion = filter->filterRegion();
     67        filterRegion.scale(filter->filterResolution().width(), filter->filterResolution().height());
     68        tileRect = enclosingIntRect(filterRegion);
     69    }
    6770
    6871    OwnPtr<ImageBuffer> tileImage = ImageBuffer::create(tileRect.size());
     
    7275
    7376    TransformationMatrix matrix;
    74     matrix.translate(m_in->subRegion().x() - subRegion().x(), m_in->subRegion().y() - subRegion().y());
     77    matrix.translate(m_in->scaledSubRegion().x() - scaledSubRegion().x(), m_in->scaledSubRegion().y() - scaledSubRegion().y());
    7578    pattern.get()->setPatternSpaceTransform(matrix);
    7679
    7780    filterContext->setFillPattern(pattern);
    78     filterContext->fillRect(FloatRect(FloatPoint(), subRegion().size()));
     81    filterContext->fillRect(FloatRect(FloatPoint(), scaledSubRegion().size()));
    7982}
    8083
  • trunk/WebCore/svg/graphics/filters/SVGFilter.cpp

    r50920 r51310  
    3333}
    3434
    35 void SVGFilter::calculateEffectSubRegion(FilterEffect* effect) const
     35void SVGFilter::calculateEffectSubRegion(FilterEffect* effect)
    3636{
    37     FloatRect subRegionBBox = effect->subRegion();
     37    FloatRect subRegionBBox = effect->effectBoundaries();
    3838    FloatRect useBBox = effect->unionOfChildEffectSubregions();
    3939    FloatRect newSubRegion = subRegionBBox;
     
    7171
    7272    effect->setSubRegion(newSubRegion);
     73    newSubRegion.scale(filterResolution().width(), filterResolution().height());
     74    effect->setScaledSubRegion(newSubRegion);
     75    m_maxImageSize = m_maxImageSize.expandedTo(newSubRegion.size());
    7376}
    7477
  • trunk/WebCore/svg/graphics/filters/SVGFilter.h

    r50920 r51310  
    2525#include "FilterEffect.h"
    2626#include "FloatRect.h"
     27#include "FloatSize.h"
    2728
    2829#include <wtf/PassRefPtr.h>
     
    3637        static PassRefPtr<SVGFilter> create(const FloatRect&, const FloatRect&, bool);
    3738
    38         bool effectBoundingBoxMode() const { return m_effectBBoxMode; }
     39        virtual bool effectBoundingBoxMode() const { return m_effectBBoxMode; }
    3940
    40         FloatRect filterRegion() const { return m_filterRect; }
    41         FloatRect sourceImageRect() const { return m_itemBox; }
    42         void calculateEffectSubRegion(FilterEffect*) const;
     41        virtual FloatRect filterRegion() const { return m_filterRect; }
     42        virtual FloatRect sourceImageRect() const { return m_itemBox; }
     43
     44        virtual FloatSize maxImageSize() const { return m_maxImageSize; }
     45        virtual void calculateEffectSubRegion(FilterEffect*);
    4346
    4447    private:
    4548        SVGFilter(const FloatRect& itemBox, const FloatRect& filterRect, bool effectBBoxMode);
    4649
     50        FloatSize m_maxImageSize;
    4751        FloatRect m_itemBox;
    4852        FloatRect m_filterRect;
Note: See TracChangeset for help on using the changeset viewer.