Bug 472135. Avoid re-getting the target marker frame in nsSVGMarkerProperty::DoUpdate --- that leads to infinite loops. Update things lazily instead via fake style changes. r+sr=roc

--HG--
extra : rebase_source : f90519e06842d6301e3a27eddb0cddd300b62db2
This commit is contained in:
Robert Longson 2009-01-16 21:20:29 +13:00
parent 0ec63aa6ad
commit 4a4ce9e387
3 changed files with 44 additions and 23 deletions

View File

@ -149,6 +149,8 @@
#endif
#ifdef MOZ_SVG
#include "nsSVGEffects.h"
#include "nsSVGUtils.h"
#include "nsSVGOuterSVGFrame.h"
#endif
nsIFrame*
@ -9466,9 +9468,20 @@ DoApplyRenderingChangeToTree(nsIFrame* aFrame,
UpdateViewsForTree(aFrame, aViewManager, aFrameManager, aChange);
// if frame has view, will already be invalidated
if ((aChange & nsChangeHint_RepaintFrame) &&
!aFrame->IsFrameOfType(nsIFrame::eSVG)) {
aFrame->Invalidate(aFrame->GetOverflowRect());
if (aChange & nsChangeHint_RepaintFrame) {
if (aFrame->IsFrameOfType(nsIFrame::eSVG)) {
#ifdef MOZ_SVG
if (!(aFrame->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(aFrame);
if (outerSVGFrame) {
// marker changes can change the covered region
outerSVGFrame->UpdateAndInvalidateCoveredRegion(aFrame);
}
}
#endif
} else {
aFrame->Invalidate(aFrame->GetOverflowRect());
}
}
}
}

View File

@ -844,6 +844,14 @@ nsChangeHint nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const
NS_UpdateHint(hint, nsChangeHint_ReflowFrame);
}
if (!EqualURIs(mMarkerEnd, aOther.mMarkerEnd) ||
!EqualURIs(mMarkerMid, aOther.mMarkerMid) ||
!EqualURIs(mMarkerStart, aOther.mMarkerStart)) {
NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
NS_UpdateHint(hint, nsChangeHint_UpdateEffects);
return hint;
}
if (mFill != aOther.mFill ||
mStroke != aOther.mStroke) {
NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
@ -855,11 +863,7 @@ nsChangeHint nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const
return hint;
}
if ( !EqualURIs(mMarkerEnd, aOther.mMarkerEnd) ||
!EqualURIs(mMarkerMid, aOther.mMarkerMid) ||
!EqualURIs(mMarkerStart, aOther.mMarkerStart) ||
mStrokeDashoffset != aOther.mStrokeDashoffset ||
if ( mStrokeDashoffset != aOther.mStrokeDashoffset ||
mStrokeWidth != aOther.mStrokeWidth ||
mFillOpacity != aOther.mFillOpacity ||

View File

@ -221,17 +221,14 @@ nsSVGMarkerProperty::DoUpdate()
if (!mFrame)
return;
if (mFrame->IsFrameOfType(nsIFrame::eSVG)) {
if (!(mFrame->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(mFrame);
if (outerSVGFrame) {
// marker changes can change the covered region
outerSVGFrame->UpdateAndInvalidateCoveredRegion(mFrame);
}
}
} else {
InvalidateAllContinuations(mFrame);
}
NS_ASSERTION(mFrame->IsFrameOfType(nsIFrame::eSVG), "SVG frame expected");
// Repaint asynchronously
nsChangeHint changeHint =
nsChangeHint(nsChangeHint_RepaintFrame | nsChangeHint_UpdateEffects);
mFramePresShell->FrameConstructor()->PostRestyleEvent(
mFrame->GetContent(), nsReStyleHint(0), changeHint);
}
void
@ -368,10 +365,17 @@ nsSVGEffects::UpdateEffects(nsIFrame *aFrame)
// Ensure that the filter is repainted correctly
// We can't do that in DoUpdate as the referenced frame may not be valid
const nsStyleSVGReset *style = aFrame->GetStyleSVGReset();
if (style->mFilter) {
GetEffectProperty(style->mFilter, aFrame, nsGkAtoms::filter, CreateFilterProperty);
}
GetEffectProperty(aFrame->GetStyleSVGReset()->mFilter,
aFrame, nsGkAtoms::filter, CreateFilterProperty);
// Set marker properties here to avoid reference loops
const nsStyleSVG *style = aFrame->GetStyleSVG();
GetEffectProperty(style->mMarkerStart, aFrame, nsGkAtoms::marker_start,
CreateMarkerProperty);
GetEffectProperty(style->mMarkerMid, aFrame, nsGkAtoms::marker_mid,
CreateMarkerProperty);
GetEffectProperty(style->mMarkerEnd, aFrame, nsGkAtoms::marker_end,
CreateMarkerProperty);
}
nsSVGFilterProperty *