Bug 731959 - Display list support for the 'clip' property in SVG means referring to "AbsPos" clip is misleading. r=bz.

This commit is contained in:
Jonathan Watt
2012-03-02 08:28:56 +00:00
parent 0d1a26a0db
commit 45ab2bff1a
3 changed files with 39 additions and 34 deletions

View File

@@ -525,12 +525,12 @@ nsBlockFrame::InvalidateInternal(const nsRect& aDamageRect,
// be able to invalidate areas outside the 'clip'.
if (aForChild) {
const nsStyleDisplay* disp = GetStyleDisplay();
nsRect absPosClipRect;
if (GetAbsPosClipRect(disp, &absPosClipRect, GetSize())) {
nsRect clipRect;
if (GetClipPropClipRect(disp, &clipRect, GetSize())) {
// Restrict the invalidated area to abs-pos clip rect
// abs-pos clipping clips everything in the frame
nsRect r;
if (r.IntersectRect(aDamageRect, absPosClipRect - nsPoint(aX, aY))) {
if (r.IntersectRect(aDamageRect, clipRect - nsPoint(aX, aY))) {
nsBlockFrameSuper::InvalidateInternal(r, aX, aY, this, aFlags);
}
return;

View File

@@ -352,7 +352,7 @@ static bool ApplyOverflowClipping(nsDisplayListBuilder* aBuilder,
const nsStyleDisplay* aDisp,
nsRect* aRect);
static bool ApplyAbsPosClipping(nsDisplayListBuilder* aBuilder,
static bool ApplyClipPropClipping(nsDisplayListBuilder* aBuilder,
const nsStyleDisplay* aDisp,
const nsIFrame* aFrame,
nsRect* aRect);
@@ -962,7 +962,7 @@ nsIFrame::Preserves3DChildren() const
nsRect temp;
return (!ApplyOverflowClipping(nsnull, this, GetStyleDisplay(), &temp) &&
!ApplyAbsPosClipping(nsnull, GetStyleDisplay(), this, &temp) &&
!ApplyClipPropClipping(nsnull, GetStyleDisplay(), this, &temp) &&
!nsSVGIntegrationUtils::UsingEffectsForFrame(this));
}
@@ -1448,8 +1448,8 @@ nsFrame::DisplayBorderBackgroundOutline(nsDisplayListBuilder* aBuilder,
}
bool
nsIFrame::GetAbsPosClipRect(const nsStyleDisplay* aDisp, nsRect* aRect,
const nsSize& aSize) const
nsIFrame::GetClipPropClipRect(const nsStyleDisplay* aDisp, nsRect* aRect,
const nsSize& aSize) const
{
NS_PRECONDITION(aRect, "Must have aRect out parameter");
@@ -1467,10 +1467,10 @@ nsIFrame::GetAbsPosClipRect(const nsStyleDisplay* aDisp, nsRect* aRect,
return true;
}
static bool ApplyAbsPosClipping(nsDisplayListBuilder* aBuilder,
static bool ApplyClipPropClipping(nsDisplayListBuilder* aBuilder,
const nsStyleDisplay* aDisp, const nsIFrame* aFrame,
nsRect* aRect) {
if (!aFrame->GetAbsPosClipRect(aDisp, aRect, aFrame->GetSize()))
if (!aFrame->GetClipPropClipRect(aDisp, aRect, aFrame->GetSize()))
return false;
if (aBuilder) {
@@ -1562,10 +1562,10 @@ protected:
bool mHaveRadius;
};
class nsAbsPosClipWrapper : public nsDisplayWrapper
class nsDisplayClipPropWrapper : public nsDisplayWrapper
{
public:
nsAbsPosClipWrapper(const nsRect& aRect)
nsDisplayClipPropWrapper(const nsRect& aRect)
: mRect(aRect) {}
virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList) {
@@ -1734,15 +1734,15 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
if (IsFrameOfType(eReplaced) && !IsVisibleForPainting(aBuilder))
return NS_OK;
nsRect absPosClip;
nsRect clipPropClip;
const nsStyleDisplay* disp = GetStyleDisplay();
// We can stop right away if this is a zero-opacity stacking context and
// we're painting.
if (disp->mOpacity == 0.0 && aBuilder->IsForPainting())
return NS_OK;
bool applyAbsPosClipping =
ApplyAbsPosClipping(aBuilder, disp, this, &absPosClip);
bool applyClipPropClipping =
ApplyClipPropClipping(aBuilder, disp, this, &clipPropClip);
nsRect dirtyRect = aDirtyRect;
bool inTransform = aBuilder->IsInTransform();
@@ -1770,9 +1770,9 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
inTransform = true;
}
if (applyAbsPosClipping) {
if (applyClipPropClipping) {
dirtyRect.IntersectRect(dirtyRect,
absPosClip - aBuilder->ToReferenceFrame(this));
clipPropClip - aBuilder->ToReferenceFrame(this));
}
bool usingSVGEffects = nsSVGIntegrationUtils::UsingEffectsForFrame(this);
@@ -1863,9 +1863,9 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
/* If we have absolute position clipping and we have, or will have, items to
* be clipped, wrap the list in a clip wrapper.
*/
if (applyAbsPosClipping &&
if (applyClipPropClipping &&
(!resultList.IsEmpty() || usingSVGEffects)) {
nsAbsPosClipWrapper wrapper(absPosClip);
nsDisplayClipPropWrapper wrapper(clipPropClip);
nsDisplayItem* item = wrapper.WrapList(aBuilder, this, &resultList);
if (!item)
return NS_ERROR_OUT_OF_MEMORY;
@@ -2088,15 +2088,15 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
}
} else {
nsRect clipRect;
bool applyAbsPosClipping =
ApplyAbsPosClipping(aBuilder, disp, child, &clipRect);
bool applyClipPropClipping =
ApplyClipPropClipping(aBuilder, disp, child, &clipRect);
// A pseudo-stacking context (e.g., a positioned element with z-index auto).
// We allow positioned descendants of the child to escape to our parent
// stacking context's positioned descendant list, because they might be
// z-index:non-auto
nsDisplayListCollection pseudoStack;
nsRect clippedDirtyRect = dirty;
if (applyAbsPosClipping) {
if (applyClipPropClipping) {
// clipRect is in builder-reference-frame coordinates,
// dirty/clippedDirtyRect are in child coordinates
clippedDirtyRect.IntersectRect(clippedDirtyRect,
@@ -2115,8 +2115,8 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
}
if (NS_SUCCEEDED(rv)) {
if (applyAbsPosClipping) {
nsAbsPosClipWrapper wrapper(clipRect);
if (applyClipPropClipping) {
nsDisplayClipPropWrapper wrapper(clipRect);
rv = wrapper.WrapListsInPlace(aBuilder, child, pseudoStack);
}
}
@@ -6738,13 +6738,13 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
true);
// Absolute position clipping
bool didHaveAbsPosClip = (GetStateBits() & NS_FRAME_HAS_CLIP) != 0;
nsRect absPosClipRect;
bool hasAbsPosClip = GetAbsPosClipRect(disp, &absPosClipRect, aNewSize);
if (hasAbsPosClip) {
bool didHaveClipPropClip = (GetStateBits() & NS_FRAME_HAS_CLIP) != 0;
nsRect clipPropClipRect;
bool hasClipPropClip = GetClipPropClipRect(disp, &clipPropClipRect, aNewSize);
if (hasClipPropClip) {
NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
nsRect& o = aOverflowAreas.Overflow(otype);
o.IntersectRect(o, absPosClipRect);
o.IntersectRect(o, clipPropClipRect);
}
AddStateBits(NS_FRAME_HAS_CLIP);
} else {
@@ -6799,7 +6799,7 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
// to do anything here since removing those styles can't require
// repainting of areas that weren't in the old overflow area.
Invalidate(aOverflowAreas.VisualOverflow());
} else if (hasAbsPosClip || didHaveAbsPosClip) {
} else if (hasClipPropClip || didHaveClipPropClip) {
// If we are (or were) clipped by the 'clip' property, and our
// overflow area changes, it might be because the clipping changed.
// The nsChangeHint_RepaintFrame for the style change will only

View File

@@ -2538,12 +2538,17 @@ NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::EmbeddingLevelProperty()))
virtual bool SupportsVisibilityHidden() { return true; }
/**
* Returns true if the frame is absolutely positioned and has a clip
* rect set via the 'clip' property. If true, then we also set aRect
* to the computed clip rect coordinates relative to this frame's origin.
* aRect must not be null!
* Returns true if the frame has a valid clip rect set via the 'clip'
* property, and the 'clip' property applies to this frame. The 'clip'
* property applies to HTML frames if they are absolutely positioned. The
* 'clip' property applies to SVG frames regardless of the value of the
* 'position' property.
*
* If this method returns true, then we also set aRect to the computed clip
* rect, with coordinates relative to this frame's origin. aRect must not be
* null!
*/
bool GetAbsPosClipRect(const nsStyleDisplay* aDisp, nsRect* aRect,
bool GetClipPropClipRect(const nsStyleDisplay* aDisp, nsRect* aRect,
const nsSize& aSize) const;
/**