Bug 516885. Pass separate visible-before-move and visible-after-move regions into ComputeVisibility, to make code clearer because we don't have to overload a single region, and which also lets us fix ambiguities related to clipping. r=dbaron

This commit is contained in:
Robert O'Callahan 2009-10-07 17:28:41 +13:00
parent e7c528888e
commit 56aad34bd4
8 changed files with 217 additions and 83 deletions

View File

@ -262,21 +262,23 @@ nsDisplayListBuilder::Allocate(size_t aSize) {
void
nsDisplayListBuilder::AccumulateVisibleRegionOfMovingContent(const nsRegion& aMovingContent,
const nsRegion& aVisibleRegion)
const nsRegion& aVisibleRegionBeforeMove,
const nsRegion& aVisibleRegionAfterMove)
{
if (!mSaveVisibleRegionOfMovingContent)
return;
// Grab the union of aMovingContent (after the move) with
// aMovingContent - mMoveDelta (before the move)
nsRegion r = aMovingContent;
r.MoveBy(-mMoveDelta);
r.Or(r, aMovingContent);
// Reduce to the part that's visible after the move
r.And(r, aVisibleRegion);
// Accumulate it into our result
nsRegion beforeRegion = aMovingContent;
beforeRegion.MoveBy(-mMoveDelta);
beforeRegion.And(beforeRegion, aVisibleRegionBeforeMove);
nsRegion afterRegion = aMovingContent;
afterRegion.And(afterRegion, aVisibleRegionAfterMove);
// Accumulate these regions into our result
mSaveVisibleRegionOfMovingContent->Or(
*mSaveVisibleRegionOfMovingContent, r);
*mSaveVisibleRegionOfMovingContent, beforeRegion);
mSaveVisibleRegionOfMovingContent->Or(
*mSaveVisibleRegionOfMovingContent, afterRegion);
mSaveVisibleRegionOfMovingContent->SimplifyOutward(15);
}
@ -314,15 +316,20 @@ nsDisplayList::GetBounds(nsDisplayListBuilder* aBuilder) const {
void
nsDisplayList::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) {
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove) {
NS_ASSERTION((aVisibleRegionBeforeMove != nsnull) == aBuilder->HasMovingFrames(),
"Should have aVisibleRegionBeforeMove when there are moving frames");
nsAutoTArray<nsDisplayItem*, 512> elements;
FlattenTo(&elements);
// Accumulate the bounds of all moving content we find in this list
nsRect movingContentAccumulatedBounds;
// Store an overapproximation of the visible region for the moving
// Store an overapproximation of the visible regions for the moving
// content in this list
nsRegion movingContentVisibleRegion;
nsRegion movingContentVisibleRegionBeforeMove;
nsRegion movingContentVisibleRegionAfterMove;
for (PRInt32 i = elements.Length() - 1; i >= 0; --i) {
nsDisplayItem* item = elements[i];
@ -342,7 +349,8 @@ nsDisplayList::ComputeVisibility(nsDisplayListBuilder* aBuilder,
if (movingContentAccumulatedBounds.IsEmpty()) {
// *aVisibleRegion can only shrink during this loop, so storing
// the first one we see is a sound overapproximation
movingContentVisibleRegion = *aVisibleRegion;
movingContentVisibleRegionBeforeMove = *aVisibleRegionBeforeMove;
movingContentVisibleRegionAfterMove = *aVisibleRegion;
}
nscoord appUnitsPerPixel = f->PresContext()->AppUnitsPerDevPixel();
nsRect roundOutBounds = bounds.
@ -352,26 +360,29 @@ nsDisplayList::ComputeVisibility(nsDisplayListBuilder* aBuilder,
}
nsRegion itemVisible;
itemVisible.And(*aVisibleRegion, bounds);
if (aVisibleRegionBeforeMove) {
// Treat the item as visible if it was visible before or after the move.
itemVisible.Or(*aVisibleRegion, *aVisibleRegionBeforeMove);
itemVisible.And(itemVisible, bounds);
} else {
itemVisible.And(*aVisibleRegion, bounds);
}
item->mVisibleRect = itemVisible.GetBounds();
if (!item->mVisibleRect.IsEmpty() &&
item->ComputeVisibility(aBuilder, aVisibleRegion)) {
item->ComputeVisibility(aBuilder, aVisibleRegion, aVisibleRegionBeforeMove)) {
AppendToBottom(item);
// Subtract opaque items from the visible region
if (item->IsOpaque(aBuilder) && f) {
nsRect opaqueArea;
if (isMoving) {
// The display list should include items for both the before and after
// states (see nsLayoutUtils::ComputeRepaintRegionForCopy. So the
// only area we want to cover is the area that was opaque in the
// before state and in the after state.
opaqueArea.IntersectRect(bounds - aBuilder->GetMoveDelta(), bounds);
} else {
opaqueArea = bounds;
// Subtract opaque item from the visible region
aBuilder->SubtractFromVisibleRegion(aVisibleRegion, nsRegion(bounds));
if (aVisibleRegionBeforeMove) {
nsRect opaqueAreaBeforeMove =
isMoving ? bounds - aBuilder->GetMoveDelta() : bounds;
aBuilder->SubtractFromVisibleRegion(aVisibleRegionBeforeMove,
nsRegion(opaqueAreaBeforeMove));
}
aBuilder->SubtractFromVisibleRegion(aVisibleRegion, nsRegion(opaqueArea));
}
} else {
item->~nsDisplayItem();
@ -379,7 +390,9 @@ nsDisplayList::ComputeVisibility(nsDisplayListBuilder* aBuilder,
}
aBuilder->AccumulateVisibleRegionOfMovingContent(
nsRegion(movingContentAccumulatedBounds), movingContentVisibleRegion);
nsRegion(movingContentAccumulatedBounds),
movingContentVisibleRegionBeforeMove,
movingContentVisibleRegionAfterMove);
#ifdef DEBUG
mDidComputeVisibility = PR_TRUE;
@ -719,13 +732,20 @@ nsDisplayOutline::Paint(nsDisplayListBuilder* aBuilder,
PRBool
nsDisplayOutline::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) {
if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion))
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove) {
NS_ASSERTION((aVisibleRegionBeforeMove != nsnull) == aBuilder->HasMovingFrames(),
"Should have aVisibleRegionBeforeMove when there are moving frames");
if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
aVisibleRegionBeforeMove))
return PR_FALSE;
const nsStyleOutline* outline = mFrame->GetStyleOutline();
nsPoint origin = aBuilder->ToReferenceFrame(mFrame);
if (nsRect(origin, mFrame->GetSize()).Contains(aVisibleRegion->GetBounds()) &&
nsRect borderBox(aBuilder->ToReferenceFrame(mFrame), mFrame->GetSize());
if (borderBox.Contains(aVisibleRegion->GetBounds()) &&
(!aVisibleRegionBeforeMove ||
borderBox.Contains(aVisibleRegionBeforeMove->GetBounds())) &&
!nsLayoutUtils::HasNonZeroCorner(outline->mOutlineRadius)) {
if (outline->mOutlineOffset >= 0) {
// the visible region is entirely inside the border-rect, and the outline
@ -747,14 +767,21 @@ nsDisplayCaret::Paint(nsDisplayListBuilder* aBuilder,
PRBool
nsDisplayBorder::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) {
if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion))
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove) {
NS_ASSERTION((aVisibleRegionBeforeMove != nsnull) == aBuilder->HasMovingFrames(),
"Should have aVisibleRegionBeforeMove when there are moving frames");
if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
aVisibleRegionBeforeMove))
return PR_FALSE;
nsRect paddingRect = mFrame->GetPaddingRect() - mFrame->GetPosition() +
aBuilder->ToReferenceFrame(mFrame);
const nsStyleBorder *styleBorder;
if (paddingRect.Contains(aVisibleRegion->GetBounds()) &&
(!aVisibleRegionBeforeMove ||
paddingRect.Contains(aVisibleRegionBeforeMove->GetBounds())) &&
!(styleBorder = mFrame->GetStyleBorder())->IsBorderImageLoaded() &&
!nsLayoutUtils::HasNonZeroCorner(styleBorder->mBorderRadius)) {
// the visible region is entirely inside the content rect, and no part
@ -797,13 +824,21 @@ nsDisplayBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder) {
PRBool
nsDisplayBoxShadowOuter::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) {
if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion))
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove) {
NS_ASSERTION((aVisibleRegionBeforeMove != nsnull) == aBuilder->HasMovingFrames(),
"Should have aVisibleRegionBeforeMove when there are moving frames");
if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
aVisibleRegionBeforeMove))
return PR_FALSE;
nsPoint origin = aBuilder->ToReferenceFrame(mFrame);
nsRect visibleBounds = aVisibleRegion->GetBounds();
if (aVisibleRegionBeforeMove) {
visibleBounds.UnionRect(visibleBounds, aVisibleRegionBeforeMove->GetBounds());
}
nsRect frameRect(origin, mFrame->GetSize());
const nsRect visibleBounds = aVisibleRegion->GetBounds();
if (!frameRect.Contains(visibleBounds))
return PR_TRUE;
@ -856,8 +891,9 @@ nsDisplayWrapList::GetBounds(nsDisplayListBuilder* aBuilder) {
PRBool
nsDisplayWrapList::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) {
mList.ComputeVisibility(aBuilder, aVisibleRegion);
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove) {
mList.ComputeVisibility(aBuilder, aVisibleRegion, aVisibleRegionBeforeMove);
// If none of the items are visible, they will all have been deleted
return mList.GetTop() != nsnull;
}
@ -1010,19 +1046,32 @@ void nsDisplayOpacity::Paint(nsDisplayListBuilder* aBuilder,
}
PRBool nsDisplayOpacity::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) {
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove) {
NS_ASSERTION((aVisibleRegionBeforeMove != nsnull) == aBuilder->HasMovingFrames(),
"Should have aVisibleRegionBeforeMove when there are moving frames");
// Our children are translucent so we should not allow them to subtract
// area from aVisibleRegion. We do need to find out what is visible under
// our children in the temporary compositing buffer, because if our children
// paint our entire bounds opaquely then we don't need an alpha channel in
// the temporary compositing buffer.
nsRegion visibleUnderChildren = *aVisibleRegion;
nsRegion visibleUnderChildrenBeforeMove;
if (aVisibleRegionBeforeMove) {
visibleUnderChildrenBeforeMove = *aVisibleRegionBeforeMove;
}
PRBool anyVisibleChildren =
nsDisplayWrapList::ComputeVisibility(aBuilder, &visibleUnderChildren);
nsDisplayWrapList::ComputeVisibility(aBuilder, &visibleUnderChildren,
aVisibleRegionBeforeMove ? &visibleUnderChildrenBeforeMove : nsnull);
if (!anyVisibleChildren)
return PR_FALSE;
mNeedAlpha = visibleUnderChildren.Intersects(mVisibleRect);
// If we're analyzing moving content, then it doesn't really matter
// what we set mNeedAlpha to, so let's conservatively set it to true so
// we don't have to worry about getting it "correct" for the moving case.
mNeedAlpha = aVisibleRegionBeforeMove ||
visibleUnderChildren.Intersects(mVisibleRect);
return PR_TRUE;
}
@ -1073,12 +1122,14 @@ void nsDisplayClip::Paint(nsDisplayListBuilder* aBuilder,
}
PRBool nsDisplayClip::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) {
nsRegion clipped;
clipped.And(*aVisibleRegion, mClip);
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove) {
NS_ASSERTION((aVisibleRegionBeforeMove != nsnull) == aBuilder->HasMovingFrames(),
"Should have aVisibleRegionBeforeMove when there are moving frames");
if (aBuilder->HasMovingFrames() &&
!aBuilder->IsMovingFrame(mClippingFrame)) {
PRBool isMoving = aBuilder->IsMovingFrame(mClippingFrame);
if (aBuilder->HasMovingFrames() && !isMoving) {
// There may be some clipped moving children that were visible before
// but are clipped out now. Conservatively assume they were there
// and add their possible area to the visible region of moving
@ -1087,14 +1138,35 @@ PRBool nsDisplayClip::ComputeVisibility(nsDisplayListBuilder* aBuilder,
// totally clipped out.
nsRegion r;
r.Sub(mClip + aBuilder->GetMoveDelta(), mClip);
aBuilder->AccumulateVisibleRegionOfMovingContent(r, *aVisibleRegion);
// These hypothetical items are not visible after the move, so we pass
// an empty region for the after-move visible region to make sure they
// don't get added in the after-move position, only the before-move position.
aBuilder->AccumulateVisibleRegionOfMovingContent(r, *aVisibleRegionBeforeMove,
nsRegion());
}
nsRegion clipped;
clipped.And(*aVisibleRegion, mClip);
nsRegion clippedBeforeMove;
if (aVisibleRegionBeforeMove) {
nsRect beforeMoveClip = isMoving ? mClip - aBuilder->GetMoveDelta() : mClip;
clippedBeforeMove.And(*aVisibleRegionBeforeMove, beforeMoveClip);
}
nsRegion finalClipped(clipped);
nsRegion finalClippedBeforeMove(clippedBeforeMove);
PRBool anyVisible =
nsDisplayWrapList::ComputeVisibility(aBuilder, &finalClipped,
aVisibleRegionBeforeMove ? &finalClippedBeforeMove : nsnull);
nsRegion removed;
removed.Sub(clipped, finalClipped);
aBuilder->SubtractFromVisibleRegion(aVisibleRegion, removed);
if (aVisibleRegionBeforeMove) {
removed.Sub(clippedBeforeMove, finalClippedBeforeMove);
aBuilder->SubtractFromVisibleRegion(aVisibleRegionBeforeMove, removed);
}
nsRegion rNew(clipped);
PRBool anyVisible = nsDisplayWrapList::ComputeVisibility(aBuilder, &rNew);
nsRegion subtracted;
subtracted.Sub(clipped, rNew);
aBuilder->SubtractFromVisibleRegion(aVisibleRegion, subtracted);
return anyVisible;
}
@ -1300,14 +1372,26 @@ void nsDisplayTransform::Paint(nsDisplayListBuilder *aBuilder,
}
PRBool nsDisplayTransform::ComputeVisibility(nsDisplayListBuilder *aBuilder,
nsRegion *aVisibleRegion)
nsRegion *aVisibleRegion,
nsRegion *aVisibleRegionBeforeMove)
{
NS_ASSERTION((aVisibleRegionBeforeMove != nsnull) == aBuilder->HasMovingFrames(),
"Should have aVisibleRegionBeforeMove when there are moving frames");
/* As we do this, we need to be sure to
* untransform the visible rect, since we want everything that's painting to
* think that it's painting in its original rectangular coordinate space. */
nsRegion untransformedVisible =
UntransformRect(mVisibleRect, mFrame, aBuilder->ToReferenceFrame(mFrame));
mStoredList.ComputeVisibility(aBuilder, &untransformedVisible);
nsRegion untransformedVisibleBeforeMove;
if (aVisibleRegionBeforeMove) {
// mVisibleRect contains areas visible before and after the move, so it's
// OK (although conservative) to just use the same regions here.
untransformedVisibleBeforeMove = untransformedVisible;
}
mStoredList.ComputeVisibility(aBuilder, &untransformedVisible,
&untransformedVisibleBeforeMove);
return PR_TRUE;
}
@ -1534,15 +1618,25 @@ void nsDisplaySVGEffects::Paint(nsDisplayListBuilder* aBuilder,
}
PRBool nsDisplaySVGEffects::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) {
nsPoint offset = aBuilder->ToReferenceFrame(mEffectsFrame);
nsRect dirtyRect = nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(mEffectsFrame,
mVisibleRect - offset) + offset;
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove) {
NS_ASSERTION((aVisibleRegionBeforeMove != nsnull) == aBuilder->HasMovingFrames(),
"Should have aVisibleRegionBeforeMove when there are moving frames");
// Our children may be translucent so we should not allow them to subtract
// area from aVisibleRegion.
nsRegion childrenVisibleRegion(dirtyRect);
nsDisplayWrapList::ComputeVisibility(aBuilder, &childrenVisibleRegion);
nsPoint offset = aBuilder->ToReferenceFrame(mEffectsFrame);
nsRect dirtyRect =
nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(mEffectsFrame,
mVisibleRect - offset) +
offset;
// Our children may be made translucent or arbitrarily deformed so we should
// not allow them to subtract area from aVisibleRegion.
nsRegion childrenVisible(dirtyRect);
// mVisibleRect contains areas visible before and after the move, so it's
// OK (although conservative) to just use the same regions here.
nsRegion childrenVisibleBeforeMove(dirtyRect);
nsDisplayWrapList::ComputeVisibility(aBuilder, &childrenVisible,
aVisibleRegionBeforeMove ? &childrenVisibleBeforeMove : nsnull);
return PR_TRUE;
}

