Bug 616892 - Make more updates honour suspendRedraw. r=roc

This commit is contained in:
Robert Longson 2012-02-04 13:58:46 +00:00
Родитель bb233a8dab
Коммит cb47632788
31 изменённых файлов: 373 добавлений и 232 удалений

Просмотреть файл

@ -39,7 +39,6 @@
#include "nsSVGSwitchElement.h"
#include "DOMSVGTests.h"
#include "nsIFrame.h"
#include "nsISVGChildFrame.h"
#include "nsSVGUtils.h"
#include "mozilla/Preferences.h"
@ -89,7 +88,7 @@ void
nsSVGSwitchElement::MaybeInvalidate()
{
// We don't reuse UpdateActiveChild() and check if mActiveChild has changed
// to determine if we should call nsSVGUtils::UpdateGraphic. If we did that,
// to determine if we should invalidate. If we did that,
// nsSVGUtils::UpdateGraphic would not invalidate the old mActiveChild area!
if (FindActiveChild() == mActiveChild) {
@ -98,10 +97,7 @@ nsSVGSwitchElement::MaybeInvalidate()
nsIFrame *frame = GetPrimaryFrame();
if (frame) {
nsISVGChildFrame* svgFrame = do_QueryFrame(frame);
if (svgFrame) {
nsSVGUtils::UpdateGraphic(svgFrame);
}
nsSVGUtils::UpdateGraphic(frame);
}
}

Просмотреть файл

@ -145,7 +145,6 @@
#include "DOMSVGTests.h"
#include "nsSVGEffects.h"
#include "nsSVGUtils.h"
#include "nsSVGOuterSVGFrame.h"
#include "nsRefreshDriver.h"
#include "nsRuleProcessorData.h"
@ -7686,23 +7685,7 @@ DoApplyRenderingChangeToTree(nsIFrame* aFrame,
// if frame has view, will already be invalidated
if (aChange & nsChangeHint_RepaintFrame) {
if (aFrame->IsFrameOfType(nsIFrame::eSVG)) {
if (!(aFrame->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(aFrame);
if (outerSVGFrame) {
// We need this to invalidate frames when their 'filter' or 'marker'
// property changes. XXX in theory changes to 'marker' should be
// handled in nsSVGPathGeometryFrame::DidSetStyleContext, but for
// some reason that's broken.
//
// This call is also currently the only mechanism for invalidating
// the area covered by a <foreignObject> when 'opacity' changes on
// it or one of its ancestors. (For 'opacity' changes on <image> or
// a graphical element such as <path>, or on one of their
// ancestors, this is redundant since
// nsSVGPathGeometryFrame::DidSetStyleContext also invalidates.)
outerSVGFrame->UpdateAndInvalidateCoveredRegion(aFrame);
}
}
nsSVGUtils::UpdateGraphic(aFrame);
} else {
aFrame->InvalidateOverflowRect();
}

Просмотреть файл

@ -217,9 +217,17 @@ random-if(gtk2Widget) == objectBoundingBox-and-fePointLight-02.svg objectBoundin
== style-without-type-attribute.svg pass.svg
== svg-in-foreignObject-01.xhtml svg-in-foreignObject-01-ref.xhtml
== svg-in-foreignObject-02.xhtml svg-in-foreignObject-01-ref.xhtml # reuse -01-ref.xhtml
random-if(gtk2Widget) == text-font-weight-01.svg text-font-weight-01-ref.svg # bug 386713
== switch-01.svg pass.svg
== suspend-01.svg about:blank
== suspend-02.svg pass.svg
fails == suspend-03.svg pass.svg # bug 724242
== suspend-04.svg pass.svg
== suspend-05.svg pass.svg
== suspend-06.svg pass.svg
== suspend-07.svg pass.svg
== suspend-08.svg pass.svg
== symbol-01.svg symbol-01-ref.svg
random-if(gtk2Widget) == text-font-weight-01.svg text-font-weight-01-ref.svg # bug 386713
== text-gradient-01.svg text-gradient-01-ref.svg
random-if(winWidget) == text-gradient-02.svg text-gradient-02-ref.svg # see bug 590101
== text-gradient-03.svg pass.svg

Просмотреть файл

@ -0,0 +1,14 @@
<?xml version="1.0"?>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<svg xmlns="http://www.w3.org/2000/svg">
<title>Test that suspendRedraw works</title>
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=615146 -->
<rect width="100%" height="100%" fill="red"/>
<script>
document.documentElement.suspendRedraw(10000);
</script>
</svg>

После

Ширина:  |  Высота:  |  Размер: 421 B

Просмотреть файл

@ -0,0 +1,23 @@
<?xml version="1.0"?>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait" onload="f()">
<title>Test that suspendRedraw works</title>
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=615146 -->
<script>
function f() {
var svg = document.documentElement;
setTimeout(function() {
svg.suspendRedraw(10000);
setTimeout(function() {
document.getElementById("r").setAttribute("fill", "red");
svg.removeAttribute("class");
}, 1);
}, 1);
}
</script>
<rect id="r" width="100%" height="100%" fill="lime"/>
</svg>

После

Ширина:  |  Высота:  |  Размер: 711 B

Просмотреть файл

@ -0,0 +1,24 @@
<?xml version="1.0"?>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait" onload="f()">
<title>Test that suspendRedraw works</title>
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=615146 -->
<script>
function f() {
var svg = document.documentElement;
setTimeout(function() {
svg.suspendRedraw(10000);
setTimeout(function() {
svg.removeChild(document.getElementById("r"));
svg.removeAttribute("class");
}, 1);
}, 1);
}
</script>
<rect width="100%" height="100%" fill="red"/>
<rect id="r" width="100%" height="100%" fill="lime"/>
</svg>

После

Ширина:  |  Высота:  |  Размер: 748 B

Просмотреть файл

@ -0,0 +1,27 @@
<?xml version="1.0"?>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait" onload="f()">
<title>Test that suspendRedraw works</title>
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=615146 -->
<script>
function f() {
var svg = document.documentElement;
setTimeout(function() {
svg.suspendRedraw(10000);
setTimeout(function() {
var r = document.createElementNS("http://www.w3.org/2000/svg", "rect");
r.setAttribute("width", "100%");
r.setAttribute("height", "100%");
r.setAttribute("fill", "red");
svg.appendChild(r);
svg.removeAttribute("class");
}, 1);
}, 1);
}
</script>
<rect width="100%" height="100%" fill="lime"/>
</svg>

После

Ширина:  |  Высота:  |  Размер: 876 B

Просмотреть файл

@ -0,0 +1,21 @@
<?xml version="1.0"?>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait" onload="f()">
<title>Test that unsuspendRedrawAll works</title>
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=615146 -->
<script>
function f() {
var svg = document.documentElement;
svg.suspendRedraw(10000);
setTimeout(function() {
svg.unsuspendRedrawAll();
svg.removeAttribute("class");
}, 1);
}
</script>
<rect width="100%" height="100%" fill="lime"/>
</svg>

После

Ширина:  |  Высота:  |  Размер: 624 B

Просмотреть файл

@ -0,0 +1,24 @@
<?xml version="1.0"?>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait" onload="f()">
<title>Test that unsuspendRedrawAll works</title>
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=615146 -->
<script>
function f() {
var svg = document.documentElement;
setTimeout(function() {
svg.suspendRedraw(10000);
setTimeout(function() {
document.getElementById("r").setAttribute("fill", "lime");
svg.unsuspendRedrawAll();
svg.removeAttribute("class");
}, 1);
}, 1);
}
</script>
<rect id="r" width="100%" height="100%" fill="red"/>
</svg>

После

Ширина:  |  Высота:  |  Размер: 752 B

Просмотреть файл

@ -0,0 +1,25 @@
<?xml version="1.0"?>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait" onload="f()">
<title>Test that unsuspendRedrawAll works</title>
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=615146 -->
<script>
function f() {
var svg = document.documentElement;
setTimeout(function() {
svg.suspendRedraw(10000);
setTimeout(function() {
svg.removeChild(document.getElementById("r"));
svg.unsuspendRedrawAll();
svg.removeAttribute("class");
}, 1);
}, 1);
}
</script>
<rect width="100%" height="100%" fill="lime"/>
<rect id="r" width="100%" height="100%" fill="red"/>
</svg>

После

Ширина:  |  Высота:  |  Размер: 789 B

Просмотреть файл

@ -0,0 +1,28 @@
<?xml version="1.0"?>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait" onload="f()">
<title>Test that unsuspendRedrawAll works</title>
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=615146 -->
<script>
function f() {
var svg = document.documentElement;
setTimeout(function() {
svg.suspendRedraw(10000);
setTimeout(function() {
var r = document.createElementNS("http://www.w3.org/2000/svg", "rect");
r.setAttribute("width", "100%");
r.setAttribute("height", "100%");
r.setAttribute("fill", "lime");
svg.appendChild(r);
svg.unsuspendRedrawAll();
svg.removeAttribute("class");
}, 1);
}, 1);
}
</script>
<rect width="100%" height="100%" fill="red"/>
</svg>

После

Ширина:  |  Высота:  |  Размер: 917 B

Просмотреть файл

@ -102,8 +102,8 @@ public:
COORD_CONTEXT_CHANGED = 0x04
};
virtual void NotifySVGChanged(PRUint32 aFlags)=0;
NS_IMETHOD NotifyRedrawSuspended()=0;
NS_IMETHOD NotifyRedrawUnsuspended()=0;
virtual void NotifyRedrawSuspended()=0;
virtual void NotifyRedrawUnsuspended()=0;
/**
* Get this frame's contribution to the rect returned by a GetBBox() call

Просмотреть файл

@ -46,9 +46,9 @@ class nsISVGSVGFrame
public:
NS_DECL_QUERYFRAME_TARGET(nsISVGSVGFrame)
NS_IMETHOD SuspendRedraw()=0;
NS_IMETHOD UnsuspendRedraw()=0;
NS_IMETHOD NotifyViewportChange()=0;
virtual void SuspendRedraw()=0;
virtual void UnsuspendRedraw()=0;
virtual void NotifyViewportChange()=0;
};
#endif // __NS_ISVGSVGFRAME_H__

Просмотреть файл

@ -105,7 +105,8 @@ nsSVGDisplayContainerFrame::Init(nsIContent* aContent,
{
if (!(GetStateBits() & NS_STATE_IS_OUTER_SVG)) {
AddStateBits(aParent->GetStateBits() &
(NS_STATE_SVG_NONDISPLAY_CHILD | NS_STATE_SVG_CLIPPATH_CHILD));
(NS_STATE_SVG_NONDISPLAY_CHILD | NS_STATE_SVG_CLIPPATH_CHILD |
NS_STATE_SVG_REDRAW_SUSPENDED));
}
nsresult rv = nsSVGContainerFrameBase::Init(aContent, aParent, aPrevInFlow);
return rv;
@ -145,11 +146,14 @@ NS_IMETHODIMP
nsSVGDisplayContainerFrame::RemoveFrame(ChildListID aListID,
nsIFrame* aOldFrame)
{
// Force the invalidation before it's too late
RemoveStateBits(NS_STATE_SVG_REDRAW_SUSPENDED);
nsSVGUtils::InvalidateCoveredRegion(aOldFrame);
nsresult rv = nsSVGContainerFrame::RemoveFrame(aListID, aOldFrame);
if (!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
if (!(GetStateBits() & (NS_STATE_SVG_NONDISPLAY_CHILD | NS_STATE_IS_OUTER_SVG))) {
nsSVGUtils::NotifyAncestorsOfFilterRegionChange(this);
}
@ -234,30 +238,16 @@ nsSVGDisplayContainerFrame::NotifySVGChanged(PRUint32 aFlags)
nsSVGUtils::NotifyChildrenOfSVGChange(this, aFlags);
}
NS_IMETHODIMP
void
nsSVGDisplayContainerFrame::NotifyRedrawSuspended()
{
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
if (SVGFrame) {
SVGFrame->NotifyRedrawSuspended();
}
}
return NS_OK;
nsSVGUtils::NotifyRedrawSuspended(this);
}
NS_IMETHODIMP
void
nsSVGDisplayContainerFrame::NotifyRedrawUnsuspended()
{
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
if (SVGFrame) {
SVGFrame->NotifyRedrawUnsuspended();
}
}
return NS_OK;
nsSVGUtils::NotifyRedrawUnsuspended(this);
}
gfxRect

Просмотреть файл

@ -110,8 +110,8 @@ public:
NS_IMETHOD UpdateCoveredRegion();
NS_IMETHOD InitialUpdate();
virtual void NotifySVGChanged(PRUint32 aFlags);
NS_IMETHOD NotifyRedrawSuspended();
NS_IMETHOD NotifyRedrawUnsuspended();
virtual void NotifyRedrawSuspended();
virtual void NotifyRedrawUnsuspended();
virtual gfxRect GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
PRUint32 aFlags);
NS_IMETHOD_(bool) IsDisplayContainer() { return true; }

Просмотреть файл

@ -91,7 +91,8 @@ nsSVGForeignObjectFrame::Init(nsIContent* aContent,
nsresult rv = nsSVGForeignObjectFrameBase::Init(aContent, aParent, aPrevInFlow);
AddStateBits(aParent->GetStateBits() &
(NS_STATE_SVG_NONDISPLAY_CHILD | NS_STATE_SVG_CLIPPATH_CHILD));
(NS_STATE_SVG_NONDISPLAY_CHILD | NS_STATE_SVG_CLIPPATH_CHILD |
NS_STATE_SVG_REDRAW_SUSPENDED));
if (NS_SUCCEEDED(rv)) {
nsSVGUtils::GetOuterSVGFrame(this)->RegisterForeignObject(this);
}
@ -439,15 +440,17 @@ nsSVGForeignObjectFrame::NotifySVGChanged(PRUint32 aFlags)
}
}
NS_IMETHODIMP
void
nsSVGForeignObjectFrame::NotifyRedrawSuspended()
{
return NS_OK;
AddStateBits(NS_STATE_SVG_REDRAW_SUSPENDED);
}
NS_IMETHODIMP
void
nsSVGForeignObjectFrame::NotifyRedrawUnsuspended()
{
RemoveStateBits(NS_STATE_SVG_REDRAW_SUSPENDED);
if (!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
if (GetStateBits() & NS_STATE_SVG_DIRTY) {
UpdateGraphic(); // invalidate our entire area
@ -455,7 +458,6 @@ nsSVGForeignObjectFrame::NotifyRedrawUnsuspended()
FlushDirtyRegion(0); // only invalidate areas dirtied by our descendants
}
}
return NS_OK;
}
gfxRect
@ -665,7 +667,8 @@ void
nsSVGForeignObjectFrame::FlushDirtyRegion(PRUint32 aFlags)
{
if ((mSameDocDirtyRegion.IsEmpty() && mSubDocDirtyRegion.IsEmpty()) ||
mInReflow)
mInReflow ||
(GetStateBits() & NS_STATE_SVG_REDRAW_SUSPENDED))
return;
nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
@ -674,9 +677,6 @@ nsSVGForeignObjectFrame::FlushDirtyRegion(PRUint32 aFlags)
return;
}
if (outerSVGFrame->IsRedrawSuspended())
return;
InvalidateDirtyRect(outerSVGFrame, mSameDocDirtyRegion.GetBounds(), aFlags);
InvalidateDirtyRect(outerSVGFrame, mSubDocDirtyRegion.GetBounds(),
aFlags | INVALIDATE_CROSS_DOC);

Просмотреть файл

@ -128,8 +128,8 @@ public:
NS_IMETHOD UpdateCoveredRegion();
NS_IMETHOD InitialUpdate();
virtual void NotifySVGChanged(PRUint32 aFlags);
NS_IMETHOD NotifyRedrawSuspended();
NS_IMETHOD NotifyRedrawUnsuspended();
virtual void NotifyRedrawSuspended();
virtual void NotifyRedrawUnsuspended();
virtual gfxRect GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
PRUint32 aFlags);
NS_IMETHOD_(bool) IsDisplayContainer() { return true; }

Просмотреть файл

@ -54,7 +54,8 @@ nsSVGGeometryFrame::Init(nsIContent* aContent,
nsIFrame* aPrevInFlow)
{
AddStateBits(aParent->GetStateBits() &
(NS_STATE_SVG_NONDISPLAY_CHILD | NS_STATE_SVG_CLIPPATH_CHILD));
(NS_STATE_SVG_NONDISPLAY_CHILD | NS_STATE_SVG_CLIPPATH_CHILD |
NS_STATE_SVG_REDRAW_SUSPENDED));
nsresult rv = nsSVGGeometryFrameBase::Init(aContent, aParent, aPrevInFlow);
return rv;
}

Просмотреть файл

@ -525,20 +525,19 @@ nsSVGGlyphFrame::NotifySVGChanged(PRUint32 aFlags)
}
}
NS_IMETHODIMP
void
nsSVGGlyphFrame::NotifyRedrawSuspended()
{
// XXX should we cache the fact that redraw is suspended?
return NS_OK;
AddStateBits(NS_STATE_SVG_REDRAW_SUSPENDED);
}
NS_IMETHODIMP
void
nsSVGGlyphFrame::NotifyRedrawUnsuspended()
{
RemoveStateBits(NS_STATE_SVG_REDRAW_SUSPENDED);
if (GetStateBits() & NS_STATE_SVG_DIRTY)
nsSVGUtils::UpdateGraphic(this);
return NS_OK;
}
void

Просмотреть файл

@ -182,8 +182,8 @@ public:
NS_IMETHOD_(nsRect) GetCoveredRegion();
NS_IMETHOD InitialUpdate();
virtual void NotifySVGChanged(PRUint32 aFlags);
NS_IMETHOD NotifyRedrawSuspended();
NS_IMETHOD NotifyRedrawUnsuspended();
virtual void NotifyRedrawSuspended();
virtual void NotifyRedrawUnsuspended();
NS_IMETHOD_(bool) IsDisplayContainer() { return false; }
NS_IMETHOD_(bool) HasValidCoveredRect() {
return !(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD);

Просмотреть файл

@ -39,7 +39,6 @@
#include "nsSVGInnerSVGFrame.h"
#include "nsIFrame.h"
#include "nsISVGChildFrame.h"
#include "nsSVGOuterSVGFrame.h"
#include "nsIDOMSVGAnimatedRect.h"
#include "nsSVGSVGElement.h"
#include "nsSVGContainerFrame.h"
@ -216,33 +215,28 @@ nsSVGInnerSVGFrame::GetFrameForPoint(const nsPoint &aPoint)
//----------------------------------------------------------------------
// nsISVGSVGFrame methods:
NS_IMETHODIMP
void
nsSVGInnerSVGFrame::SuspendRedraw()
{
nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
if (!outerSVGFrame) {
NS_ERROR("no outer svg frame");
return NS_ERROR_FAILURE;
}
return outerSVGFrame->SuspendRedraw();
if (GetParent()->GetStateBits() & NS_STATE_SVG_REDRAW_SUSPENDED)
return;
nsSVGUtils::NotifyRedrawSuspended(this);
}
NS_IMETHODIMP
void
nsSVGInnerSVGFrame::UnsuspendRedraw()
{
nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
if (!outerSVGFrame) {
NS_ERROR("no outer svg frame");
return NS_ERROR_FAILURE;
}
return outerSVGFrame->UnsuspendRedraw();
if (GetParent()->GetStateBits() & NS_STATE_SVG_REDRAW_SUSPENDED)
return;
nsSVGUtils::NotifyRedrawUnsuspended(this);
}
NS_IMETHODIMP
void
nsSVGInnerSVGFrame::NotifyViewportChange()
{
NS_ERROR("Inner SVG frames should not get Viewport changes.");
return NS_ERROR_FAILURE;
}
//----------------------------------------------------------------------

Просмотреть файл

@ -89,9 +89,9 @@ public:
virtual gfxMatrix GetCanvasTM();
// nsISVGSVGFrame interface:
NS_IMETHOD SuspendRedraw();
NS_IMETHOD UnsuspendRedraw();
NS_IMETHOD NotifyViewportChange();
virtual void SuspendRedraw();
virtual void UnsuspendRedraw();
virtual void NotifyViewportChange();
protected:

Просмотреть файл

@ -141,7 +141,7 @@ NS_IMPL_FRAMEARENA_HELPERS(nsSVGOuterSVGFrame)
nsSVGOuterSVGFrame::nsSVGOuterSVGFrame(nsStyleContext* aContext)
: nsSVGOuterSVGFrameBase(aContext)
, mRedrawSuspendCount(0)
, mRedrawSuspendCount(0)
, mFullZoom(0)
, mViewportInitialized(false)
#ifdef XP_MACOSX
@ -681,97 +681,35 @@ nsSVGOuterSVGFrame::GetType() const
return nsGkAtoms::svgOuterSVGFrame;
}
//----------------------------------------------------------------------
// nsSVGOuterSVGFrame methods:
void
nsSVGOuterSVGFrame::InvalidateCoveredRegion(nsIFrame *aFrame)
{
// Make sure elements styled by :hover get updated if script/animation moves
// them under or out from under the pointer:
PresContext()->PresShell()->SynthesizeMouseMove(false);
nsISVGChildFrame *svgFrame = do_QueryFrame(aFrame);
if (!svgFrame)
return;
nsRect rect = nsSVGUtils::FindFilterInvalidation(aFrame, svgFrame->GetCoveredRegion());
Invalidate(rect);
}
bool
nsSVGOuterSVGFrame::UpdateAndInvalidateCoveredRegion(nsIFrame *aFrame)
{
// Make sure elements styled by :hover get updated if script/animation moves
// them under or out from under the pointer:
PresContext()->PresShell()->SynthesizeMouseMove(false);
nsISVGChildFrame *svgFrame = do_QueryFrame(aFrame);
if (!svgFrame)
return false;
nsRect oldRegion = svgFrame->GetCoveredRegion();
Invalidate(nsSVGUtils::FindFilterInvalidation(aFrame, oldRegion));
svgFrame->UpdateCoveredRegion();
nsRect newRegion = svgFrame->GetCoveredRegion();
if (oldRegion.IsEqualInterior(newRegion))
return false;
Invalidate(nsSVGUtils::FindFilterInvalidation(aFrame, newRegion));
return true;
}
bool
nsSVGOuterSVGFrame::IsRedrawSuspended()
{
return (mRedrawSuspendCount>0) || !mViewportInitialized;
}
//----------------------------------------------------------------------
// nsISVGSVGFrame methods:
NS_IMETHODIMP
void
nsSVGOuterSVGFrame::SuspendRedraw()
{
if (++mRedrawSuspendCount != 1)
return NS_OK;
return;
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
if (SVGFrame) {
SVGFrame->NotifyRedrawSuspended();
}
}
return NS_OK;
nsSVGUtils::NotifyRedrawSuspended(this);
}
NS_IMETHODIMP
void
nsSVGOuterSVGFrame::UnsuspendRedraw()
{
NS_ASSERTION(mRedrawSuspendCount >=0, "unbalanced suspend count!");
if (--mRedrawSuspendCount > 0)
return NS_OK;
return;
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
if (SVGFrame) {
SVGFrame->NotifyRedrawUnsuspended();
}
}
return NS_OK;
nsSVGUtils::NotifyRedrawUnsuspended(this);
}
NS_IMETHODIMP
void
nsSVGOuterSVGFrame::NotifyViewportChange()
{
// no point in doing anything when were not init'ed yet:
if (!mViewportInitialized) {
return NS_OK;
return;
}
PRUint32 flags = COORD_CONTEXT_CHANGED;
@ -790,10 +728,7 @@ nsSVGOuterSVGFrame::NotifyViewportChange()
}
// inform children
SuspendRedraw();
nsSVGUtils::NotifyChildrenOfSVGChange(this, flags);
UnsuspendRedraw();
return NS_OK;
}
//----------------------------------------------------------------------

Просмотреть файл

@ -124,21 +124,10 @@ public:
nsIAtom* aAttribute,
PRInt32 aModType);
// nsSVGOuterSVGFrame methods:
void InvalidateCoveredRegion(nsIFrame *aFrame);
// Calls aSVG->UpdateCoveredRegion and returns true if the covered
// region actually changed. If it changed, invalidates the old and new
// covered regions, taking filters into account, like
// InvalidateCoveredRegion.
bool UpdateAndInvalidateCoveredRegion(nsIFrame *aFrame);
bool IsRedrawSuspended();
// nsISVGSVGFrame interface:
NS_IMETHOD SuspendRedraw();
NS_IMETHOD UnsuspendRedraw();
NS_IMETHOD NotifyViewportChange();
virtual void SuspendRedraw();
virtual void UnsuspendRedraw();
virtual void NotifyViewportChange();
// nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM();
@ -169,9 +158,9 @@ protected:
// subtree if we were to use a list (see bug 381285 comment 20).
nsTHashtable<nsVoidPtrHashKey> mForeignObjectHash;
PRUint32 mRedrawSuspendCount;
nsAutoPtr<gfxMatrix> mCanvasTM;
PRUint32 mRedrawSuspendCount;
float mFullZoom;
bool mViewportInitialized;

Просмотреть файл

@ -236,20 +236,19 @@ nsSVGPathGeometryFrame::NotifySVGChanged(PRUint32 aFlags)
}
}
NS_IMETHODIMP
void
nsSVGPathGeometryFrame::NotifyRedrawSuspended()
{
// XXX should we cache the fact that redraw is suspended?
return NS_OK;
AddStateBits(NS_STATE_SVG_REDRAW_SUSPENDED);
}
NS_IMETHODIMP
void
nsSVGPathGeometryFrame::NotifyRedrawUnsuspended()
{
RemoveStateBits(NS_STATE_SVG_REDRAW_SUSPENDED);
if (GetStateBits() & NS_STATE_SVG_DIRTY)
nsSVGUtils::UpdateGraphic(this);
return NS_OK;
}
gfxRect

Просмотреть файл

@ -96,8 +96,8 @@ protected:
NS_IMETHOD UpdateCoveredRegion();
NS_IMETHOD InitialUpdate();
virtual void NotifySVGChanged(PRUint32 aFlags);
NS_IMETHOD NotifyRedrawSuspended();
NS_IMETHOD NotifyRedrawUnsuspended();
virtual void NotifyRedrawSuspended();
virtual void NotifyRedrawUnsuspended();
virtual gfxRect GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
PRUint32 aFlags);
NS_IMETHOD_(bool) IsDisplayContainer() { return false; }

Просмотреть файл

@ -80,7 +80,7 @@ public:
NS_IMETHODIMP_(nsRect) GetCoveredRegion();
NS_IMETHOD UpdateCoveredRegion();
NS_IMETHOD InitialUpdate();
NS_IMETHOD NotifyRedrawUnsuspended();
virtual void NotifyRedrawUnsuspended();
virtual gfxRect GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
PRUint32 aFlags);
@ -186,13 +186,15 @@ nsSVGSwitchFrame::InitialUpdate()
return nsSVGSwitchFrameBase::InitialUpdate();
}
NS_IMETHODIMP
void
nsSVGSwitchFrame::NotifyRedrawUnsuspended()
{
RemoveStateBits(NS_STATE_SVG_REDRAW_SUSPENDED);
if (GetStateBits() & NS_STATE_SVG_DIRTY)
nsSVGUtils::UpdateGraphic(this);
return nsSVGSwitchFrameBase::NotifyRedrawUnsuspended();
nsSVGSwitchFrameBase::NotifyRedrawUnsuspended();
}
gfxRect

Просмотреть файл

@ -209,20 +209,13 @@ nsSVGTextFrame::NotifySVGChanged(PRUint32 aFlags)
}
}
NS_IMETHODIMP
nsSVGTextFrame::NotifyRedrawSuspended()
{
mMetricsState = suspended;
return nsSVGTextFrameBase::NotifyRedrawSuspended();
}
NS_IMETHODIMP
void
nsSVGTextFrame::NotifyRedrawUnsuspended()
{
mMetricsState = unsuspended;
RemoveStateBits(NS_STATE_SVG_REDRAW_SUSPENDED);
UpdateGlyphPositioning(false);
return nsSVGTextFrameBase::NotifyRedrawUnsuspended();
nsSVGTextFrameBase::NotifyRedrawUnsuspended();
}
NS_IMETHODIMP
@ -338,7 +331,7 @@ nsSVGTextFrame::SetWhitespaceHandling(nsSVGGlyphFrame *aFrame)
void
nsSVGTextFrame::UpdateGlyphPositioning(bool aForceGlobalTransform)
{
if (mMetricsState == suspended || !mPositioningDirty)
if ((GetStateBits() & NS_STATE_SVG_REDRAW_SUSPENDED) || !mPositioningDirty)
return;
mPositioningDirty = false;

Просмотреть файл

@ -52,7 +52,6 @@ class nsSVGTextFrame : public nsSVGTextFrameBase
protected:
nsSVGTextFrame(nsStyleContext* aContext)
: nsSVGTextFrameBase(aContext),
mMetricsState(unsuspended),
mPositioningDirty(true) {}
public:
@ -85,8 +84,7 @@ public:
// nsISVGChildFrame interface:
virtual void NotifySVGChanged(PRUint32 aFlags);
NS_IMETHOD NotifyRedrawSuspended();
NS_IMETHOD NotifyRedrawUnsuspended();
virtual void NotifyRedrawUnsuspended();
// Override these four to ensure that UpdateGlyphPositioning is called
// to bring glyph positions up to date
NS_IMETHOD PaintSVG(nsSVGRenderState* aContext,
@ -126,9 +124,6 @@ private:
nsAutoPtr<gfxMatrix> mCanvasTM;
enum UpdateState { unsuspended, suspended };
UpdateState mMetricsState;
bool mPositioningDirty;
};

Просмотреть файл

@ -598,45 +598,67 @@ nsSVGUtils::InvalidateCoveredRegion(nsIFrame *aFrame)
nsSVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame(aFrame);
NS_ASSERTION(outerSVGFrame, "no outer svg frame");
if (outerSVGFrame)
outerSVGFrame->InvalidateCoveredRegion(aFrame);
if (outerSVGFrame) {
nsISVGChildFrame *svgFrame = do_QueryFrame(aFrame);
if (!svgFrame)
return;
// Make sure elements styled by :hover get updated if script/animation moves
// them under or out from under the pointer:
aFrame->PresContext()->PresShell()->SynthesizeMouseMove(false);
nsRect rect = FindFilterInvalidation(aFrame, svgFrame->GetCoveredRegion());
outerSVGFrame->Invalidate(rect);
}
}
void
nsSVGUtils::UpdateGraphic(nsISVGChildFrame *aSVGFrame)
nsSVGUtils::UpdateGraphic(nsIFrame *aFrame)
{
nsIFrame *frame = do_QueryFrame(aSVGFrame);
nsSVGEffects::InvalidateRenderingObservers(aFrame);
nsSVGEffects::InvalidateRenderingObservers(frame);
if (frame->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)
if (aFrame->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)
return;
nsSVGOuterSVGFrame *outerSVGFrame = GetOuterSVGFrame(frame);
if (aFrame->GetStateBits() & NS_STATE_SVG_REDRAW_SUSPENDED) {
aFrame->AddStateBits(NS_STATE_SVG_DIRTY);
return;
}
aFrame->RemoveStateBits(NS_STATE_SVG_DIRTY);
nsISVGChildFrame *svgFrame = do_QueryFrame(aFrame);
if (!svgFrame)
return;
nsSVGOuterSVGFrame *outerSVGFrame = GetOuterSVGFrame(aFrame);
if (!outerSVGFrame) {
NS_ERROR("null outerSVGFrame");
return;
}
if (outerSVGFrame->IsRedrawSuspended()) {
frame->AddStateBits(NS_STATE_SVG_DIRTY);
} else {
frame->RemoveStateBits(NS_STATE_SVG_DIRTY);
// Make sure elements styled by :hover get updated if script/animation moves
// them under or out from under the pointer:
aFrame->PresContext()->PresShell()->SynthesizeMouseMove(false);
bool changed = outerSVGFrame->UpdateAndInvalidateCoveredRegion(frame);
if (changed) {
NotifyAncestorsOfFilterRegionChange(frame);
}
nsRect oldRegion = svgFrame->GetCoveredRegion();
outerSVGFrame->Invalidate(FindFilterInvalidation(aFrame, oldRegion));
svgFrame->UpdateCoveredRegion();
nsRect newRegion = svgFrame->GetCoveredRegion();
if (oldRegion.IsEqualInterior(newRegion))
return;
outerSVGFrame->Invalidate(FindFilterInvalidation(aFrame, newRegion));
if (!(aFrame->GetStateBits() & NS_STATE_IS_OUTER_SVG)) {
NotifyAncestorsOfFilterRegionChange(aFrame);
}
}
void
nsSVGUtils::NotifyAncestorsOfFilterRegionChange(nsIFrame *aFrame)
{
if (aFrame->GetStateBits() & NS_STATE_IS_OUTER_SVG) {
// It would be better if we couldn't get here
return;
}
NS_ABORT_IF_FALSE(!(aFrame->GetStateBits() & NS_STATE_IS_OUTER_SVG),
"Not expecting to be called on the outer SVG Frame");
aFrame = aFrame->GetParent();
@ -883,6 +905,38 @@ nsSVGUtils::NotifyChildrenOfSVGChange(nsIFrame *aFrame, PRUint32 aFlags)
}
}
void
nsSVGUtils::NotifyRedrawSuspended(nsIFrame *aFrame)
{
aFrame->AddStateBits(NS_STATE_SVG_REDRAW_SUSPENDED);
nsIFrame *kid = aFrame->GetFirstPrincipalChild();
while (kid) {
nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
if (SVGFrame) {
SVGFrame->NotifyRedrawSuspended();
}
kid = kid->GetNextSibling();
}
}
void
nsSVGUtils::NotifyRedrawUnsuspended(nsIFrame *aFrame)
{
aFrame->RemoveStateBits(NS_STATE_SVG_REDRAW_SUSPENDED);
nsIFrame *kid = aFrame->GetFirstPrincipalChild();
while (kid) {
nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
if (SVGFrame) {
SVGFrame->NotifyRedrawUnsuspended();
}
kid = kid->GetNextSibling();
}
}
// ************************************************************
class SVGPaintCallback : public nsSVGFilterPaintCallback

Просмотреть файл

@ -102,6 +102,9 @@ class Element;
// If this bit is set, we are a <clipPath> element or descendant.
#define NS_STATE_SVG_CLIPPATH_CHILD NS_FRAME_STATE_BIT(23)
// If this bit is set, redraw is suspended.
#define NS_STATE_SVG_REDRAW_SUSPENDED NS_FRAME_STATE_BIT(24)
/**
* Byte offsets of channels in a native packed gfxColor or cairo image surface.
*/
@ -327,9 +330,10 @@ public:
static void InvalidateCoveredRegion(nsIFrame *aFrame);
/*
* Update the area covered by the frame
* Update the area covered by the frame allowing for the frame to
* have moved.
*/
static void UpdateGraphic(nsISVGChildFrame *aSVGFrame);
static void UpdateGraphic(nsIFrame *aFrame);
/*
* Update the filter invalidation region for ancestor frames, if relevant.
@ -424,6 +428,19 @@ public:
static void
NotifyChildrenOfSVGChange(nsIFrame *aFrame, PRUint32 aFlags);
/*
* Tells child frames that redraw is suspended
*/
static void
NotifyRedrawSuspended(nsIFrame *aFrame);
/*
* Tells child frames that redraw is no longer suspended
* @return true if any of the child frames are dirty
*/
static void
NotifyRedrawUnsuspended(nsIFrame *aFrame);
/*
* Get frame's covered region by walking the children and doing union.
*/