Bug 423998 - Fix repainting regression(s) and multiple invalidation bugs. r=jwatt,sr=roc,a1.9=blocking1.9+ and beltzner

This commit is contained in:
longsonr@gmail.com 2008-04-08 05:51:19 -07:00
Родитель a93beedc81
Коммит f027bf9559
17 изменённых файлов: 102 добавлений и 144 удалений

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

@ -158,7 +158,7 @@ nsSVGDisplayContainerFrame::RemoveFrame(nsIAtom* aListName,
nsresult rv = nsSVGContainerFrame::RemoveFrame(aListName, aOldFrame); nsresult rv = nsSVGContainerFrame::RemoveFrame(aListName, aOldFrame);
if (!GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD) { if (!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
nsSVGUtils::NotifyAncestorsOfFilterRegionChange(this); nsSVGUtils::NotifyAncestorsOfFilterRegionChange(this);
} }

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

@ -372,6 +372,9 @@ nsSVGForeignObjectFrame::UpdateCoveredRegion()
// XXXjwatt: _this_ is where we should reflow _if_ mRect.width has changed! // XXXjwatt: _this_ is where we should reflow _if_ mRect.width has changed!
// we should not unconditionally reflow in AttributeChanged // we should not unconditionally reflow in AttributeChanged
mRect = GetTransformedRegion(x, y, w, h, ctm); mRect = GetTransformedRegion(x, y, w, h, ctm);
nsSVGUtils::UpdateFilterRegion(this);
return NS_OK; return NS_OK;
} }
@ -574,33 +577,7 @@ void nsSVGForeignObjectFrame::RequestReflow(nsIPresShell::IntrinsicDirty aType)
void nsSVGForeignObjectFrame::UpdateGraphic() void nsSVGForeignObjectFrame::UpdateGraphic()
{ {
if (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD) nsSVGUtils::UpdateGraphic(this);
return;
nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
if (!outerSVGFrame) {
NS_ERROR("null outerSVGFrame");
return;
}
if (outerSVGFrame->IsRedrawSuspended()) {
AddStateBits(NS_STATE_SVG_DIRTY);
} else {
RemoveStateBits(NS_STATE_SVG_DIRTY);
// Invalidate the area we used to cover
// XXXjwatt: if we fix the following XXX, try to subtract the new region from the old here.
// hmm, if x then y is changed, our second call could invalidate an "old" area we never actually painted to.
outerSVGFrame->InvalidateCoveredRegion(this);
UpdateCoveredRegion();
// Invalidate the area we now cover
// XXXjwatt: when we're called due to an event that also requires reflow,
// we want to let reflow trigger this rasterization so it doesn't happen twice.
outerSVGFrame->InvalidateCoveredRegion(this);
nsSVGUtils::NotifyAncestorsOfFilterRegionChange(this);
}
// Clear any layout dirty region since we invalidated our whole area. // Clear any layout dirty region since we invalidated our whole area.
mDirtyRegion.SetEmpty(); mDirtyRegion.SetEmpty();

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

@ -103,6 +103,8 @@ nsSVGGeometryFrame::DidModifySVGObservable(nsISVGValue* observable,
if (!frame) if (!frame)
return NS_OK; return NS_OK;
PRBool refresh = PR_FALSE;
if (GetStateBits() & NS_STATE_SVG_FILL_PSERVER) { if (GetStateBits() & NS_STATE_SVG_FILL_PSERVER) {
nsIFrame *ps = static_cast<nsIFrame*>(GetProperty(nsGkAtoms::fill)); nsIFrame *ps = static_cast<nsIFrame*>(GetProperty(nsGkAtoms::fill));
if (frame == ps) { if (frame == ps) {
@ -110,7 +112,7 @@ nsSVGGeometryFrame::DidModifySVGObservable(nsISVGValue* observable,
DeleteProperty(nsGkAtoms::fill); DeleteProperty(nsGkAtoms::fill);
RemoveStateBits(NS_STATE_SVG_FILL_PSERVER); RemoveStateBits(NS_STATE_SVG_FILL_PSERVER);
} }
UpdateGraphic(); refresh = PR_TRUE;
} }
} }
@ -121,7 +123,15 @@ nsSVGGeometryFrame::DidModifySVGObservable(nsISVGValue* observable,
DeleteProperty(nsGkAtoms::stroke); DeleteProperty(nsGkAtoms::stroke);
RemoveStateBits(NS_STATE_SVG_STROKE_PSERVER); RemoveStateBits(NS_STATE_SVG_STROKE_PSERVER);
} }
UpdateGraphic(); refresh = PR_TRUE;
}
}
if (refresh) {
nsISVGChildFrame* svgFrame = nsnull;
CallQueryInterface(this, &svgFrame);
if (svgFrame) {
nsSVGUtils::UpdateGraphic(svgFrame);
} }
} }

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

