Bug 447567. Instead of brutally wiping out effects properties whenever the style context changes for an SVG frame (which wouldn't work for non-SVG frames), create a new style change hint to handle it. r=longsonr,sr=dbaron

This commit is contained in:
Robert O'Callahan 2008-08-06 12:55:07 +12:00
parent 19c8f95e49
commit ab2b084996
17 changed files with 46 additions and 73 deletions

View File

@ -147,6 +147,9 @@
#ifdef MOZ_MATHML
#include "nsMathMLParts.h"
#endif
#ifdef MOZ_SVG
#include "nsSVGUtils.h"
#endif
nsIFrame*
NS_NewHTMLCanvasFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
@ -9821,6 +9824,11 @@ nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
RecreateFramesForContent(content);
} else {
NS_ASSERTION(frame, "This shouldn't happen");
#ifdef MOZ_SVG
if (hint & nsChangeHint_UpdateEffects) {
nsSVGUtils::UpdateEffects(frame);
}
#endif
if (hint & nsChangeHint_ReflowFrame) {
StyleChangeReflow(frame);
}

View File

@ -49,7 +49,17 @@ enum nsChangeHint {
nsChangeHint_ReflowFrame = 0x02, // change requires reflow (e.g., WIDTH=)
nsChangeHint_SyncFrameView = 0x04, // change requires view to be updated, if there is one (e.g., clip:)
nsChangeHint_UpdateCursor = 0x08, // The currently shown mouse cursor needs to be updated
nsChangeHint_ReconstructFrame = 0x10 // change requires frame change (e.g., display:)
/**
* SVG filter/mask/clip effects need to be recomputed because the URI
* in the filter/mask/clip-path property has changed. This wipes
* out cached nsSVGPropertyBase and subclasses which hold a reference to
* the element referenced by the URI, and a mutation observer for
* the DOM subtree rooted at that element. Also, for filters they store a
* bounding-box for the filter result so that if the filter changes we can
* invalidate the old covered area.
*/
nsChangeHint_UpdateEffects = 0x10,
nsChangeHint_ReconstructFrame = 0x20 // change requires frame change (e.g., display:)
// This subsumes all the above
// TBD: add nsChangeHint_ForceFrameView to force frame reconstruction if the frame doesn't yet
// have a view

View File

@ -447,6 +447,11 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther)
// a framechange here and a reflow should be sufficient. See bug 35768.
DO_STRUCT_DIFFERENCE(Quotes);
#ifdef MOZ_SVG
maxHint = nsChangeHint(NS_STYLE_HINT_REFLOW | nsChangeHint_UpdateEffects);
DO_STRUCT_DIFFERENCE(SVGReset);
#endif
// At this point, we know that the worst kind of damage we could do is
// a reflow.
maxHint = NS_STYLE_HINT_REFLOW;

View File

@ -885,25 +885,34 @@ nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset& aSource)
nsChangeHint nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) const
{
nsChangeHint hint = nsChangeHint(0);
if (!EqualURIs(mClipPath, aOther.mClipPath) ||
!EqualURIs(mFilter, aOther.mFilter) ||
!EqualURIs(mMask, aOther.mMask)) {
NS_UpdateHint(hint, nsChangeHint_UpdateEffects);
NS_UpdateHint(hint, nsChangeHint_ReflowFrame);
NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
}
if (mStopColor != aOther.mStopColor ||
mFloodColor != aOther.mFloodColor ||
mLightingColor != aOther.mLightingColor ||
!EqualURIs(mClipPath, aOther.mClipPath) ||
!EqualURIs(mFilter, aOther.mFilter) ||
!EqualURIs(mMask, aOther.mMask) ||
mStopOpacity != aOther.mStopOpacity ||
mFloodOpacity != aOther.mFloodOpacity ||
mDominantBaseline != aOther.mDominantBaseline)
return NS_STYLE_HINT_VISUAL;
return NS_STYLE_HINT_NONE;
NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
return hint;
}
#ifdef DEBUG
/* static */
nsChangeHint nsStyleSVGReset::MaxDifference()
{
return NS_STYLE_HINT_VISUAL;
return NS_CombineHint(NS_CombineHint(nsChangeHint_UpdateEffects,
nsChangeHint_ReflowFrame),
nsChangeHint_RepaintFrame);
}
#endif

View File

