Bug 796847 - Make AdjustInvalidAreaForSVGEffects correctly adjust for the coordinate space of the input rect. r=dholbert

This commit is contained in:
Matt Woodrow 2012-11-28 17:06:07 +13:00
parent 98607acc14
commit 489b64c3b6
6 changed files with 57 additions and 5 deletions

View File

@ -2407,7 +2407,9 @@ FrameLayerBuilder::AddThebesDisplayItem(ThebesLayer* aLayer,
props->MoveBy(-offset);
nsIntRegion invalid = props->ComputeDifferences(layer, nullptr);
if (aLayerState == LAYER_SVG_EFFECTS) {
invalid = nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(aItem->GetUnderlyingFrame(), invalid.GetBounds());
invalid = nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(aItem->GetUnderlyingFrame(),
aItem->ToReferenceFrame(),
invalid.GetBounds());
}
if (!invalid.IsEmpty()) {
#ifdef DEBUG_INVALIDATIONS

View File

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg">
<filter id="f" x="0" y="0" width="100%" height="100%">
<feGaussianBlur in="SourceGraphic" stdDeviation="0.1"/>
</filter>
<g filter="url(#f)">
<rect x="0" y="0" width="100" height="100" style="fill: lime;"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 276 B

View File

@ -0,0 +1,25 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" class="reftest-wait">
<title>Test that the area that's covered by a filtered elemnt is invalidated when content inside it changes</title>
<filter id="f" x="0" y="0" width="100%" height="100">
<feGaussianBlur in="SourceGraphic" stdDeviation="0.1"/>
</filter>
<script type="text/javascript">//<![CDATA[
function doTest()
{
var e = document.getElementsByTagName("rect")[0];
e.style.fill = "lime";
document.documentElement.removeAttribute('class');
}
document.addEventListener("MozReftestInvalidate", doTest, false);
//]]></script>
<g filter="url(#f)">
<rect x="0" y="0" width="100" height="100" style="fill: red;"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 828 B

View File

@ -1725,6 +1725,7 @@ fuzzy-if(true,17,5859) == 759036-2.html 759036-2-ref.html
== 776265-2c.html 776265-2-ref.html
== 776265-2d.html 776265-2-ref.html
== 787947-1.html 787947-1-ref.html
== 796847.svg 796847-ref.svg
fuzzy(40,800) == 797797-1.html 797797-1-ref.html # 'opacity:N' and rgba(,,,N) text don't match precisely
fuzzy(40,800) == 797797-2.html 797797-2-ref.html # 'opacity:N' and rgba(,,,N) text don't match precisely
== 801994-1.html 801994-1-ref.html

View File

@ -282,6 +282,7 @@ nsRect
nsIntRect
nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(nsIFrame* aFrame,
const nsPoint& aToReferenceFrame,
const nsIntRect& aInvalidRect)
{
// Don't bother calling GetEffectProperties; the filter property should
@ -304,19 +305,25 @@ nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(nsIFrame* aFrame,
if (!filterFrame) {
// The frame is either not there or not currently available,
// perhaps because we're in the middle of tearing stuff down.
// Be conservative.
nsRect overflow = aFrame->GetVisualOverflowRect();
// Be conservative, return our visual overflow rect relative
// to the reference frame.
nsRect overflow = aFrame->GetVisualOverflowRect() + aToReferenceFrame;
return overflow.ToOutsidePixels(appUnitsPerDevPixel);
}
// Convert aInvalidRect into "user space" in app units:
nsPoint toUserSpace =
aFrame->GetOffsetTo(firstFrame) + GetOffsetToUserSpace(firstFrame);
// The initial rect was relative to the reference frame, so we need to
// remove that offset to get a rect relative to the current frame.
toUserSpace -= aToReferenceFrame;
nsRect preEffectsRect = aInvalidRect.ToAppUnits(appUnitsPerDevPixel) + toUserSpace;
// Return ther result, relative to aFrame, not in user space:
// Adjust the dirty area for effects, and shift it back to being relative to
// the reference frame.
nsRect result = filterFrame->GetPostFilterDirtyArea(firstFrame, preEffectsRect) -
toUserSpace;
// Return the result, in pixels relative to the reference frame.
return result.ToOutsidePixels(appUnitsPerDevPixel);
}

View File

@ -115,9 +115,18 @@ public:
/**
* Used to adjust the area of a frame that needs to be invalidated to take
* account of SVG effects.
*
* @param aFrame The effects frame.
* @param aToReferenceFrame The offset (in app units) from aFrame to its
* reference display item.
* @param aInvalidRect The pre-effects invalid rect in pixels relative to
* the reference display item.
* @return The post-effects invalid rect in pixels relative to the reference
* display item.
*/
static nsIntRect
AdjustInvalidAreaForSVGEffects(nsIFrame* aFrame, const nsIntRect& aInvalidRect);
AdjustInvalidAreaForSVGEffects(nsIFrame* aFrame, const nsPoint& aToReferenceFrame,
const nsIntRect& aInvalidRect);
/**
* Figure out which area of the source is needed given an area to