@ -113,8 +113,6 @@ public:
PRBool SetupCairoStroke(gfxContext *aContext); PRBool SetupCairoStroke(gfxContext *aContext);
protected: protected:
virtual nsresult UpdateGraphic(PRBool suppressInvalidation = PR_FALSE) = 0;
nsSVGPaintServerFrame *GetPaintServer(const nsStyleSVGPaint *aPaint); nsSVGPaintServerFrame *GetPaintServer(const nsStyleSVGPaint *aPaint);
private: private:

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

@ -36,7 +36,6 @@
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#include "nsSVGOuterSVGFrame.h"
#include "nsSVGTextFrame.h" #include "nsSVGTextFrame.h"
#include "nsILookAndFeel.h" #include "nsILookAndFeel.h"
#include "nsTextFragment.h" #include "nsTextFragment.h"
@ -216,16 +215,7 @@ nsSVGGlyphFrame::CharacterDataChanged(nsPresContext* aPresContext,
PRBool aAppend) PRBool aAppend)
{ {
ClearTextRun(); ClearTextRun();
return UpdateGraphic(); NotifyGlyphMetricsChange();
}
nsresult
nsSVGGlyphFrame::UpdateGraphic(PRBool suppressInvalidation)
{
nsSVGTextContainerFrame *containerFrame =
static_cast<nsSVGTextContainerFrame *>(mParent);
if (containerFrame)
containerFrame->UpdateGraphic();
return NS_OK; return NS_OK;
} }
@ -240,7 +230,9 @@ nsSVGGlyphFrame::DidSetStyleContext()
{ {
nsSVGGlyphFrameBase::DidSetStyleContext(); nsSVGGlyphFrameBase::DidSetStyleContext();
ClearTextRun(); ClearTextRun();
return UpdateGraphic(); NotifyGlyphMetricsChange();
return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -266,7 +258,7 @@ nsSVGGlyphFrame::SetSelected(nsPresContext* aPresContext,
else else
mState &= ~NS_FRAME_SELECTED_CONTENT; mState &= ~NS_FRAME_SELECTED_CONTENT;
UpdateGeometry(PR_FALSE, PR_FALSE); nsSVGUtils::UpdateGraphic(this);
return NS_OK; return NS_OK;
} }
@ -466,7 +458,9 @@ nsSVGGlyphFrame::InitialUpdate()
NS_ASSERTION(!(mState & NS_FRAME_IN_REFLOW), NS_ASSERTION(!(mState & NS_FRAME_IN_REFLOW),
"We don't actually participate in reflow"); "We don't actually participate in reflow");
NotifyGlyphMetricsChange();
// Do unset the various reflow bits, though. // Do unset the various reflow bits, though.
mState &= ~(NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY | mState &= ~(NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY |
NS_FRAME_HAS_DIRTY_CHILDREN); NS_FRAME_HAS_DIRTY_CHILDREN);
@ -480,7 +474,9 @@ nsSVGGlyphFrame::NotifySVGChanged(PRUint32 aFlags)
if (aFlags & TRANSFORM_CHANGED) { if (aFlags & TRANSFORM_CHANGED) {
ClearTextRun(); ClearTextRun();
} }
UpdateGeometry(PR_TRUE, (aFlags & SUPPRESS_INVALIDATION) != 0); if (!(aFlags & SUPPRESS_INVALIDATION)) {
nsSVGUtils::UpdateGraphic(this);
}
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -494,7 +490,7 @@ NS_IMETHODIMP
nsSVGGlyphFrame::NotifyRedrawUnsuspended() nsSVGGlyphFrame::NotifyRedrawUnsuspended()
{ {
if (GetStateBits() & NS_STATE_SVG_DIRTY) if (GetStateBits() & NS_STATE_SVG_DIRTY)
UpdateGeometry(PR_TRUE, PR_FALSE); nsSVGUtils::UpdateGraphic(this);
return NS_OK; return NS_OK;
} }
@ -821,7 +817,7 @@ NS_IMETHODIMP_(void)
nsSVGGlyphFrame::SetGlyphPosition(float x, float y) nsSVGGlyphFrame::SetGlyphPosition(float x, float y)
{ {
mPosition.MoveTo(x, y); mPosition.MoveTo(x, y);
UpdateGeometry(PR_TRUE, PR_FALSE); nsSVGUtils::UpdateGraphic(this);
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -1142,37 +1138,13 @@ nsSVGGlyphFrame::SetWhitespaceHandling(PRUint8 aWhitespaceHandling)
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// //
void nsSVGGlyphFrame::UpdateGeometry(PRBool bRedraw, void
PRBool suppressInvalidation) nsSVGGlyphFrame::NotifyGlyphMetricsChange()
{ {
if (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD) nsSVGTextContainerFrame *containerFrame =
return; static_cast<nsSVGTextContainerFrame *>(mParent);
if (containerFrame)
nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this); containerFrame->NotifyGlyphMetricsChange();
if (!outerSVGFrame) {
NS_ERROR("null outerSVGFrame");
return;
}
if (outerSVGFrame->IsRedrawSuspended()) {
AddStateBits(NS_STATE_SVG_DIRTY);
} else {
RemoveStateBits(NS_STATE_SVG_DIRTY);
if (suppressInvalidation)
return;
outerSVGFrame->InvalidateRect(mRect);
UpdateCoveredRegion();
nsRect filterRect;
filterRect = nsSVGUtils::FindFilterInvalidation(this);
if (!filterRect.IsEmpty()) {
outerSVGFrame->InvalidateRect(filterRect);
} else {
outerSVGFrame->InvalidateRect(mRect);
}
}
} }
PRBool PRBool

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

@ -130,9 +130,8 @@ public:
NS_IMETHOD_(PRBool) IsDisplayContainer() { return PR_FALSE; } NS_IMETHOD_(PRBool) IsDisplayContainer() { return PR_FALSE; }
NS_IMETHOD_(PRBool) HasValidCoveredRect() { return PR_TRUE; } NS_IMETHOD_(PRBool) HasValidCoveredRect() { return PR_TRUE; }
// nsISVGGeometrySource interface: // nsSVGGeometryFrame methods
NS_IMETHOD GetCanvasTM(nsIDOMSVGMatrix * *aCTM); NS_IMETHOD GetCanvasTM(nsIDOMSVGMatrix * *aCTM);
virtual nsresult UpdateGraphic(PRBool suppressInvalidation = PR_FALSE);
// nsISVGGlyphFragmentLeaf interface: // nsISVGGlyphFragmentLeaf interface:
// These do not use the global transform if NS_STATE_NONDISPLAY_CHILD // These do not use the global transform if NS_STATE_NONDISPLAY_CHILD
@ -207,8 +206,7 @@ protected:
void FillCharacters(CharacterIterator *aIter, void FillCharacters(CharacterIterator *aIter,
gfxContext *aContext); gfxContext *aContext);
void UpdateGeometry(PRBool bRedraw, PRBool suppressInvalidation); void NotifyGlyphMetricsChange();
void UpdateMetrics();
PRBool ContainsPoint(float x, float y); PRBool ContainsPoint(float x, float y);
PRBool GetGlobalTransform(gfxMatrix *aMatrix); PRBool GetGlobalTransform(gfxMatrix *aMatrix);
void SetupGlobalTransform(gfxContext *aContext); void SetupGlobalTransform(gfxContext *aContext);

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

@ -187,7 +187,7 @@ nsSVGImageFrame::AttributeChanged(PRInt32 aNameSpaceID,
aAttribute == nsGkAtoms::width || aAttribute == nsGkAtoms::width ||
aAttribute == nsGkAtoms::height || aAttribute == nsGkAtoms::height ||
aAttribute == nsGkAtoms::preserveAspectRatio)) { aAttribute == nsGkAtoms::preserveAspectRatio)) {
UpdateGraphic(); nsSVGUtils::UpdateGraphic(this);
return NS_OK; return NS_OK;
} }
@ -389,7 +389,7 @@ NS_IMETHODIMP nsSVGImageListener::OnStopDecode(imgIRequest *aRequest,
if (!mFrame) if (!mFrame)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
mFrame->UpdateGraphic(); nsSVGUtils::UpdateGraphic(mFrame);
return NS_OK; return NS_OK;
} }
@ -400,7 +400,7 @@ NS_IMETHODIMP nsSVGImageListener::FrameChanged(imgIContainer *aContainer,
if (!mFrame) if (!mFrame)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
mFrame->UpdateGraphic(); nsSVGUtils::UpdateGraphic(mFrame);
return NS_OK; return NS_OK;
} }
@ -411,7 +411,7 @@ NS_IMETHODIMP nsSVGImageListener::OnStartContainer(imgIRequest *aRequest,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
mFrame->mImageContainer = aContainer; mFrame->mImageContainer = aContainer;
mFrame->UpdateGraphic(); nsSVGUtils::UpdateGraphic(mFrame);
return NS_OK; return NS_OK;
} }

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

