mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 428156. Relanding. Make ComputeRepaintRegionForCopy handle non-moving frames that clip moving frames. r+sr=dbaron
This commit is contained in:
parent
bb0afdab7b
commit
a091e3d5c6
@ -852,15 +852,17 @@ PRBool nsDisplayOpacity::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem*
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsDisplayClip::nsDisplayClip(nsIFrame* aFrame, nsDisplayItem* aItem,
|
||||
const nsRect& aRect)
|
||||
: nsDisplayWrapList(aFrame, aItem), mClip(aRect) {
|
||||
nsDisplayClip::nsDisplayClip(nsIFrame* aFrame, nsIFrame* aClippingFrame,
|
||||
nsDisplayItem* aItem, const nsRect& aRect)
|
||||
: nsDisplayWrapList(aFrame, aItem),
|
||||
mClippingFrame(aClippingFrame), mClip(aRect) {
|
||||
MOZ_COUNT_CTOR(nsDisplayClip);
|
||||
}
|
||||
|
||||
nsDisplayClip::nsDisplayClip(nsIFrame* aFrame, nsDisplayList* aList,
|
||||
const nsRect& aRect)
|
||||
: nsDisplayWrapList(aFrame, aList), mClip(aRect) {
|
||||
nsDisplayClip::nsDisplayClip(nsIFrame* aFrame, nsIFrame* aClippingFrame,
|
||||
nsDisplayList* aList, const nsRect& aRect)
|
||||
: nsDisplayWrapList(aFrame, aList),
|
||||
mClippingFrame(aClippingFrame), mClip(aRect) {
|
||||
MOZ_COUNT_CTOR(nsDisplayClip);
|
||||
}
|
||||
|
||||
@ -903,7 +905,7 @@ PRBool nsDisplayClip::TryMerge(nsDisplayListBuilder* aBuilder,
|
||||
if (aItem->GetType() != TYPE_CLIP)
|
||||
return PR_FALSE;
|
||||
nsDisplayClip* other = static_cast<nsDisplayClip*>(aItem);
|
||||
if (other->mClip != mClip)
|
||||
if (other->mClip != mClip || other->mClippingFrame != mClippingFrame)
|
||||
return PR_FALSE;
|
||||
mList.AppendToBottom(&other->mList);
|
||||
return PR_TRUE;
|
||||
@ -911,5 +913,6 @@ PRBool nsDisplayClip::TryMerge(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
nsDisplayWrapList* nsDisplayClip::WrapWithClone(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem) {
|
||||
return new (aBuilder) nsDisplayClip(aItem->GetUnderlyingFrame(), aItem, mClip);
|
||||
return new (aBuilder)
|
||||
nsDisplayClip(aItem->GetUnderlyingFrame(), mClippingFrame, aItem, mClip);
|
||||
}
|
||||
|
@ -1190,8 +1190,15 @@ private:
|
||||
*/
|
||||
class nsDisplayClip : public nsDisplayWrapList {
|
||||
public:
|
||||
nsDisplayClip(nsIFrame* aFrame, nsDisplayItem* aItem, const nsRect& aRect);
|
||||
nsDisplayClip(nsIFrame* aFrame, nsDisplayList* aList, const nsRect& aRect);
|
||||
/**
|
||||
* @param aFrame the frame that should be considered the underlying
|
||||
* frame for this content, e.g. the frame whose z-index we have.
|
||||
* @param aClippingFrame the frame that is inducing the clipping.
|
||||
*/
|
||||
nsDisplayClip(nsIFrame* aFrame, nsIFrame* aClippingFrame,
|
||||
nsDisplayItem* aItem, const nsRect& aRect);
|
||||
nsDisplayClip(nsIFrame* aFrame, nsIFrame* aClippingFrame,
|
||||
nsDisplayList* aList, const nsRect& aRect);
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
virtual ~nsDisplayClip();
|
||||
#endif
|
||||
@ -1207,12 +1214,18 @@ public:
|
||||
|
||||
nsRect GetClipRect() { return mClip; }
|
||||
void SetClipRect(const nsRect& aRect) { mClip = aRect; }
|
||||
nsIFrame* GetClippingFrame() { return mClippingFrame; }
|
||||
|
||||
virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem);
|
||||
|
||||
private:
|
||||
nsRect mClip;
|
||||
// The frame that is responsible for the clipping. This may be different
|
||||
// from mFrame because mFrame represents the content that is being
|
||||
// clipped, and for example may be used to obtain the z-index of the
|
||||
// content.
|
||||
nsIFrame* mClippingFrame;
|
||||
nsRect mClip;
|
||||
};
|
||||
|
||||
#endif /*NSDISPLAYLIST_H_*/
|
||||
|
@ -1017,8 +1017,25 @@ AddItemsToRegion(nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
|
||||
nsDisplayList* sublist = item->GetList();
|
||||
if (sublist) {
|
||||
if (item->GetType() == nsDisplayItem::TYPE_CLIP) {
|
||||
nsRect clip;
|
||||
clip.IntersectRect(aClipRect, static_cast<nsDisplayClip*>(item)->GetClipRect());
|
||||
nsDisplayClip* clipItem = static_cast<nsDisplayClip*>(item);
|
||||
nsRect clip = aClipRect;
|
||||
// If the clipping frame is moving, then it isn't clipping any
|
||||
// non-moving content (see ApplyAbsPosClipping), so we don't need
|
||||
// to do anything special, but we should not restrict aClipRect.
|
||||
if (!aBuilder->IsMovingFrame(clipItem->GetClippingFrame())) {
|
||||
clip.IntersectRect(clip, clipItem->GetClipRect());
|
||||
|
||||
// Invalidate the translation of the source area that was clipped out
|
||||
nsRegion clippedOutSource;
|
||||
clippedOutSource.Sub(aRect, clip);
|
||||
clippedOutSource.MoveBy(aDelta);
|
||||
aRegion->Or(*aRegion, clippedOutSource);
|
||||
|
||||
// Invalidate the destination area that is clipped out
|
||||
nsRegion clippedOutDestination;
|
||||
clippedOutDestination.Sub(aRect + aDelta, clip);
|
||||
aRegion->Or(*aRegion, clippedOutDestination);
|
||||
}
|
||||
AddItemsToRegion(aBuilder, sublist, aRect, clip, aDelta, aRegion);
|
||||
} else {
|
||||
// opacity, or a generic sublist
|
||||
@ -1075,7 +1092,7 @@ nsLayoutUtils::ComputeRepaintRegionForCopy(nsIFrame* aRootFrame,
|
||||
// to clip non-moving items --- this is enforced by the code that sets
|
||||
// up nsDisplayClip items, in particular see ApplyAbsPosClipping.
|
||||
// XXX but currently a non-moving clip item can incorrectly clip
|
||||
// moving moving items! See bug 428156.
|
||||
// moving items! See bug 428156.
|
||||
nsRect rect;
|
||||
rect.UnionRect(aCopyRect, aCopyRect + aDelta);
|
||||
nsDisplayListBuilder builder(aRootFrame, PR_FALSE, PR_TRUE);
|
||||
|
@ -5101,7 +5101,7 @@ PresShell::ClipListToRange(nsDisplayListBuilder *aBuilder,
|
||||
// wrap the item in an nsDisplayClip so that it can be clipped to
|
||||
// the selection. If the allocation fails, fall through and delete
|
||||
// the item below.
|
||||
itemToInsert = new (aBuilder)nsDisplayClip(frame, i, textRect);
|
||||
itemToInsert = new (aBuilder)nsDisplayClip(frame, frame, i, textRect);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1034,13 +1034,13 @@ public:
|
||||
// We are not a stacking context root. There is no valid underlying
|
||||
// frame for the whole list. These items are all in-flow descendants so
|
||||
// we can safely just clip them.
|
||||
return new (aBuilder) nsDisplayClip(nsnull, aList, mRect);
|
||||
return new (aBuilder) nsDisplayClip(nsnull, mContainer, aList, mRect);
|
||||
}
|
||||
virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem) {
|
||||
nsIFrame* f = aItem->GetUnderlyingFrame();
|
||||
if (mClipAll || nsLayoutUtils::IsProperAncestorFrame(mContainer, f, nsnull))
|
||||
return new (aBuilder) nsDisplayClip(f, aItem, mRect);
|
||||
return new (aBuilder) nsDisplayClip(f, mContainer, aItem, mRect);
|
||||
return aItem;
|
||||
}
|
||||
protected:
|
||||
@ -1053,20 +1053,22 @@ protected:
|
||||
class nsAbsPosClipWrapper : public nsDisplayWrapper
|
||||
{
|
||||
public:
|
||||
nsAbsPosClipWrapper(const nsRect& aRect)
|
||||
: mRect(aRect) {}
|
||||
nsAbsPosClipWrapper(nsIFrame* aContainer, const nsRect& aRect)
|
||||
: mContainer(aContainer), mRect(aRect) {}
|
||||
virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame, nsDisplayList* aList) {
|
||||
// We are not a stacking context root. There is no valid underlying
|
||||
// frame for the whole list.
|
||||
return new (aBuilder) nsDisplayClip(nsnull, aList, mRect);
|
||||
return new (aBuilder) nsDisplayClip(nsnull, mContainer, aList, mRect);
|
||||
}
|
||||
virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem) {
|
||||
return new (aBuilder) nsDisplayClip(aItem->GetUnderlyingFrame(), aItem, mRect);
|
||||
return new (aBuilder) nsDisplayClip(aItem->GetUnderlyingFrame(),
|
||||
mContainer, aItem, mRect);
|
||||
}
|
||||
protected:
|
||||
nsRect mRect;
|
||||
nsIFrame* mContainer;
|
||||
nsRect mRect;
|
||||
};
|
||||
|
||||
nsresult
|
||||
@ -1087,7 +1089,7 @@ nsIFrame::Clip(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aToSet,
|
||||
const nsRect& aClipRect)
|
||||
{
|
||||
nsAbsPosClipWrapper wrapper(aClipRect);
|
||||
nsAbsPosClipWrapper wrapper(this, aClipRect);
|
||||
return wrapper.WrapLists(aBuilder, this, aFromSet, aToSet);
|
||||
}
|
||||
|
||||
@ -1236,7 +1238,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||
resultList.AppendToTop(set.PositionedDescendants());
|
||||
|
||||
if (applyAbsPosClipping) {
|
||||
nsAbsPosClipWrapper wrapper(absPosClip);
|
||||
nsAbsPosClipWrapper wrapper(this, absPosClip);
|
||||
nsDisplayItem* item = wrapper.WrapList(aBuilder, this, &resultList);
|
||||
if (!item)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
@ -1253,6 +1255,34 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||
return rv;
|
||||
}
|
||||
|
||||
class nsDisplaySummary : public nsDisplayItem
|
||||
{
|
||||
public:
|
||||
nsDisplaySummary(nsIFrame* aFrame) : nsDisplayItem(aFrame) {
|
||||
MOZ_COUNT_CTOR(nsDisplaySummary);
|
||||
}
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
virtual ~nsDisplaySummary() {
|
||||
MOZ_COUNT_DTOR(nsDisplaySummary);
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
|
||||
NS_DISPLAY_DECL_NAME("Summary")
|
||||
};
|
||||
|
||||
nsRect
|
||||
nsDisplaySummary::GetBounds(nsDisplayListBuilder* aBuilder) {
|
||||
return mFrame->GetOverflowRect() + aBuilder->ToReferenceFrame(mFrame);
|
||||
}
|
||||
|
||||
static void
|
||||
AddSummaryFrameToList(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame, nsDisplayList* aList)
|
||||
{
|
||||
aList->AppendNewToTop(new (aBuilder) nsDisplaySummary(aFrame));
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aChild,
|
||||
@ -1336,7 +1366,17 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||
// No position-varying content has been rendered in this prescontext.
|
||||
// Therefore there is no need to descend into analyzing the moving frame's
|
||||
// descendants looking for such content, because any bitblit will
|
||||
// not be copying position-varying graphics.
|
||||
// not be copying position-varying graphics. However, to keep things
|
||||
// sane we still need display items representing the frame subtree.
|
||||
// We need to add these summaries to every list that the child could
|
||||
// contribute to. This avoids display list optimizations optimizing
|
||||
// away entire lists because they appear to be empty.
|
||||
AddSummaryFrameToList(aBuilder, aChild, aLists.BlockBorderBackgrounds());
|
||||
AddSummaryFrameToList(aBuilder, aChild, aLists.BorderBackground());
|
||||
AddSummaryFrameToList(aBuilder, aChild, aLists.Content());
|
||||
AddSummaryFrameToList(aBuilder, aChild, aLists.Floats());
|
||||
AddSummaryFrameToList(aBuilder, aChild, aLists.PositionedDescendants());
|
||||
AddSummaryFrameToList(aBuilder, aChild, aLists.Outlines());
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
@ -1427,7 +1467,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (isPositioned && applyAbsPosClipping) {
|
||||
nsAbsPosClipWrapper wrapper(clipRect);
|
||||
nsAbsPosClipWrapper wrapper(aChild, clipRect);
|
||||
rv = wrapper.WrapListsInPlace(aBuilder, aChild, pseudoStack);
|
||||
}
|
||||
}
|
||||
|
@ -352,7 +352,7 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
rv = f->BuildDisplayListForStackingContext(aBuilder, dirty, &childItems);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = aLists.Content()->AppendNewToTop(
|
||||
new (aBuilder) nsDisplayClip(nsnull, &childItems,
|
||||
new (aBuilder) nsDisplayClip(nsnull, this, &childItems,
|
||||
nsRect(aBuilder->ToReferenceFrame(f), f->GetSize())));
|
||||
// delete childItems in case of OOM
|
||||
childItems.DeleteAll();
|
||||
|
Loading…
Reference in New Issue
Block a user