Bug 1558937 - Don't allow duplicate items for printing. r=miko

Differential Revision: https://phabricator.services.mozilla.com/D34775

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Matt Woodrow 2019-06-24 08:00:41 +00:00
Родитель 2d66061d8f
Коммит 8f12c70442
6 изменённых файлов: 68 добавлений и 12 удалений

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

@ -405,8 +405,8 @@ static void BuildDisplayListForExtraPage(nsDisplayListBuilder* aBuilder,
nsPageFrame* aPage,
nsIFrame* aExtraPage,
nsDisplayList* aList) {
// The only content in aExtraPage we care about is out-of-flow content whose
// placeholders have occurred in aPage. If
// The only content in aExtraPage we care about is out-of-flow content from
// aPage, whose placeholders have occurred in aExtraPage. If
// NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO is not set, then aExtraPage has
// no such content.
if (!aExtraPage->HasAnyStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) {
@ -520,13 +520,27 @@ void nsPageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// these extra pages are pruned so that only display items for the
// page we currently care about (which we would have reached by
// following placeholders to their out-of-flows) end up on the list.
nsIFrame* page = child;
while ((page = GetNextPage(page)) != nullptr) {
nsRect childVisible = visibleRect + child->GetOffsetTo(page);
//
// Stacking context frames that wrap content on their normal page,
// as well as OOF content for this page will have their container
// items duplicated. We tell the builder to include our page number
// in the unique key for any extra page items so that they can be
// differentiated from the ones created on the normal page.
NS_ASSERTION(mPageNum <= 255, "Too many pages to handle OOFs");
if (mPageNum <= 255) {
uint8_t oldPageNum = aBuilder->GetBuildingExtraPagesForPageNum();
aBuilder->SetBuildingExtraPagesForPageNum(mPageNum);
nsDisplayListBuilder::AutoBuildingDisplayList buildingForChild(
aBuilder, page, childVisible, childVisible);
BuildDisplayListForExtraPage(aBuilder, this, page, &content);
nsIFrame* page = child;
while ((page = GetNextPage(page)) != nullptr) {
nsRect childVisible = visibleRect + child->GetOffsetTo(page);
nsDisplayListBuilder::AutoBuildingDisplayList buildingForChild(
aBuilder, page, childVisible, childVisible);
BuildDisplayListForExtraPage(aBuilder, this, page, &content);
}
aBuilder->SetBuildingExtraPagesForPageNum(oldPageNum);
}
// Invoke AutoBuildingDisplayList to ensure that the correct visibleRect

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

@ -1221,6 +1221,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mRootAGR(AnimatedGeometryRoot::CreateAGRForFrame(
aReferenceFrame, nullptr, true, aRetainingDisplayList)),
mCurrentAGR(mRootAGR),
mBuildingExtraPagesForPageNum(0),
mUsedAGRBudget(0),
mDirtyRect(-1, -1, -1, -1),
mGlassDisplayItem(nullptr),

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

@ -1699,6 +1699,13 @@ class nsDisplayListBuilder {
mBuildingInvisibleItems = aBuildingInvisibleItems;
}
void SetBuildingExtraPagesForPageNum(uint8_t aPageNum) {
mBuildingExtraPagesForPageNum = aPageNum;
}
uint8_t GetBuildingExtraPagesForPageNum() const {
return mBuildingExtraPagesForPageNum;
}
/**
* This is a convenience function to ease the transition until AGRs and ASRs
* are unified.
@ -1889,6 +1896,8 @@ class nsDisplayListBuilder {
nsDataHashtable<nsPtrHashKey<nsIFrame>, FrameWillChangeBudget>
mWillChangeBudgetSet;
uint8_t mBuildingExtraPagesForPageNum;
// Area of animated geometry root budget already allocated
uint32_t mUsedAGRBudget;
// Set of frames already counted in budget
@ -2065,6 +2074,7 @@ MOZ_ALWAYS_INLINE T* MakeDisplayItem(nsDisplayListBuilder* aBuilder, F* aFrame,
}
item->SetPerFrameKey(item->CalculatePerFrameKey());
item->SetExtraPageForPageNum(aBuilder->GetBuildingExtraPagesForPageNum());
nsPaintedDisplayItem* paintedItem = item->AsPaintedDisplayItem();
if (paintedItem) {
@ -2077,8 +2087,7 @@ MOZ_ALWAYS_INLINE T* MakeDisplayItem(nsDisplayListBuilder* aBuilder, F* aFrame,
}
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
if (aBuilder->IsRetainingDisplayList() && !aBuilder->IsInPageSequence() &&
aBuilder->IsBuilding()) {
if (aBuilder->IsRetainingDisplayList() && aBuilder->IsBuilding()) {
AssertUniqueItem(item);
}
@ -2220,11 +2229,12 @@ class nsDisplayItemBase : public nsDisplayItemLink {
* uniquely identifies this display item in the display item tree.
*/
uint32_t GetPerFrameKey() const {
// The top 8 bits are currently unused.
// The top 8 bits are the page index
// The middle 16 bits of the per frame key uniquely identify the display
// item when there are more than one item of the same type for a frame.
// The low 8 bits are the display item type.
return (static_cast<uint32_t>(mKey) << TYPE_BITS) |
return (static_cast<uint32_t>(mExtraPageForPageNum) << (TYPE_BITS + (sizeof(mKey) * 8))) |
(static_cast<uint32_t>(mKey) << TYPE_BITS) |
static_cast<uint32_t>(mType);
}
@ -2331,6 +2341,7 @@ class nsDisplayItemBase : public nsDisplayItemLink {
: mFrame(aOther.mFrame),
mItemFlags(aOther.mItemFlags),
mType(aOther.mType),
mExtraPageForPageNum(aOther.mExtraPageForPageNum),
mKey(aOther.mKey) {
MOZ_COUNT_CTOR(nsDisplayItemBase);
}
@ -2345,6 +2356,15 @@ class nsDisplayItemBase : public nsDisplayItemLink {
void SetType(const DisplayItemType aType) { mType = aType; }
void SetPerFrameKey(const uint16_t aKey) { mKey = aKey; }
// Display list building for printing can build duplicate
// container display items when they contain a mixture of
// OOF and normal content that is spread across multiple
// pages. We include the page number for the duplicates
// to make our GetPerFrameKey unique.
void SetExtraPageForPageNum(const uint8_t aPageNum) {
mExtraPageForPageNum = aPageNum;
}
void SetDeletedFrame();
nsIFrame* mFrame; // 8
@ -2363,6 +2383,7 @@ class nsDisplayItemBase : public nsDisplayItemLink {
mozilla::EnumSet<ItemBaseFlag, uint8_t> mItemFlags; // 1
DisplayItemType mType; // 1
uint8_t mExtraPageForPageNum = 0; // 1
uint16_t mKey; // 2
OldListIndex mOldListIndex; // 4
uintptr_t mOldList = 0; // 8

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

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html class="reftest-paged">
<body>
<div style="height:400px;"></div>
<div style="height:1000px">
<div style="width:100px; height:100px; background:black;"></div>
</div>
</body>
</html>

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

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html class="reftest-paged">
<body>
<div style="height:400px;"></div>
<div style="height:1000px; clip-path:border-box">
<div style="position:absolute; top:0; left:0; width:100px; height:100px; background:black;"></div>
<div style="width:100px; height:100px; background:black;"></div>
</div>
</body>
</html>

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

@ -2109,3 +2109,4 @@ fuzzy-if(!webrender,0-6,0-34) fails-if(webrender) fuzzy-if(geckoview,9-9,44-44)
skip-if(!asyncPan) fuzzy-if(geckoview,1-1,165-165) == 1544895.html 1544895-ref.html
== 1548809.html 1548809-ref.html
!= 1552789-1.html 1552789-ref-1.html
== 1558937-1.html 1558937-1-ref.html