@ -109,7 +109,7 @@ nsSVGMutationObserver::AttributeChanged(nsIDocument *aDocument,
if (metrics) { if (metrics) {
nsSVGTextContainerFrame *containerFrame = nsSVGTextContainerFrame *containerFrame =
static_cast<nsSVGTextContainerFrame *>(frame); static_cast<nsSVGTextContainerFrame *>(frame);
containerFrame->UpdateGraphic(); containerFrame->NotifyGlyphMetricsChange();
continue; continue;
} }
// if not, are there text elements amongst its descendents // if not, are there text elements amongst its descendents

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

@ -162,7 +162,7 @@ nsSVGMarkerProperty::RemoveMutationObserver(nsWeakPtr aObservedMarker)
void void
nsSVGMarkerProperty::DoUpdate() nsSVGMarkerProperty::DoUpdate()
{ {
mFrame->UpdateGraphic(); nsSVGUtils::UpdateGraphic(mFrame);
} }
void void
@ -248,7 +248,7 @@ nsSVGPathGeometryFrame::AttributeChanged(PRInt32 aNameSpaceID,
(static_cast<nsSVGPathGeometryElement*> (static_cast<nsSVGPathGeometryElement*>
(mContent)->IsDependentAttribute(aAttribute) || (mContent)->IsDependentAttribute(aAttribute) ||
aAttribute == nsGkAtoms::transform)) aAttribute == nsGkAtoms::transform))
UpdateGraphic(); nsSVGUtils::UpdateGraphic(this);
return NS_OK; return NS_OK;
} }
@ -272,7 +272,7 @@ nsSVGPathGeometryFrame::DidSetStyleContext()
// style_hints don't map very well onto svg. Here seems to be the // style_hints don't map very well onto svg. Here seems to be the
// best place to deal with style changes: // best place to deal with style changes:
UpdateGraphic(); nsSVGUtils::UpdateGraphic(this);
return NS_OK; return NS_OK;
} }
@ -447,8 +447,10 @@ nsSVGPathGeometryFrame::UpdateCoveredRegion()
} }
// Add in markers // Add in markers
UpdateMarkerProperty();
mRect = GetCoveredRegion(); mRect = GetCoveredRegion();
nsSVGUtils::UpdateFilterRegion(this);
return NS_OK; return NS_OK;
} }
@ -459,7 +461,7 @@ nsSVGPathGeometryFrame::InitialUpdate()
"Yikes! We've been called already! Hopefully we weren't called " "Yikes! We've been called already! Hopefully we weren't called "
"before our nsSVGOuterSVGFrame's initial Reflow()!!!"); "before our nsSVGOuterSVGFrame's initial Reflow()!!!");
UpdateGraphic(); nsSVGUtils::UpdateGraphic(this);
NS_ASSERTION(!(mState & NS_FRAME_IN_REFLOW), NS_ASSERTION(!(mState & NS_FRAME_IN_REFLOW),
"We don't actually participate in reflow"); "We don't actually participate in reflow");
@ -473,7 +475,9 @@ nsSVGPathGeometryFrame::InitialUpdate()
void void
nsSVGPathGeometryFrame::NotifySVGChanged(PRUint32 aFlags) nsSVGPathGeometryFrame::NotifySVGChanged(PRUint32 aFlags)
{ {
UpdateGraphic((aFlags & SUPPRESS_INVALIDATION) != 0); if (!(aFlags & SUPPRESS_INVALIDATION)) {
nsSVGUtils::UpdateGraphic(this);
}
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -487,7 +491,7 @@ NS_IMETHODIMP
nsSVGPathGeometryFrame::NotifyRedrawUnsuspended() nsSVGPathGeometryFrame::NotifyRedrawUnsuspended()
{ {
if (GetStateBits() & NS_STATE_SVG_DIRTY) if (GetStateBits() & NS_STATE_SVG_DIRTY)
UpdateGraphic(); nsSVGUtils::UpdateGraphic(this);
return NS_OK; return NS_OK;
} }
@ -734,40 +738,3 @@ nsSVGPathGeometryFrame::GetHittestMask()
return mask; return mask;
} }
//----------------------------------------------------------------------
nsresult
nsSVGPathGeometryFrame::UpdateGraphic(PRBool suppressInvalidation)
{
if (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)
return NS_OK;
nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
if (!outerSVGFrame) {
NS_ERROR("null outerSVGFrame");
return NS_ERROR_FAILURE;
}
if (outerSVGFrame->IsRedrawSuspended()) {
AddStateBits(NS_STATE_SVG_DIRTY);
} else {
RemoveStateBits(NS_STATE_SVG_DIRTY);
if (suppressInvalidation)
return NS_OK;
outerSVGFrame->InvalidateCoveredRegion(this);
UpdateMarkerProperty();
UpdateCoveredRegion();
nsSVGUtils::UpdateFilterRegion(this);
outerSVGFrame->InvalidateCoveredRegion(this);
nsSVGUtils::NotifyAncestorsOfFilterRegionChange(this);
}
return NS_OK;
}

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