View File

@ -191,7 +191,8 @@ public:
* recorded region of visible moving content.
*/
void AccumulateVisibleRegionOfMovingContent(const nsRegion& aMovingContent,
const nsRegion& aVisibleRegion);
const nsRegion& aVisibleRegionBeforeMove,
const nsRegion& aVisibleRegionAfterMove);
/**
* @return PR_TRUE if aFrame is, or is a descendant of, the hypothetical
@ -552,19 +553,27 @@ public:
* On entry, aVisibleRegion contains the region (relative to ReferenceFrame())
* which may be visible. If the display item opaquely covers an area, it
* can remove that area from aVisibleRegion before returning.
* If we're doing scroll analysis with moving frames, then
* aVisibleRegionBeforeMove will be non-null and contains the region that
* would have been visible before the move. aVisibleRegion contains the
* region that is visible after the move.
* nsDisplayList::ComputeVisibility automatically subtracts the bounds
* of items that return true from IsOpaque(), and automatically
* removes items whose bounds do not intersect the visible area,
* so implementations of nsDisplayItem::ComputeVisibility do not
* need to do these things.
* nsDisplayList::ComputeVisibility will already have set mVisibleRect on
* this item to the intersection of *aVisibleRegion and this item's bounds.
* this item to the intersection of *aVisibleRegion (unioned with
* *aVisibleRegionBeforeMove, if that's non-null) and this item's bounds.
*
* @return PR_TRUE if the item is visible, PR_FALSE if no part of the item
* is visible
*/
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) { return PR_TRUE; }
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove)
{ return PR_TRUE; }
/**
* Try to merge with the other item (which is below us in the display
* list). This gets used by nsDisplayClip to coalesce clipping operations
@ -788,7 +797,9 @@ public:
* @param aVisibleRegion the area that is visible, relative to the
* reference frame; on return, this contains the area visible under the list
*/
void ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion);
void ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove);
/**
* Paint the list to the rendering context. We assume that (0,0) in aCtx
* corresponds to the origin of the reference frame. For best results,
@ -1108,7 +1119,9 @@ public:
virtual Type GetType() { return TYPE_BORDER; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion);
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove);
NS_DISPLAY_DECL_NAME("Border")
};
@ -1195,7 +1208,9 @@ public:
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion);
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove);
NS_DISPLAY_DECL_NAME("BoxShadowOuter")
};
@ -1234,7 +1249,9 @@ public:
virtual Type GetType() { return TYPE_OUTLINE; }
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion);
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove);
NS_DISPLAY_DECL_NAME("Outline")
};
@ -1291,7 +1308,8 @@ public:
virtual PRBool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion);
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove);
virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) {
NS_WARNING("This list should already have been flattened!!!");
return PR_FALSE;
@ -1359,7 +1377,8 @@ public:
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion);
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove);
virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
NS_DISPLAY_DECL_NAME("Opacity")
@ -1396,7 +1415,8 @@ public:
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion);
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove);
virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
NS_DISPLAY_DECL_NAME("Clip")
@ -1437,7 +1457,8 @@ public:
}
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion);
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove);
virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
NS_DISPLAY_DECL_NAME("SVGEffects")
@ -1494,7 +1515,8 @@ public:
virtual void Paint(nsDisplayListBuilder *aBuilder,
nsIRenderingContext *aCtx);
virtual PRBool ComputeVisibility(nsDisplayListBuilder *aBuilder,
nsRegion *aVisibleRegion);
nsRegion *aVisibleRegion,
nsRegion *aVisibleRegionBeforeMove);
virtual PRBool TryMerge(nsDisplayListBuilder *aBuilder, nsDisplayItem *aItem);
/**

View File

@ -1118,7 +1118,7 @@ nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFra
#endif
nsRegion visibleRegion = aDirtyRegion;
list.ComputeVisibility(&builder, &visibleRegion);
list.ComputeVisibility(&builder, &visibleRegion, nsnull);
#ifdef DEBUG
if (gDumpPaintList) {
@ -1285,7 +1285,8 @@ nsLayoutUtils::ComputeRepaintRegionForCopy(nsIFrame* aRootFrame,
// Optimize for visibility, but frames under aMovingFrame will not be
// considered opaque, so they don't cover non-moving frames.
nsRegion visibleRegion(aUpdateRect);
list.ComputeVisibility(&builder, &visibleRegion);
nsRegion visibleRegionBeforeMove(aUpdateRect);
list.ComputeVisibility(&builder, &visibleRegion, &visibleRegionBeforeMove);
#ifdef DEBUG
if (gDumpRepaintRegionForCopy) {

View File

@ -2378,7 +2378,7 @@ nsRootPresContext::GetPluginGeometryUpdates(nsIFrame* aChangedSubtree,
#endif
nsRegion visibleRegion(bounds);
list.ComputeVisibility(&builder, &visibleRegion);
list.ComputeVisibility(&builder, &visibleRegion, nsnull);
#ifdef DEBUG
if (gDumpPluginList) {

View File

@ -5350,7 +5350,7 @@ PresShell::RenderDocument(const nsRect& aRect, PRUint32 aFlags,
rc->Init(devCtx, aThebesContext);
nsRegion region(rect);
list.ComputeVisibility(&builder, &region);
list.ComputeVisibility(&builder, &region, nsnull);
list.Paint(&builder, rc);
// Flush the list so we don't trigger the IsEmpty-on-destruction assertion
list.DeleteAll();
@ -5640,7 +5640,7 @@ PresShell::PaintRangePaintInfo(nsTArray<nsAutoPtr<RangePaintInfo> >* aItems,
aArea.MoveBy(-rangeInfo->mRootOffset.x, -rangeInfo->mRootOffset.y);
nsRegion visible(aArea);
rangeInfo->mList.ComputeVisibility(&rangeInfo->mBuilder, &visible);
rangeInfo->mList.ComputeVisibility(&rangeInfo->mBuilder, &visible, nsnull);
rangeInfo->mList.Paint(&rangeInfo->mBuilder, rc);
aArea.MoveBy(rangeInfo->mRootOffset.x, rangeInfo->mRootOffset.y);
}

View File

@ -87,6 +87,10 @@ body > div {
<div style="width:300px; height:200px; background:-moz-linear-gradient(left, right, from(red), to(black));"></div>
</div>
<div id="testMovingClipArea">
<div style="margin-top:20px; height:20px; margin-bottom:300px; background-color:blue; overflow:hidden;"></div>
</div>
<script>
var tests = document.querySelectorAll("body>div");
var currentTest = -1;
@ -216,6 +220,13 @@ function testSimpleScrollWithSubpixelOffset4(blitRegion, paintRegion) {
"Should not repaint area that was blitted: " + paintRegion.toString());
}
function testMovingClipArea(blitRegion, paintRegion) {
ok(blitRegion.equalsRegion(new Region([[0,0,200,40]])),
"Should blit everything that's affected: " + blitRegion.toString());
ok(paintRegion.isEmpty(),
"Shouldn't repaint anything: " + paintRegion.toString());
}
function clientRectToRect(cr)
{
return [cr.left, cr.top, cr.right, cr.bottom];

View File

@ -1155,10 +1155,15 @@ nsDisplayPlugin::Paint(nsDisplayListBuilder* aBuilder,
PRBool
nsDisplayPlugin::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion)
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove)
{
NS_ASSERTION((aVisibleRegionBeforeMove != nsnull) == aBuilder->HasMovingFrames(),
"Should have aVisibleRegionBeforeMove when there are moving frames");
mVisibleRegion.And(*aVisibleRegion, GetBounds(aBuilder));
return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion);
return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
aVisibleRegionBeforeMove);
}
PRBool

View File

@ -254,7 +254,8 @@ public:
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx);
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion);
nsRegion* aVisibleRegion,
nsRegion* aVisibleRegionBeforeMove);
NS_DISPLAY_DECL_NAME("Plugin")