diff options
Diffstat (limited to 'WebCore/svg/graphics/SVGResourceFilter.cpp')
-rw-r--r-- | WebCore/svg/graphics/SVGResourceFilter.cpp | 65 |
1 files changed, 62 insertions, 3 deletions
diff --git a/WebCore/svg/graphics/SVGResourceFilter.cpp b/WebCore/svg/graphics/SVGResourceFilter.cpp index 973743c..fcf0e40 100644 --- a/WebCore/svg/graphics/SVGResourceFilter.cpp +++ b/WebCore/svg/graphics/SVGResourceFilter.cpp @@ -35,6 +35,10 @@ #include "SVGRenderTreeAsText.h" #include "SVGFilterPrimitiveStandardAttributes.h" +static const float kMaxFilterSize = 5000.0f; + +using std::min; + namespace WebCore { SVGResourceFilter::SVGResourceFilter(const SVGFilterElement* ownerElement) @@ -42,6 +46,9 @@ SVGResourceFilter::SVGResourceFilter(const SVGFilterElement* ownerElement) , m_ownerElement(ownerElement) , m_filterBBoxMode(false) , m_effectBBoxMode(false) + , m_filterRes(false) + , m_scaleX(1.f) + , m_scaleY(1.f) , m_savedContext(0) , m_sourceGraphicBuffer(0) { @@ -52,27 +59,72 @@ SVGResourceFilter::~SVGResourceFilter() { } +static inline bool shouldProcessFilter(SVGResourceFilter* filter) +{ + return (!filter->scaleX() || !filter->scaleY() || !filter->filterBoundingBox().width() + || !filter->filterBoundingBox().height()); +} + void SVGResourceFilter::addFilterEffect(SVGFilterPrimitiveStandardAttributes* effectAttributes, PassRefPtr<FilterEffect> effect) { effectAttributes->setStandardAttributes(this, effect.get()); builder()->add(effectAttributes->result(), effect); } +bool SVGResourceFilter::fitsInMaximumImageSize(const FloatSize& size) +{ + bool matchesFilterSize = true; + if (size.width() > kMaxFilterSize) { + m_scaleX *= kMaxFilterSize / size.width(); + matchesFilterSize = false; + } + if (size.height() > kMaxFilterSize) { + m_scaleY *= kMaxFilterSize / size.height(); + matchesFilterSize = false; + } + + return matchesFilterSize; +} + void SVGResourceFilter::prepareFilter(GraphicsContext*& context, const RenderObject* object) { FloatRect targetRect = object->objectBoundingBox(); m_ownerElement->buildFilter(targetRect); + if (shouldProcessFilter(this)) + return; + // clip sourceImage to filterRegion FloatRect clippedSourceRect = targetRect; clippedSourceRect.intersect(m_filterBBox); + // scale filter size to filterRes + FloatRect tempSourceRect = clippedSourceRect; + if (m_filterRes) { + m_scaleX = m_filterResSize.width() / m_filterBBox.width(); + m_scaleY = m_filterResSize.height() / m_filterBBox.height(); + } + + // scale to big sourceImage size to kMaxFilterSize + tempSourceRect.scale(m_scaleX, m_scaleY); + fitsInMaximumImageSize(tempSourceRect.size()); + // prepare Filters m_filter = SVGFilter::create(targetRect, m_filterBBox, m_effectBBoxMode); + m_filter->setFilterResolution(FloatSize(m_scaleX, m_scaleY)); FilterEffect* lastEffect = m_filterBuilder->lastEffect(); - if (lastEffect) + if (lastEffect) { lastEffect->calculateEffectRect(m_filter.get()); + // at least one FilterEffect has a too big image size, + // recalculate the effect sizes with new scale factors + if (!fitsInMaximumImageSize(m_filter->maxImageSize())) { + m_filter->setFilterResolution(FloatSize(m_scaleX, m_scaleY)); + lastEffect->calculateEffectRect(m_filter.get()); + } + } + + clippedSourceRect.scale(m_scaleX, m_scaleY); // Draw the content of the current element and it's childs to a imageBuffer to get the SourceGraphic. // The size of the SourceGraphic is clipped to the size of the filterRegion. @@ -83,6 +135,7 @@ void SVGResourceFilter::prepareFilter(GraphicsContext*& context, const RenderObj return; GraphicsContext* sourceGraphicContext = sourceGraphic->context(); + sourceGraphicContext->scale(FloatSize(m_scaleX, m_scaleY)); sourceGraphicContext->translate(-targetRect.x(), -targetRect.y()); sourceGraphicContext->clearRect(FloatRect(FloatPoint(), targetRect.size())); m_sourceGraphicBuffer.set(sourceGraphic.release()); @@ -91,8 +144,11 @@ void SVGResourceFilter::prepareFilter(GraphicsContext*& context, const RenderObj context = sourceGraphicContext; } -void SVGResourceFilter::applyFilter(GraphicsContext*& context, const RenderObject*) +void SVGResourceFilter::applyFilter(GraphicsContext*& context, const RenderObject* object) { + if (shouldProcessFilter(this)) + return; + if (!m_savedContext) return; @@ -113,7 +169,10 @@ void SVGResourceFilter::applyFilter(GraphicsContext*& context, const RenderObjec #if !PLATFORM(CG) resultImage->transformColorSpace(LinearRGB, DeviceRGB); #endif - context->drawImage(resultImage->image(), lastEffect->subRegion()); + ColorSpace colorSpace = DeviceColorSpace; + if (object) + colorSpace = object->style()->colorSpace(); + context->drawImage(resultImage->image(), colorSpace, lastEffect->subRegion()); } } |