@ -98,9 +98,8 @@ public:
} }
#endif #endif
// nsISVGGeometrySource interface: // nsSVGGeometryFrame methods
NS_IMETHOD GetCanvasTM(nsIDOMSVGMatrix * *aCTM); NS_IMETHOD GetCanvasTM(nsIDOMSVGMatrix * *aCTM);
virtual nsresult UpdateGraphic(PRBool suppressInvalidation = PR_FALSE);
protected: protected:
// nsISVGChildFrame interface: // nsISVGChildFrame interface:

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

@ -93,7 +93,7 @@ nsSVGTSpanFrame::AttributeChanged(PRInt32 aNameSpaceID,
aAttribute == nsGkAtoms::y || aAttribute == nsGkAtoms::y ||
aAttribute == nsGkAtoms::dx || aAttribute == nsGkAtoms::dx ||
aAttribute == nsGkAtoms::dy)) { aAttribute == nsGkAtoms::dy)) {
UpdateGraphic(); NotifyGlyphMetricsChange();
} }
return NS_OK; return NS_OK;

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

@ -52,7 +52,7 @@ NS_INTERFACE_MAP_BEGIN(nsSVGTextContainerFrame)
NS_INTERFACE_MAP_END_INHERITING(nsSVGDisplayContainerFrame) NS_INTERFACE_MAP_END_INHERITING(nsSVGDisplayContainerFrame)
void void
nsSVGTextContainerFrame::UpdateGraphic() nsSVGTextContainerFrame::NotifyGlyphMetricsChange()
{ {
nsSVGTextFrame *textFrame = GetTextFrame(); nsSVGTextFrame *textFrame = GetTextFrame();
if (textFrame) if (textFrame)
@ -141,7 +141,7 @@ nsSVGTextContainerFrame::InsertFrames(nsIAtom* aListName,
aPrevFrame, aPrevFrame,
aFrameList); aFrameList);
UpdateGraphic(); NotifyGlyphMetricsChange();
return rv; return rv;
} }

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

