summaryrefslogtreecommitdiffstats
path: root/WebCore/svg/graphics/SVGResourceFilter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/svg/graphics/SVGResourceFilter.cpp')
-rw-r--r--WebCore/svg/graphics/SVGResourceFilter.cpp65
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());
}
}