@ -65,8 +65,6 @@ public:
nsIAtom* aAttribute,
PRInt32 aModType);
NS_IMETHOD DidSetStyleContext();
/**
* Get the "type" of the frame
*
@ -129,14 +127,6 @@ nsSVGAFrame::AttributeChanged(PRInt32 aNameSpaceID,
return NS_OK;
}
NS_IMETHODIMP
nsSVGAFrame::DidSetStyleContext()
{
nsSVGUtils::StyleEffects(this);
return NS_OK;
}
nsIAtom *
nsSVGAFrame::GetType() const
{

View File

@ -105,13 +105,6 @@ nsSVGDisplayContainerFrame::Init(nsIContent* aContent,
return rv;
}
void
nsSVGDisplayContainerFrame::Destroy()
{
nsSVGUtils::StyleEffects(this);
nsSVGContainerFrame::Destroy();
}
NS_IMETHODIMP
nsSVGDisplayContainerFrame::InsertFrames(nsIAtom* aListName,
nsIFrame* aPrevFrame,

View File

@ -91,7 +91,6 @@ private:
public:
// nsIFrame:
virtual void Destroy();
NS_IMETHOD InsertFrames(nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList);

View File

@ -106,10 +106,6 @@ nsSVGForeignObjectFrame::Init(nsIContent* aContent,
void nsSVGForeignObjectFrame::Destroy()
{
nsSVGUtils::GetOuterSVGFrame(this)->UnregisterForeignObject(this);
// Delete any clipPath/filter/mask properties _before_ we die. The properties
// and property hash table have weak pointers to us that are dereferenced
// when the properties are destroyed.
nsSVGUtils::StyleEffects(this);
nsSVGForeignObjectFrameBase::Destroy();
}
@ -143,13 +139,6 @@ nsSVGForeignObjectFrame::AttributeChanged(PRInt32 aNameSpaceID,
return NS_OK;
}
NS_IMETHODIMP
nsSVGForeignObjectFrame::DidSetStyleContext()
{
nsSVGUtils::StyleEffects(this);
return NS_OK;
}
NS_IMETHODIMP
nsSVGForeignObjectFrame::Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,

View File

@ -75,8 +75,6 @@ public:
return GetFirstChild(nsnull)->GetContentInsertionFrame();
}
NS_IMETHOD DidSetStyleContext();
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,

View File

@ -140,13 +140,6 @@ nsSVGGFrame::GetCanvasTM()
return retval;
}
NS_IMETHODIMP
nsSVGGFrame::DidSetStyleContext()
{
nsSVGUtils::StyleEffects(this);
return NS_OK;
}
NS_IMETHODIMP
nsSVGGFrame::AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,

View File

@ -67,7 +67,6 @@ public:
#endif
// nsIFrame interface:
NS_IMETHOD DidSetStyleContext();
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);

View File

@ -64,9 +64,6 @@ private:
NS_IMETHOD_(nsrefcnt) Release() { return 1; }
public:
// nsIFrame:
NS_IMETHOD DidSetStyleContext();
// We don't define an AttributeChanged method since changes to the
// 'x', 'y', 'width' and 'height' attributes of our content object
// are handled in nsSVGSVGElement::DidModifySVGObservable
@ -404,10 +401,3 @@ nsSVGInnerSVGFrame::DidModifySVGObservable (nsISVGValue* observable,
NotifyViewportChange();
return NS_OK;
}
NS_IMETHODIMP
nsSVGInnerSVGFrame::DidSetStyleContext()
{
nsSVGUtils::StyleEffects(this);
return NS_OK;
}

View File

@ -599,8 +599,6 @@ nsSVGPathGeometryFrame::UpdateMarkerProperty()
void
nsSVGPathGeometryFrame::RemovePathProperties()
{
nsSVGUtils::StyleEffects(this);
if (GetStateBits() & NS_STATE_SVG_HAS_MARKERS)
DeleteProperty(nsGkAtoms::marker);
}

View File

@ -99,14 +99,6 @@ nsSVGTextFrame::AttributeChanged(PRInt32 aNameSpaceID,
return NS_OK;
}
NS_IMETHODIMP
nsSVGTextFrame::DidSetStyleContext()
{
nsSVGUtils::StyleEffects(this);
return NS_OK;
}
nsIAtom *
nsSVGTextFrame::GetType() const
{

View File

@ -59,7 +59,6 @@ public:
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
NS_IMETHOD DidSetStyleContext();
/**
* Get the "type" of the frame

View File

@ -1391,7 +1391,7 @@ nsSVGUtils::PaintChildWithEffects(nsSVGRenderState *aContext,
}
void
nsSVGUtils::StyleEffects(nsIFrame *aFrame)
nsSVGUtils::UpdateEffects(nsIFrame *aFrame)
{
aFrame->DeleteProperty(nsGkAtoms::filter);
aFrame->DeleteProperty(nsGkAtoms::mask);

View File

@ -336,11 +336,12 @@ public:
nsRect *aDirtyRect,
nsIFrame *aFrame);
/* Style change for effects (filter/clip/mask/opacity) - call when
* the frame's style has changed to make sure the effects properties
* stay in sync. */
/**
* Called by nsCSSFrameConstructor when style changes require the
* effect properties on aFrame to be updated
*/
static void
StyleEffects(nsIFrame *aFrame);
UpdateEffects(nsIFrame *aFrame);
/* Hit testing - check if point hits the clipPath of indicated
* frame. (x,y) are specified in device pixels relative to the