@ -53,7 +53,7 @@ public:
nsSVGTextContainerFrame(nsStyleContext* aContext) : nsSVGTextContainerFrame(nsStyleContext* aContext) :
nsSVGDisplayContainerFrame(aContext) {} nsSVGDisplayContainerFrame(aContext) {}
void UpdateGraphic(); void NotifyGlyphMetricsChange();
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetX(); NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetX();
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetY(); NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetY();
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetDx(); NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetDx();

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

@ -322,6 +322,7 @@ void
nsSVGTextFrame::NotifyGlyphMetricsChange() nsSVGTextFrame::NotifyGlyphMetricsChange()
{ {
mPositioningDirty = PR_TRUE; mPositioningDirty = PR_TRUE;
UpdateGlyphPositioning(PR_FALSE);
} }
static void static void
@ -355,6 +356,8 @@ nsSVGTextFrame::UpdateGlyphPositioning(PRBool aForceGlobalTransform)
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode(); nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (!node) return; if (!node) return;
mPositioningDirty = PR_FALSE;
// we'll align every fragment in this chunk on the dominant-baseline: // we'll align every fragment in this chunk on the dominant-baseline:
// XXX should actually inspect 'alignment-baseline' for each fragment // XXX should actually inspect 'alignment-baseline' for each fragment
@ -393,7 +396,6 @@ nsSVGTextFrame::UpdateGlyphPositioning(PRBool aForceGlobalTransform)
firstFragment = node->GetFirstGlyphFragment(); firstFragment = node->GetFirstGlyphFragment();
if (!firstFragment) { if (!firstFragment) {
mPositioningDirty = PR_FALSE;
return; return;
} }
@ -477,6 +479,4 @@ nsSVGTextFrame::UpdateGlyphPositioning(PRBool aForceGlobalTransform)
} }
firstFragment = fragment; firstFragment = fragment;
} }
mPositioningDirty = PR_FALSE;
} }

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

