| Index: Source/core/rendering/FilterEffectRenderer.cpp
|
| diff --git a/Source/core/rendering/FilterEffectRenderer.cpp b/Source/core/rendering/FilterEffectRenderer.cpp
|
| index 6d6ce158d6ef4900745dbe18ee657e6fa76934b6..2c4aef2a57d53e771c4ec89a7eb41e2925ec0daa 100644
|
| --- a/Source/core/rendering/FilterEffectRenderer.cpp
|
| +++ b/Source/core/rendering/FilterEffectRenderer.cpp
|
| @@ -50,6 +50,7 @@
|
| #include "core/rendering/RenderView.h"
|
|
|
| #if ENABLE(SVG)
|
| +#include "SVGNames.h"
|
| #include "core/loader/cache/CachedSVGDocument.h"
|
| #include "core/loader/cache/CachedSVGDocumentReference.h"
|
| #include "core/platform/graphics/filters/SourceAlpha.h"
|
| @@ -143,6 +144,11 @@ PassRefPtr<FilterEffect> FilterEffectRenderer::buildReferenceFilter(RenderObject
|
| return 0;
|
| }
|
|
|
| + if (!filter->isSVGElement() || !filter->hasTagName(SVGNames::filterTag))
|
| + return 0;
|
| +
|
| + SVGFilterElement* filterElement = toSVGFilterElement(toSVGElement(filter));
|
| +
|
| RefPtr<FilterEffect> effect;
|
|
|
| // FIXME: Figure out what to do with SourceAlpha. Right now, we're
|
| @@ -152,7 +158,7 @@ PassRefPtr<FilterEffect> FilterEffectRenderer::buildReferenceFilter(RenderObject
|
| // This may need a spec clarification.
|
| RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(previousEffect, SourceAlpha::create(this));
|
|
|
| - for (Node* node = filter->firstChild(); node; node = node->nextSibling()) {
|
| + for (Node* node = filterElement->firstChild(); node; node = node->nextSibling()) {
|
| if (!node->isSVGElement())
|
| continue;
|
|
|
| @@ -167,6 +173,7 @@ PassRefPtr<FilterEffect> FilterEffectRenderer::buildReferenceFilter(RenderObject
|
| continue;
|
|
|
| effectElement->setStandardAttributes(effect.get());
|
| + effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement->primitiveUnits(), sourceImageRect()));
|
| builder->add(effectElement->result(), effect);
|
| m_effects.append(effect);
|
| }
|
| @@ -183,8 +190,6 @@ bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations&
|
| {
|
| m_hasCustomShaderFilter = false;
|
| m_hasFilterThatMovesPixels = operations.hasFilterThatMovesPixels();
|
| - if (m_hasFilterThatMovesPixels)
|
| - m_outsets = operations.outsets();
|
|
|
| // Keep the old effects on the stack until we've created the new effects.
|
| // New FECustomFilters can reuse cached resources from old FECustomFilters.
|
| @@ -199,7 +204,7 @@ bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations&
|
| case FilterOperation::REFERENCE: {
|
| ReferenceFilterOperation* referenceOperation = static_cast<ReferenceFilterOperation*>(filterOperation);
|
| effect = buildReferenceFilter(renderer, previousEffect, referenceOperation);
|
| - referenceOperation->setFilterEffect(effect);
|
| + referenceOperation->setFilterEffect(effect, this);
|
| break;
|
| }
|
| case FilterOperation::GRAYSCALE: {
|
| @@ -351,11 +356,11 @@ bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations&
|
| }
|
|
|
| if (effect) {
|
| - // Unlike SVG, filters applied here should not clip to their primitive subregions.
|
| - effect->setClipsToBounds(false);
|
| effect->setOperatingColorSpace(ColorSpaceDeviceRGB);
|
|
|
| if (filterOperation->getOperationType() != FilterOperation::REFERENCE) {
|
| + // Unlike SVG, filters applied here should not clip to their primitive subregions.
|
| + effect->setClipsToBounds(false);
|
| effect->inputEffects().append(previousEffect);
|
| m_effects.append(effect);
|
| }
|
| @@ -367,8 +372,6 @@ bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations&
|
| if (!m_effects.size())
|
| return false;
|
|
|
| - setMaxEffectRects(m_sourceDrawingRegion);
|
| -
|
| return true;
|
| }
|
|
|
| @@ -419,15 +422,14 @@ LayoutRect FilterEffectRenderer::computeSourceImageRectForDirtyRect(const Layout
|
| return filterBoxRect;
|
| }
|
| // The result of this function is the area in the "filterBoxRect" that needs to be repainted, so that we fully cover the "dirtyRect".
|
| - LayoutRect rectForRepaint = dirtyRect;
|
| - if (hasFilterThatMovesPixels()) {
|
| - // Note that the outsets are reversed here because we are going backwards -> we have the dirty rect and
|
| - // need to find out what is the rectangle that might influence the result inside that dirty rect.
|
| - rectForRepaint.move(-m_outsets.right(), -m_outsets.bottom());
|
| - rectForRepaint.expand(m_outsets.left() + m_outsets.right(), m_outsets.top() + m_outsets.bottom());
|
| - }
|
| + FloatRect rectForRepaint = dirtyRect;
|
| + rectForRepaint.move(-filterBoxRect.location().x(), -filterBoxRect.location().y());
|
| + float inf = std::numeric_limits<float>::infinity();
|
| + FloatRect clipRect = FloatRect(FloatPoint(-inf, -inf), FloatSize(inf, inf));
|
| + rectForRepaint = lastEffect()->getSourceRect(rectForRepaint, clipRect);
|
| + rectForRepaint.move(filterBoxRect.location().x(), filterBoxRect.location().y());
|
| rectForRepaint.intersect(filterBoxRect);
|
| - return rectForRepaint;
|
| + return LayoutRect(rectForRepaint);
|
| }
|
|
|
| bool FilterEffectRendererHelper::prepareFilterEffect(RenderLayer* renderLayer, const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect, const LayoutRect& layerRepaintRect)
|
| @@ -438,13 +440,19 @@ bool FilterEffectRendererHelper::prepareFilterEffect(RenderLayer* renderLayer, c
|
|
|
| FilterEffectRenderer* filter = renderLayer->filterRenderer();
|
| LayoutRect filterSourceRect = filter->computeSourceImageRectForDirtyRect(filterBoxRect, dirtyRect);
|
| - m_paintOffset = filterSourceRect.location();
|
|
|
| if (filterSourceRect.isEmpty()) {
|
| // The dirty rect is not in view, just bail out.
|
| m_haveFilterEffect = false;
|
| return false;
|
| }
|
| +
|
| + AffineTransform absoluteTransform;
|
| + absoluteTransform.translate(filterBoxRect.x(), filterBoxRect.y());
|
| + filter->setAbsoluteTransform(absoluteTransform);
|
| + filter->setAbsoluteFilterRegion(filterSourceRect);
|
| + filter->setFilterRegion(absoluteTransform.inverse().mapRect(filterSourceRect));
|
| + filter->lastEffect()->determineFilterPrimitiveSubregion();
|
|
|
| bool hasUpdatedBackingStore = filter->updateBackingStoreRect(filterSourceRect);
|
| if (filter->hasFilterThatMovesPixels()) {
|
| @@ -466,7 +474,7 @@ GraphicsContext* FilterEffectRendererHelper::beginFilterEffect(GraphicsContext*
|
| filter->allocateBackingStoreIfNeeded();
|
| // Paint into the context that represents the SourceGraphic of the filter.
|
| GraphicsContext* sourceGraphicsContext = filter->inputContext();
|
| - if (!sourceGraphicsContext || !isFilterSizeValid(filter->filterRegion())) {
|
| + if (!sourceGraphicsContext || !isFilterSizeValid(filter->absoluteFilterRegion())) {
|
| // Disable the filters and continue.
|
| m_haveFilterEffect = false;
|
| return oldContext;
|
| @@ -476,7 +484,10 @@ GraphicsContext* FilterEffectRendererHelper::beginFilterEffect(GraphicsContext*
|
|
|
| // Translate the context so that the contents of the layer is captuterd in the offscreen memory buffer.
|
| sourceGraphicsContext->save();
|
| - sourceGraphicsContext->translate(-m_paintOffset.x(), -m_paintOffset.y());
|
| + // FIXME: can we just use sourceImageRect for everything, and get rid of
|
| + // m_repaintRect?
|
| + FloatPoint offset = filter->sourceImageRect().location();
|
| + sourceGraphicsContext->translate(-offset.x(), -offset.y());
|
| sourceGraphicsContext->clearRect(m_repaintRect);
|
| sourceGraphicsContext->clip(m_repaintRect);
|
|
|
| @@ -492,10 +503,7 @@ GraphicsContext* FilterEffectRendererHelper::applyFilterEffect()
|
| filter->apply();
|
|
|
| // Get the filtered output and draw it in place.
|
| - LayoutRect destRect = filter->outputRect();
|
| - destRect.move(m_paintOffset.x(), m_paintOffset.y());
|
| -
|
| - m_savedGraphicsContext->drawImageBuffer(filter->output(), m_renderLayer->renderer()->style()->colorSpace(), pixelSnappedIntRect(destRect), CompositeSourceOver);
|
| + m_savedGraphicsContext->drawImageBuffer(filter->output(), m_renderLayer->renderer()->style()->colorSpace(), filter->outputRect(), CompositeSourceOver);
|
|
|
| filter->clearIntermediateResults();
|
|
|
|
|