Index: Source/core/rendering/FilterEffectRenderer.cpp |
diff --git a/Source/core/rendering/FilterEffectRenderer.cpp b/Source/core/rendering/FilterEffectRenderer.cpp |
index f58ed4e0b78babf25eec2f33ce9a1f58a3ba5354..507ab39abfe27ff43ee80dc1e1a2285d857a5b7d 100644 |
--- a/Source/core/rendering/FilterEffectRenderer.cpp |
+++ b/Source/core/rendering/FilterEffectRenderer.cpp |
@@ -32,20 +32,22 @@ |
#include "core/fetch/DocumentResourceReference.h" |
#include "core/frame/Settings.h" |
#include "core/page/Page.h" |
-#include "core/rendering/RenderLayer.h" |
-#include "core/rendering/RenderView.h" |
+#include "core/rendering/RenderObject.h" |
#include "core/rendering/svg/ReferenceFilterBuilder.h" |
#include "core/svg/SVGElement.h" |
#include "core/svg/SVGFilterPrimitiveStandardAttributes.h" |
#include "platform/FloatConversion.h" |
#include "platform/LengthFunctions.h" |
#include "platform/graphics/ColorSpace.h" |
+#include "platform/graphics/GraphicsContext.h" |
+#include "platform/graphics/ImageFilter.h" |
#include "platform/graphics/UnacceleratedImageBufferSurface.h" |
#include "platform/graphics/filters/FEColorMatrix.h" |
#include "platform/graphics/filters/FEComponentTransfer.h" |
#include "platform/graphics/filters/FEDropShadow.h" |
#include "platform/graphics/filters/FEGaussianBlur.h" |
#include "platform/graphics/filters/SkiaImageFilterBuilder.h" |
+#include "platform/graphics/filters/SourceGraphic.h" |
#include "wtf/MathExtras.h" |
#include <algorithm> |
@@ -67,9 +69,7 @@ static inline void lastMatrixRow(Vector<float>& parameters) |
} |
FilterEffectRenderer::FilterEffectRenderer() |
- : Filter(AffineTransform()) |
{ |
- m_sourceGraphic = SourceGraphic::create(this); |
} |
FilterEffectRenderer::~FilterEffectRenderer() |
@@ -78,18 +78,18 @@ FilterEffectRenderer::~FilterEffectRenderer() |
bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations& operations) |
{ |
- // Inverse zoom the pre-zoomed CSS shorthand filters, so that they are in the same zoom as the unzoomed reference filters. |
const RenderStyle* style = renderer->style(); |
float zoom = style ? style->effectiveZoom() : 1.0f; |
- RefPtr<FilterEffect> previousEffect = m_sourceGraphic; |
+ // Create a parent filter for shorthand filters. These have already been scaled by the CSS code for page zoom, so scale is 1.0 here. |
+ RefPtr<ReferenceFilter> parentFilter = ReferenceFilter::create(1.0f); |
+ RefPtr<FilterEffect> previousEffect = SourceGraphic::create(parentFilter.get()); |
for (size_t i = 0; i < operations.operations().size(); ++i) { |
RefPtr<FilterEffect> effect; |
FilterOperation* filterOperation = operations.operations().at(i).get(); |
switch (filterOperation->type()) { |
case FilterOperation::REFERENCE: { |
- RefPtr<ReferenceFilter> referenceFilter = ReferenceFilter::create(); |
- referenceFilter->setAbsoluteTransform(AffineTransform().scale(zoom, zoom)); |
+ RefPtr<ReferenceFilter> referenceFilter = ReferenceFilter::create(zoom); |
effect = ReferenceFilterBuilder::build(referenceFilter.get(), renderer, previousEffect.get(), toReferenceFilterOperation(filterOperation)); |
referenceFilter->setLastEffect(effect); |
m_referenceFilters.append(referenceFilter); |
@@ -119,7 +119,7 @@ bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations& |
lastMatrixRow(inputParameters); |
- effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters); |
+ effect = FEColorMatrix::create(parentFilter.get(), FECOLORMATRIX_TYPE_MATRIX, inputParameters); |
break; |
} |
case FilterOperation::SEPIA: { |
@@ -146,19 +146,19 @@ bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations& |
lastMatrixRow(inputParameters); |
- effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters); |
+ effect = FEColorMatrix::create(parentFilter.get(), FECOLORMATRIX_TYPE_MATRIX, inputParameters); |
break; |
} |
case FilterOperation::SATURATE: { |
Vector<float> inputParameters; |
inputParameters.append(narrowPrecisionToFloat(toBasicColorMatrixFilterOperation(filterOperation)->amount())); |
- effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_SATURATE, inputParameters); |
+ effect = FEColorMatrix::create(parentFilter.get(), FECOLORMATRIX_TYPE_SATURATE, inputParameters); |
break; |
} |
case FilterOperation::HUE_ROTATE: { |
Vector<float> inputParameters; |
inputParameters.append(narrowPrecisionToFloat(toBasicColorMatrixFilterOperation(filterOperation)->amount())); |
- effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_HUEROTATE, inputParameters); |
+ effect = FEColorMatrix::create(parentFilter.get(), FECOLORMATRIX_TYPE_HUEROTATE, inputParameters); |
break; |
} |
case FilterOperation::INVERT: { |
@@ -171,7 +171,7 @@ bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations& |
transferFunction.tableValues = transferParameters; |
ComponentTransferFunction nullFunction; |
- effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); |
+ effect = FEComponentTransfer::create(parentFilter.get(), transferFunction, transferFunction, transferFunction, nullFunction); |
break; |
} |
case FilterOperation::OPACITY: { |
@@ -183,7 +183,7 @@ bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations& |
transferFunction.tableValues = transferParameters; |
ComponentTransferFunction nullFunction; |
- effect = FEComponentTransfer::create(this, nullFunction, nullFunction, nullFunction, transferFunction); |
+ effect = FEComponentTransfer::create(parentFilter.get(), nullFunction, nullFunction, nullFunction, transferFunction); |
break; |
} |
case FilterOperation::BRIGHTNESS: { |
@@ -193,7 +193,7 @@ bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations& |
transferFunction.intercept = 0; |
ComponentTransferFunction nullFunction; |
- effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); |
+ effect = FEComponentTransfer::create(parentFilter.get(), transferFunction, transferFunction, transferFunction, nullFunction); |
break; |
} |
case FilterOperation::CONTRAST: { |
@@ -204,12 +204,12 @@ bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations& |
transferFunction.intercept = -0.5 * amount + 0.5; |
ComponentTransferFunction nullFunction; |
- effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction); |
+ effect = FEComponentTransfer::create(parentFilter.get(), transferFunction, transferFunction, transferFunction, nullFunction); |
break; |
} |
case FilterOperation::BLUR: { |
float stdDeviation = floatValueForLength(toBlurFilterOperation(filterOperation)->stdDeviation(), 0); |
- effect = FEGaussianBlur::create(this, stdDeviation, stdDeviation); |
+ effect = FEGaussianBlur::create(parentFilter.get(), stdDeviation, stdDeviation); |
break; |
} |
case FilterOperation::DROP_SHADOW: { |
@@ -217,7 +217,7 @@ bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations& |
float stdDeviation = dropShadowOperation->stdDeviation(); |
float x = dropShadowOperation->x(); |
float y = dropShadowOperation->y(); |
- effect = FEDropShadow::create(this, stdDeviation, stdDeviation, x, y, dropShadowOperation->color(), 1); |
+ effect = FEDropShadow::create(parentFilter.get(), stdDeviation, stdDeviation, x, y, dropShadowOperation->color(), 1); |
break; |
} |
default: |
@@ -235,6 +235,8 @@ bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations& |
} |
} |
+ m_referenceFilters.append(parentFilter); |
+ |
// We need to keep the old effects alive until this point, so that SVG reference filters |
// can share cached resources across frames. |
m_lastEffect = previousEffect; |
@@ -246,75 +248,30 @@ bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations& |
return true; |
} |
-void FilterEffectRenderer::updateBackingStoreRect(const FloatRect& floatFilterRect) |
-{ |
- IntRect filterRect = enclosingIntRect(floatFilterRect); |
- if (!filterRect.isEmpty() && FilterEffect::isFilterSizeValid(filterRect)) { |
- setSourceImageRect(filterRect); |
- } |
-} |
- |
void FilterEffectRenderer::clearIntermediateResults() |
{ |
if (m_lastEffect.get()) |
m_lastEffect->clearResultsRecursive(); |
} |
-LayoutRect FilterEffectRenderer::computeSourceImageRectForDirtyRect(const LayoutRect& dirtyRect) |
-{ |
- // The result of this function is the area that needs paint invalidation, so that we fully cover the "dirtyRect". |
- FloatRect rectForPaintInvalidation = dirtyRect; |
- float inf = std::numeric_limits<float>::infinity(); |
- FloatRect clipRect = FloatRect(FloatPoint(-inf, -inf), FloatSize(inf, inf)); |
- rectForPaintInvalidation = lastEffect()->getSourceRect(rectForPaintInvalidation, clipRect); |
- return LayoutRect(rectForPaintInvalidation); |
-} |
- |
-bool FilterEffectRendererHelper::prepareFilterEffect(RenderLayer* renderLayer, const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect) |
-{ |
- ASSERT(m_haveFilterEffect && renderLayer->filterRenderer()); |
- m_renderLayer = renderLayer; |
- |
- FilterEffectRenderer* filter = renderLayer->filterRenderer(); |
- |
- IntRect filterSourceRect = pixelSnappedIntRect(filter->computeSourceImageRectForDirtyRect(dirtyRect)); |
- |
- if (filterSourceRect.isEmpty()) { |
- // The dirty rect is not in view, just bail out. |
- m_haveFilterEffect = false; |
- return false; |
- } |
- |
- m_filterBoxRect = filterBoxRect; |
- filter->lastEffect()->determineFilterPrimitiveSubregion(MapRectForward); |
- |
- filter->updateBackingStoreRect(filterSourceRect); |
- return true; |
-} |
- |
-void FilterEffectRendererHelper::beginFilterEffect(GraphicsContext* context) |
+bool FilterEffectRenderer::beginFilterEffect(GraphicsContext* context, const FloatRect& filterBoxRect) |
{ |
- ASSERT(m_renderLayer); |
- |
- FilterEffectRenderer* filter = m_renderLayer->filterRenderer(); |
SkiaImageFilterBuilder builder(context); |
- RefPtr<ImageFilter> imageFilter = builder.build(filter->lastEffect().get(), ColorSpaceDeviceRGB); |
- if (!imageFilter) { |
- m_haveFilterEffect = false; |
- return; |
- } |
+ m_lastEffect->determineFilterPrimitiveSubregion(MapRectForward); |
+ RefPtr<ImageFilter> imageFilter = builder.build(m_lastEffect.get(), ColorSpaceDeviceRGB); |
+ if (!imageFilter) |
+ return false; |
context->save(); |
- FloatRect boundaries = mapImageFilterRect(imageFilter.get(), m_filterBoxRect); |
- context->translate(m_filterBoxRect.x(), m_filterBoxRect.y()); |
- boundaries.move(-m_filterBoxRect.x(), -m_filterBoxRect.y()); |
+ FloatRect boundaries = mapImageFilterRect(imageFilter.get(), filterBoxRect); |
+ context->translate(filterBoxRect.x(), filterBoxRect.y()); |
+ boundaries.move(-filterBoxRect.x(), -filterBoxRect.y()); |
context->beginLayer(1, CompositeSourceOver, &boundaries, ColorFilterNone, imageFilter.get()); |
- context->translate(-m_filterBoxRect.x(), -m_filterBoxRect.y()); |
+ context->translate(-filterBoxRect.x(), -filterBoxRect.y()); |
+ return true; |
} |
-void FilterEffectRendererHelper::endFilterEffect(GraphicsContext* context) |
+void FilterEffectRenderer::endFilterEffect(GraphicsContext* context) |
{ |
- ASSERT(m_haveFilterEffect && m_renderLayer->filterRenderer()); |
- |
context->endLayer(); |
context->restore(); |
} |