@ -72,7 +72,7 @@ nsSVGPathListener::AttributeChanged(nsIDocument *aDocument,
PRInt32 aModType, PRInt32 aModType,
PRUint32 aStateMask) PRUint32 aStateMask)
{ {
mTextPathFrame->UpdateGraphic(); mTextPathFrame->NotifyGlyphMetricsChange();
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -237,11 +237,11 @@ nsSVGTextPathFrame::AttributeChanged(PRInt32 aNameSpaceID,
{ {
if (aNameSpaceID == kNameSpaceID_None && if (aNameSpaceID == kNameSpaceID_None &&
aAttribute == nsGkAtoms::startOffset) { aAttribute == nsGkAtoms::startOffset) {
UpdateGraphic(); NotifyGlyphMetricsChange();
} else if (aNameSpaceID == kNameSpaceID_XLink && } else if (aNameSpaceID == kNameSpaceID_XLink &&
aAttribute == nsGkAtoms::href) { aAttribute == nsGkAtoms::href) {
mPathListener = nsnull; mPathListener = nsnull;
UpdateGraphic(); NotifyGlyphMetricsChange();
} }
return NS_OK; return NS_OK;

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

@ -888,7 +888,39 @@ nsSVGUtils::UpdateFilterRegion(nsIFrame *aFrame)
} }
} }
void void
nsSVGUtils::UpdateGraphic(nsISVGChildFrame *aSVGFrame)
{
nsIFrame *frame;
CallQueryInterface(aSVGFrame, &frame);
if (frame->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)
return;
nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(frame);
if (!outerSVGFrame) {
NS_ERROR("null outerSVGFrame");
return;
}
if (outerSVGFrame->IsRedrawSuspended()) {
frame->AddStateBits(NS_STATE_SVG_DIRTY);
} else {
frame->RemoveStateBits(NS_STATE_SVG_DIRTY);
// Invalidate the area we used to cover
outerSVGFrame->InvalidateCoveredRegion(frame);
aSVGFrame->UpdateCoveredRegion();
// Invalidate the area we now cover
outerSVGFrame->InvalidateCoveredRegion(frame);
NotifyAncestorsOfFilterRegionChange(frame);
}
}
void
nsSVGUtils::NotifyAncestorsOfFilterRegionChange(nsIFrame *aFrame) nsSVGUtils::NotifyAncestorsOfFilterRegionChange(nsIFrame *aFrame)
{ {
aFrame = aFrame->GetParent(); aFrame = aFrame->GetParent();

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

@ -270,6 +270,11 @@ public:
*/ */
static void UpdateFilterRegion(nsIFrame *aFrame); static void UpdateFilterRegion(nsIFrame *aFrame);
/*
* Update the area covered by the frame
*/
static void UpdateGraphic(nsISVGChildFrame *aSVGFrame);
/* /*
* Update the filter invalidation region for ancestor frames, if relevant. * Update the filter invalidation region for ancestor frames, if relevant.
*/ */