mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Bug 539356 - Part 9d - Make SVG support the new invalidation model. r=jwatt
This commit is contained in:
parent
cee1aa3599
commit
da86ec189f
@ -613,3 +613,18 @@ nsSVGForeignObjectFrame::DoReflow()
|
||||
mInReflow = false;
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsSVGForeignObjectFrame::GetInvalidRegion()
|
||||
{
|
||||
nsIFrame* kid = GetFirstPrincipalChild();
|
||||
if (kid->HasInvalidFrameInSubtree()) {
|
||||
gfxRect r(mRect.x, mRect.y, mRect.width, mRect.height);
|
||||
r.Scale(1.0 / nsPresContext::AppUnitsPerCSSPixel());
|
||||
nsRect rect = ToCanvasBounds(r, GetCanvasTM(FOR_PAINTING), PresContext());
|
||||
rect = nsSVGUtils::GetPostFilterVisualOverflowRect(this, rect);
|
||||
return rect;
|
||||
}
|
||||
return nsRect();
|
||||
}
|
||||
|
||||
|
||||
|
@ -90,6 +90,8 @@ public:
|
||||
|
||||
gfxMatrix GetCanvasTM(uint32_t aFor);
|
||||
|
||||
nsRect GetInvalidRegion();
|
||||
|
||||
protected:
|
||||
// implementation helpers:
|
||||
void DoReflow();
|
||||
|
@ -280,9 +280,9 @@ nsRect
|
||||
return overflowRect - (aFrame->GetOffsetTo(firstFrame) + firstFrameToUserSpace);
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsIntRect
|
||||
nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(nsIFrame* aFrame,
|
||||
const nsRect& aInvalidRect)
|
||||
const nsIntRect& aInvalidRect)
|
||||
{
|
||||
// Don't bother calling GetEffectProperties; the filter property should
|
||||
// already have been set up during reflow/ComputeFrameEffectsRect
|
||||
@ -298,22 +298,26 @@ nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(nsIFrame* aFrame,
|
||||
return aInvalidRect;
|
||||
}
|
||||
|
||||
int32_t appUnitsPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
|
||||
nsSVGFilterFrame* filterFrame = prop->GetFilterFrame();
|
||||
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.
|
||||
return aFrame->GetVisualOverflowRect();
|
||||
nsRect overflow = aFrame->GetVisualOverflowRect();
|
||||
return overflow.ToOutsidePixels(appUnitsPerDevPixel);
|
||||
}
|
||||
|
||||
// Convert aInvalidRect into "user space" in app units:
|
||||
nsPoint toUserSpace =
|
||||
aFrame->GetOffsetTo(firstFrame) + GetOffsetToUserSpace(firstFrame);
|
||||
nsRect preEffectsRect = aInvalidRect + toUserSpace;
|
||||
nsRect preEffectsRect = aInvalidRect.ToAppUnits(appUnitsPerDevPixel) + toUserSpace;
|
||||
|
||||
// Return ther result, relative to aFrame, not in user space:
|
||||
return filterFrame->GetPostFilterDirtyArea(firstFrame, preEffectsRect) -
|
||||
nsRect result = filterFrame->GetPostFilterDirtyArea(firstFrame, preEffectsRect) -
|
||||
toUserSpace;
|
||||
return result.ToOutsidePixels(appUnitsPerDevPixel);
|
||||
}
|
||||
|
||||
nsRect
|
||||
|
@ -116,8 +116,8 @@ public:
|
||||
* Used to adjust the area of a frame that needs to be invalidated to take
|
||||
* account of SVG effects.
|
||||
*/
|
||||
static nsRect
|
||||
AdjustInvalidAreaForSVGEffects(nsIFrame* aFrame, const nsRect& aInvalidRect);
|
||||
static nsIntRect
|
||||
AdjustInvalidAreaForSVGEffects(nsIFrame* aFrame, const nsIntRect& aInvalidRect);
|
||||
|
||||
/**
|
||||
* Figure out which area of the source is needed given an area to
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "nsSVGSVGElement.h"
|
||||
#include "nsSVGTextFrame.h"
|
||||
#include "nsSVGViewElement.h"
|
||||
#include "nsSubDocumentFrame.h"
|
||||
|
||||
namespace dom = mozilla::dom;
|
||||
|
||||
@ -505,6 +506,11 @@ public:
|
||||
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
|
||||
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx);
|
||||
|
||||
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion);
|
||||
|
||||
NS_DISPLAY_DECL_NAME("SVGOuterSVG", TYPE_SVG_OUTER_SVG)
|
||||
};
|
||||
|
||||
@ -570,6 +576,39 @@ nsDisplayOuterSVG::Paint(nsDisplayListBuilder* aBuilder,
|
||||
#endif
|
||||
}
|
||||
|
||||
static PLDHashOperator CheckForeignObjectInvalidatedArea(nsPtrHashKey<nsSVGForeignObjectFrame>* aEntry, void* aData)
|
||||
{
|
||||
nsRegion* region = static_cast<nsRegion*>(aData);
|
||||
region->Or(*region, aEntry->GetKey()->GetInvalidRegion());
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsRegion
|
||||
nsSVGOuterSVGFrame::FindInvalidatedForeignObjectFrameChildren(nsIFrame* aFrame)
|
||||
{
|
||||
nsRegion result;
|
||||
if (mForeignObjectHash.Count()) {
|
||||
mForeignObjectHash.EnumerateEntries(CheckForeignObjectInvalidatedArea, &result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayOuterSVG::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion)
|
||||
{
|
||||
nsSVGOuterSVGFrame *frame = static_cast<nsSVGOuterSVGFrame*>(mFrame);
|
||||
frame->InvalidateSVG(frame->FindInvalidatedForeignObjectFrameChildren(frame));
|
||||
|
||||
nsRegion result = frame->GetInvalidRegion();
|
||||
result.MoveBy(ToReferenceFrame());
|
||||
frame->ClearInvalidRegion();
|
||||
|
||||
nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
|
||||
aInvalidRegion->Or(*aInvalidRegion, result);
|
||||
}
|
||||
|
||||
// helper
|
||||
static inline bool
|
||||
DependsOnIntrinsicSize(const nsIFrame* aEmbeddingFrame)
|
||||
|
@ -144,6 +144,25 @@ public:
|
||||
return mCallingReflowSVG;
|
||||
}
|
||||
|
||||
void InvalidateSVG(const nsRegion& aRegion)
|
||||
{
|
||||
if (!aRegion.IsEmpty()) {
|
||||
mInvalidRegion.Or(mInvalidRegion, aRegion);
|
||||
InvalidateFrame();
|
||||
}
|
||||
}
|
||||
|
||||
void ClearInvalidRegion() { mInvalidRegion.SetEmpty(); }
|
||||
|
||||
const nsRegion& GetInvalidRegion() {
|
||||
if (!IsInvalid()) {
|
||||
mInvalidRegion.SetEmpty();
|
||||
}
|
||||
return mInvalidRegion;
|
||||
}
|
||||
|
||||
nsRegion FindInvalidatedForeignObjectFrameChildren(nsIFrame* aFrame);
|
||||
|
||||
protected:
|
||||
|
||||
bool mCallingReflowSVG;
|
||||
@ -164,10 +183,12 @@ protected:
|
||||
// A hash-set containing our nsSVGForeignObjectFrame descendants. Note we use
|
||||
// a hash-set to avoid the O(N^2) behavior we'd get tearing down an SVG frame
|
||||
// subtree if we were to use a list (see bug 381285 comment 20).
|
||||
nsTHashtable<nsVoidPtrHashKey> mForeignObjectHash;
|
||||
nsTHashtable<nsPtrHashKey<nsSVGForeignObjectFrame> > mForeignObjectHash;
|
||||
|
||||
nsAutoPtr<gfxMatrix> mCanvasTM;
|
||||
|
||||
nsRegion mInvalidRegion;
|
||||
|
||||
float mFullZoom;
|
||||
|
||||
bool mViewportInitialized;
|
||||
|
@ -415,6 +415,14 @@ nsSVGUtils::InvalidateBounds(nsIFrame *aFrame, bool aDuringUpdate,
|
||||
return;
|
||||
}
|
||||
|
||||
aFrame->InvalidateFrameSubtree();
|
||||
|
||||
if ((aFrame->GetType() == nsGkAtoms::svgPathGeometryFrame ||
|
||||
aFrame->GetType() == nsGkAtoms::svgGlyphFrame) &&
|
||||
NS_SVGDisplayListPaintingEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Okay, so now we pass the area that needs to be invalidated up our parent
|
||||
// chain, accounting for filter effects and transforms as we go, until we
|
||||
// reach our nsSVGOuterSVGFrame where we can invalidate:
|
||||
@ -479,8 +487,7 @@ nsSVGUtils::InvalidateBounds(nsIFrame *aFrame, bool aDuringUpdate,
|
||||
NS_ASSERTION(aFrame->GetStateBits() & NS_STATE_IS_OUTER_SVG,
|
||||
"SVG frames must always have an nsSVGOuterSVGFrame ancestor!");
|
||||
|
||||
static_cast<nsSVGOuterSVGFrame*>(aFrame)->InvalidateWithFlags(invalidArea,
|
||||
aFlags);
|
||||
static_cast<nsSVGOuterSVGFrame*>(aFrame)->InvalidateSVG(invalidArea);
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user