зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
2d66061d8f
Коммит
8f12c70442
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче