Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1181)

Unified Diff: Source/core/rendering/FilterEffectRenderer.cpp

Issue 14652016: Implement filter primitive subregion for reference CSS filters. This required refactoring determin… (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fix test failures: ReferenceFilterOperation should ref the Filter which owns its FilterEffects Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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();
« no previous file with comments | « Source/core/rendering/FilterEffectRenderer.h ('k') | Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698