зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1714584 - Part 1: Decouple nsDisplayList internal list from nsDisplayItems r=mstange
Differential Revision: https://phabricator.services.mozilla.com/D138152
This commit is contained in:
Родитель
5e97d6f437
Коммит
ddec6eef59
|
@ -558,7 +558,8 @@ struct DIGroup {
|
|||
nsDisplayListBuilder* aDisplayListBuilder,
|
||||
wr::DisplayListBuilder& aBuilder,
|
||||
wr::IpcResourceUpdateQueue& aResources, Grouper* aGrouper,
|
||||
nsDisplayItem* aStartItem, nsDisplayItem* aEndItem) {
|
||||
nsDisplayList::iterator aStartItem,
|
||||
nsDisplayList::iterator aEndItem) {
|
||||
GP("\n\n");
|
||||
GP("Begin EndGroup\n");
|
||||
|
||||
|
@ -654,6 +655,7 @@ struct DIGroup {
|
|||
|
||||
RenderRootStateManager* rootManager =
|
||||
aWrManager->GetRenderRootStateManager();
|
||||
|
||||
bool empty = aStartItem == aEndItem;
|
||||
if (empty) {
|
||||
ClearImageKey(rootManager, true);
|
||||
|
@ -663,8 +665,8 @@ struct DIGroup {
|
|||
// Reset mHitInfo, it will get updated inside PaintItemRange
|
||||
mHitInfo = CompositorHitTestInvisibleToHit;
|
||||
|
||||
PaintItemRange(aGrouper, nsDisplayList::Range(aStartItem, aEndItem),
|
||||
context, recorder, rootManager, aResources);
|
||||
PaintItemRange(aGrouper, aStartItem, aEndItem, context, recorder,
|
||||
rootManager, aResources);
|
||||
|
||||
// XXX: set this correctly perhaps using
|
||||
// aItem->GetOpaqueRegion(aDisplayListBuilder, &snapped).
|
||||
|
@ -769,14 +771,14 @@ struct DIGroup {
|
|||
SideBits::eNone);
|
||||
}
|
||||
|
||||
void PaintItemRange(Grouper* aGrouper, nsDisplayList::Iterator aIter,
|
||||
gfxContext* aContext,
|
||||
void PaintItemRange(Grouper* aGrouper, nsDisplayList::iterator aStartItem,
|
||||
nsDisplayList::iterator aEndItem, gfxContext* aContext,
|
||||
WebRenderDrawEventRecorder* aRecorder,
|
||||
RenderRootStateManager* aRootManager,
|
||||
wr::IpcResourceUpdateQueue& aResources) {
|
||||
LayerIntSize size = mVisibleRect.Size();
|
||||
while (aIter.HasNext()) {
|
||||
nsDisplayItem* item = aIter.GetNext();
|
||||
for (auto it = aStartItem; it != aEndItem; ++it) {
|
||||
nsDisplayItem* item = *it;
|
||||
MOZ_ASSERT(item);
|
||||
|
||||
BlobItemData* data = GetBlobItemData(item);
|
||||
|
@ -949,7 +951,7 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem,
|
|||
aContext->GetDrawTarget()->FlushItem(aItemBounds);
|
||||
} else {
|
||||
aContext->Multiply(ThebesMatrix(trans2d));
|
||||
aGroup->PaintItemRange(this, nsDisplayList::Iterator(aChildren),
|
||||
aGroup->PaintItemRange(this, aChildren->begin(), aChildren->end(),
|
||||
aContext, aRecorder, aRootManager, aResources);
|
||||
}
|
||||
|
||||
|
@ -972,8 +974,8 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem,
|
|||
GP("beginGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
|
||||
aItem->GetPerFrameKey());
|
||||
aContext->GetDrawTarget()->FlushItem(aItemBounds);
|
||||
aGroup->PaintItemRange(this, nsDisplayList::Iterator(aChildren), aContext,
|
||||
aRecorder, aRootManager, aResources);
|
||||
aGroup->PaintItemRange(this, aChildren->begin(), aChildren->end(),
|
||||
aContext, aRecorder, aRootManager, aResources);
|
||||
aContext->GetDrawTarget()->PopLayer();
|
||||
GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
|
||||
aItem->GetPerFrameKey());
|
||||
|
@ -989,8 +991,8 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem,
|
|||
GP("beginGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
|
||||
aItem->GetPerFrameKey());
|
||||
aContext->GetDrawTarget()->FlushItem(aItemBounds);
|
||||
aGroup->PaintItemRange(this, nsDisplayList::Iterator(aChildren), aContext,
|
||||
aRecorder, aRootManager, aResources);
|
||||
aGroup->PaintItemRange(this, aChildren->begin(), aChildren->end(),
|
||||
aContext, aRecorder, aRootManager, aResources);
|
||||
aContext->GetDrawTarget()->PopLayer();
|
||||
GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
|
||||
aItem->GetPerFrameKey());
|
||||
|
@ -1003,8 +1005,8 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem,
|
|||
GP("beginGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
|
||||
aItem->GetPerFrameKey());
|
||||
aContext->GetDrawTarget()->FlushItem(aItemBounds);
|
||||
aGroup->PaintItemRange(this, nsDisplayList::Iterator(aChildren), aContext,
|
||||
aRecorder, aRootManager, aResources);
|
||||
aGroup->PaintItemRange(this, aChildren->begin(), aChildren->end(),
|
||||
aContext, aRecorder, aRootManager, aResources);
|
||||
aContext->GetDrawTarget()->PopLayer();
|
||||
GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
|
||||
aItem->GetPerFrameKey());
|
||||
|
@ -1023,7 +1025,7 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem,
|
|||
GP("beginGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
|
||||
aItem->GetPerFrameKey());
|
||||
aContext->GetDrawTarget()->FlushItem(aItemBounds);
|
||||
aGroup->PaintItemRange(this, nsDisplayList::Iterator(aChildren),
|
||||
aGroup->PaintItemRange(this, aChildren->begin(), aChildren->end(),
|
||||
aContext, aRecorder, aRootManager,
|
||||
aResources);
|
||||
GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
|
||||
|
@ -1061,8 +1063,8 @@ void Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem,
|
|||
}
|
||||
|
||||
default:
|
||||
aGroup->PaintItemRange(this, nsDisplayList::Iterator(aChildren), aContext,
|
||||
aRecorder, aRootManager, aResources);
|
||||
aGroup->PaintItemRange(this, aChildren->begin(), aChildren->end(),
|
||||
aContext, aRecorder, aRootManager, aResources);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1186,15 +1188,18 @@ void Grouper::ConstructGroups(nsDisplayListBuilder* aDisplayListBuilder,
|
|||
RenderRootStateManager* manager =
|
||||
aCommandBuilder->mManager->GetRenderRootStateManager();
|
||||
|
||||
nsDisplayItem* startOfCurrentGroup = nullptr;
|
||||
nsDisplayList::iterator startOfCurrentGroup = aList->end();
|
||||
DIGroup* currentGroup = aGroup;
|
||||
|
||||
// We need to track whether we have active siblings for mixed blend mode.
|
||||
bool encounteredActiveItem = false;
|
||||
|
||||
for (nsDisplayItem* item : *aList) {
|
||||
if (!startOfCurrentGroup) {
|
||||
startOfCurrentGroup = item;
|
||||
for (auto it = aList->begin(); it != aList->end(); ++it) {
|
||||
nsDisplayItem* item = *it;
|
||||
MOZ_ASSERT(item);
|
||||
|
||||
if (startOfCurrentGroup == aList->end()) {
|
||||
startOfCurrentGroup = it;
|
||||
}
|
||||
|
||||
if (IsItemProbablyActive(item, aBuilder, aResources, aSc, manager,
|
||||
|
@ -1250,7 +1255,7 @@ void Grouper::ConstructGroups(nsDisplayListBuilder* aDisplayListBuilder,
|
|||
|
||||
currentGroup->EndGroup(aCommandBuilder->mManager, aDisplayListBuilder,
|
||||
aBuilder, aResources, this, startOfCurrentGroup,
|
||||
item);
|
||||
it);
|
||||
|
||||
{
|
||||
auto spaceAndClipChain =
|
||||
|
@ -1270,7 +1275,7 @@ void Grouper::ConstructGroups(nsDisplayListBuilder* aDisplayListBuilder,
|
|||
sIndent--;
|
||||
}
|
||||
|
||||
startOfCurrentGroup = nullptr;
|
||||
startOfCurrentGroup = aList->end();
|
||||
currentGroup = &groupData->mFollowingGroup;
|
||||
} else { // inactive item
|
||||
ConstructItemInsideInactive(aCommandBuilder, aBuilder, aResources,
|
||||
|
@ -1280,7 +1285,7 @@ void Grouper::ConstructGroups(nsDisplayListBuilder* aDisplayListBuilder,
|
|||
|
||||
currentGroup->EndGroup(aCommandBuilder->mManager, aDisplayListBuilder,
|
||||
aBuilder, aResources, this, startOfCurrentGroup,
|
||||
nullptr);
|
||||
aList->end());
|
||||
}
|
||||
|
||||
// This does a pass over the display lists and will join the display items
|
||||
|
|
|
@ -234,7 +234,8 @@ struct RangePaintInfo {
|
|||
|
||||
RangePaintInfo(nsRange* aRange, nsIFrame* aFrame)
|
||||
: mRange(aRange),
|
||||
mBuilder(aFrame, nsDisplayListBuilderMode::Painting, false) {
|
||||
mBuilder(aFrame, nsDisplayListBuilderMode::Painting, false),
|
||||
mList(&mBuilder) {
|
||||
MOZ_COUNT_CTOR(RangePaintInfo);
|
||||
mBuilder.BeginFrame();
|
||||
}
|
||||
|
@ -4909,7 +4910,7 @@ UniquePtr<RangePaintInfo> PresShell::CreateRangePaintInfo(
|
|||
ViewID zoomedId =
|
||||
nsLayoutUtils::FindOrCreateIDFor(rootScrollFrame->GetContent());
|
||||
|
||||
nsDisplayList wrapped;
|
||||
nsDisplayList wrapped(&info->mBuilder);
|
||||
wrapped.AppendNewToTop<nsDisplayAsyncZoom>(&info->mBuilder, rootScrollFrame,
|
||||
&info->mList, nullptr, zoomedId);
|
||||
info->mList.AppendToTop(&wrapped);
|
||||
|
@ -5215,8 +5216,13 @@ already_AddRefed<SourceSurface> PresShell::RenderSelection(
|
|||
aScreenRect, aFlags);
|
||||
}
|
||||
|
||||
void AddDisplayItemToBottom(nsDisplayList* aList, nsDisplayItem* aItem) {
|
||||
nsDisplayList list;
|
||||
void AddDisplayItemToBottom(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayList* aList, nsDisplayItem* aItem) {
|
||||
if (!aItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsDisplayList list(aBuilder);
|
||||
list.AppendToTop(aItem);
|
||||
list.AppendToTop(aList);
|
||||
aList->AppendToTop(&list);
|
||||
|
@ -5228,7 +5234,7 @@ void PresShell::AddPrintPreviewBackgroundItem(nsDisplayListBuilder* aBuilder,
|
|||
const nsRect& aBounds) {
|
||||
nsDisplayItem* item = MakeDisplayItem<nsDisplaySolidColor>(
|
||||
aBuilder, aFrame, aBounds, NS_RGB(115, 115, 115));
|
||||
AddDisplayItemToBottom(aList, item);
|
||||
AddDisplayItemToBottom(aBuilder, aList, item);
|
||||
}
|
||||
|
||||
static bool AddCanvasBackgroundColor(const nsDisplayList* aList,
|
||||
|
@ -5308,7 +5314,7 @@ void PresShell::AddCanvasBackgroundColorItem(
|
|||
if (!addedScrollingBackgroundColor || forceUnscrolledItem) {
|
||||
nsDisplayItem* item = MakeDisplayItem<nsDisplaySolidColor>(
|
||||
aBuilder, aFrame, aBounds, bgcolor);
|
||||
AddDisplayItemToBottom(aList, item);
|
||||
AddDisplayItemToBottom(aBuilder, aList, item);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2521,7 +2521,7 @@ bool nsLayoutUtils::GetLayerTransformForFrame(nsIFrame* aFrame,
|
|||
nsDisplayListBuilderMode::TransformComputation,
|
||||
false /*don't build caret*/);
|
||||
builder.BeginFrame();
|
||||
nsDisplayList list;
|
||||
nsDisplayList list(&builder);
|
||||
nsDisplayTransform* item =
|
||||
MakeDisplayItem<nsDisplayTransform>(&builder, aFrame, &list, nsRect());
|
||||
MOZ_ASSERT(item);
|
||||
|
@ -2716,7 +2716,7 @@ nsresult nsLayoutUtils::GetFramesForArea(RelativeTo aRelativeTo,
|
|||
nsDisplayListBuilder builder(frame, nsDisplayListBuilderMode::EventDelivery,
|
||||
false);
|
||||
builder.BeginFrame();
|
||||
nsDisplayList list;
|
||||
nsDisplayList list(&builder);
|
||||
|
||||
if (aOptions.mBits.contains(FrameForPointOption::IgnorePaintSuppression)) {
|
||||
builder.IgnorePaintSuppression();
|
||||
|
@ -3058,7 +3058,7 @@ struct TemporaryDisplayListBuilder {
|
|||
TemporaryDisplayListBuilder(nsIFrame* aFrame,
|
||||
nsDisplayListBuilderMode aBuilderMode,
|
||||
const bool aBuildCaret)
|
||||
: mBuilder(aFrame, aBuilderMode, aBuildCaret) {}
|
||||
: mBuilder(aFrame, aBuilderMode, aBuildCaret), mList(&mBuilder) {}
|
||||
|
||||
~TemporaryDisplayListBuilder() { mList.DeleteAll(&mBuilder); }
|
||||
|
||||
|
@ -3354,7 +3354,6 @@ void nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
|
|||
}
|
||||
|
||||
list->DeleteAll(builder);
|
||||
list->RestoreState();
|
||||
|
||||
builder->ClearRetainedWindowRegions();
|
||||
builder->ClearWillChangeBudgets();
|
||||
|
|
|
@ -73,7 +73,7 @@ bool nsHTMLButtonControlFrame::ShouldClipPaintingToBorderBox() {
|
|||
|
||||
void nsHTMLButtonControlFrame::BuildDisplayList(
|
||||
nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists) {
|
||||
nsDisplayList onTop;
|
||||
nsDisplayList onTop(aBuilder);
|
||||
if (IsVisibleForPainting()) {
|
||||
// Clip the button itself to its border area for event hit testing.
|
||||
Maybe<DisplayListClipState::AutoSaveRestore> eventClipState;
|
||||
|
|
|
@ -285,6 +285,7 @@ TextOverflow::TextOverflow(nsDisplayListBuilder* aBuilder,
|
|||
mBuilder(aBuilder),
|
||||
mBlock(aBlockFrame),
|
||||
mScrollableFrame(nsLayoutUtils::GetScrollableFrameFor(aBlockFrame)),
|
||||
mMarkerList(aBuilder),
|
||||
mBlockSize(aBlockFrame->GetSize()),
|
||||
mBlockWM(aBlockFrame->GetWritingMode()),
|
||||
mAdjustForPixelSnapping(false) {
|
||||
|
|
|
@ -124,7 +124,7 @@ static void BuildDisplayListForTopLayerFrame(nsDisplayListBuilder* aBuilder,
|
|||
nsDisplayListBuilder::AutoBuildingDisplayList buildingForChild(
|
||||
aBuilder, aFrame, visible, dirty);
|
||||
|
||||
nsDisplayList list;
|
||||
nsDisplayList list(aBuilder);
|
||||
aFrame->BuildDisplayListForStackingContext(aBuilder, &list);
|
||||
aList->AppendToTop(&list);
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ static bool BackdropListIsOpaque(ViewportFrame* aFrame,
|
|||
// The common case for ::backdrop elements on the top layer is a single
|
||||
// fixed position container, holding an opaque background color covering
|
||||
// the whole viewport.
|
||||
if (aList->Count() != 1 ||
|
||||
if (aList->Length() != 1 ||
|
||||
aList->GetTop()->GetType() != DisplayItemType::TYPE_FIXED_POSITION) {
|
||||
return false;
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ static bool BackdropListIsOpaque(ViewportFrame* aFrame,
|
|||
|
||||
nsDisplayWrapList* ViewportFrame::BuildDisplayListForTopLayer(
|
||||
nsDisplayListBuilder* aBuilder, bool* aIsOpaque) {
|
||||
nsDisplayList topLayerList;
|
||||
nsDisplayList topLayerList(aBuilder);
|
||||
|
||||
nsTArray<dom::Element*> topLayer = PresContext()->Document()->GetTopLayer();
|
||||
for (dom::Element* elem : topLayer) {
|
||||
|
|
|
@ -502,7 +502,7 @@ void nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
return false;
|
||||
}();
|
||||
|
||||
nsDisplayList layerItems;
|
||||
nsDisplayList layerItems(aBuilder);
|
||||
|
||||
// Create separate items for each background layer.
|
||||
const nsStyleImageLayers& layers = bg->StyleBackground()->mImage;
|
||||
|
@ -518,7 +518,7 @@ void nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
GetRectRelativeToSelf() + aBuilder->ToReferenceFrame(this);
|
||||
|
||||
const ActiveScrolledRoot* thisItemASR = asr;
|
||||
nsDisplayList thisItemList;
|
||||
nsDisplayList thisItemList(aBuilder);
|
||||
nsDisplayBackgroundImage::InitData bgData =
|
||||
nsDisplayBackgroundImage::GetInitData(aBuilder, this, i, bgRect, bg);
|
||||
|
||||
|
|
|
@ -4132,7 +4132,7 @@ void ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
// Effectively we are double clipping to the viewport, at potentially
|
||||
// different async scales.
|
||||
|
||||
nsDisplayList resultList;
|
||||
nsDisplayList resultList(aBuilder);
|
||||
set.SerializeWithCorrectZOrder(&resultList, mOuter->GetContent());
|
||||
|
||||
if (blendCapture.CaptureContainsBlendMode()) {
|
||||
|
|
|
@ -2924,7 +2924,7 @@ static bool ItemParticipatesIn3DContext(nsIFrame* aAncestor,
|
|||
const bool isContainer = type == DisplayItemType::TYPE_WRAP_LIST ||
|
||||
type == DisplayItemType::TYPE_CONTAINER;
|
||||
|
||||
if (isContainer && aItem->GetChildren()->Count() == 1) {
|
||||
if (isContainer && aItem->GetChildren()->Length() == 1) {
|
||||
// If the wraplist has only one child item, use the type of that item.
|
||||
type = aItem->GetChildren()->GetBottom()->GetType();
|
||||
}
|
||||
|
@ -3131,7 +3131,6 @@ bool TryToReuseStackingContextItem(nsDisplayListBuilder* aBuilder,
|
|||
}
|
||||
|
||||
nsDisplayItem* container = *res;
|
||||
MOZ_ASSERT(!container->GetAbove());
|
||||
MOZ_ASSERT(container->Frame() == aFrame);
|
||||
DL_LOGD("RDL - Found SC item %p (%s) (frame: %p)", container,
|
||||
container->Name(), container->Frame());
|
||||
|
@ -3341,7 +3340,7 @@ void nsIFrame::BuildDisplayListForStackingContext(
|
|||
bool usingSVGEffects = usingFilter || usingMask;
|
||||
|
||||
nsRect visibleRectOutsideSVGEffects = visibleRect;
|
||||
nsDisplayList hoistedScrollInfoItemsStorage;
|
||||
nsDisplayList hoistedScrollInfoItemsStorage(aBuilder);
|
||||
if (usingSVGEffects) {
|
||||
dirtyRect =
|
||||
SVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect);
|
||||
|
@ -3570,7 +3569,7 @@ void nsIFrame::BuildDisplayListForStackingContext(
|
|||
content = PresContext()->Document()->GetRootElement();
|
||||
}
|
||||
|
||||
nsDisplayList resultList;
|
||||
nsDisplayList resultList(aBuilder);
|
||||
set.SerializeWithCorrectZOrder(&resultList, content);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -3697,8 +3696,8 @@ void nsIFrame::BuildDisplayListForStackingContext(
|
|||
if (isTransformed && extend3DContext) {
|
||||
// Install dummy nsDisplayTransform as a leaf containing
|
||||
// descendants not participating this 3D rendering context.
|
||||
nsDisplayList nonparticipants;
|
||||
nsDisplayList participants;
|
||||
nsDisplayList nonparticipants(aBuilder);
|
||||
nsDisplayList participants(aBuilder);
|
||||
int index = 1;
|
||||
|
||||
nsDisplayItem* separator = nullptr;
|
||||
|
@ -3880,7 +3879,7 @@ void nsIFrame::BuildDisplayListForStackingContext(
|
|||
}
|
||||
|
||||
nsDisplayItem* container = resultList.GetBottom();
|
||||
if (resultList.Count() > 1 || container->Frame() != this) {
|
||||
if (resultList.Length() > 1 || container->Frame() != this) {
|
||||
container = MakeDisplayItem<nsDisplayContainer>(
|
||||
aBuilder, this, containerItemASR, &resultList);
|
||||
} else {
|
||||
|
@ -3918,7 +3917,7 @@ static nsDisplayItem* WrapInWrapList(nsDisplayListBuilder* aBuilder,
|
|||
// on which items we build, so we need to ensure that we don't transition
|
||||
// to/from a wrap list without invalidating correctly.
|
||||
bool needsWrapList =
|
||||
aList->Count() > 1 || item->Frame() != aFrame || item->GetChildren();
|
||||
aList->Length() > 1 || item->Frame() != aFrame || item->GetChildren();
|
||||
|
||||
// If we have an explicit container item (that can't change without an
|
||||
// invalidation) or we're doing a full build and don't need a wrap list, then
|
||||
|
@ -4340,8 +4339,8 @@ void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
|||
awayFromCommonPath = true;
|
||||
}
|
||||
|
||||
nsDisplayList list;
|
||||
nsDisplayList extraPositionedDescendants;
|
||||
nsDisplayList list(aBuilder);
|
||||
nsDisplayList extraPositionedDescendants(aBuilder);
|
||||
const ActiveScrolledRoot* wrapListASR;
|
||||
bool builtContainerItem = false;
|
||||
if (isStackingContext) {
|
||||
|
|
|
@ -301,7 +301,7 @@ static void BuildDisplayListForExtraPage(nsDisplayListBuilder* aBuilder,
|
|||
if (!aExtraPage->HasAnyStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) {
|
||||
return;
|
||||
}
|
||||
nsDisplayList list;
|
||||
nsDisplayList list(aBuilder);
|
||||
aExtraPage->BuildDisplayListForStackingContext(aBuilder, &list);
|
||||
PruneDisplayListForExtraPage(aBuilder, aPage, &list);
|
||||
aList->AppendToTop(&list);
|
||||
|
@ -332,7 +332,7 @@ void nsPageContentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
nsDisplayListCollection set(aBuilder);
|
||||
|
||||
nsDisplayList content;
|
||||
nsDisplayList content(aBuilder);
|
||||
{
|
||||
const nsRect clipRect(aBuilder->ToReferenceFrame(this), GetSize());
|
||||
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
|
||||
|
|
|
@ -585,7 +585,7 @@ nsSize nsPageFrame::ComputePageSize() const {
|
|||
|
||||
void nsPageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aLists) {
|
||||
nsDisplayList content;
|
||||
nsDisplayList content(aBuilder);
|
||||
nsDisplayListSet set(&content, &content, &content, &content, &content,
|
||||
&content);
|
||||
{
|
||||
|
|
|
@ -731,7 +731,7 @@ void nsPageSequenceFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
aBuilder->SetDisablePartialUpdates(true);
|
||||
DisplayBorderBackgroundOutline(aBuilder, aLists);
|
||||
|
||||
nsDisplayList content;
|
||||
nsDisplayList content(aBuilder);
|
||||
|
||||
{
|
||||
// Clear clip state while we construct the children of the
|
||||
|
|
|
@ -310,7 +310,7 @@ static void WrapBackgroundColorInOwnLayer(nsDisplayListBuilder* aBuilder,
|
|||
nsDisplayItem* item;
|
||||
while ((item = aList->RemoveBottom()) != nullptr) {
|
||||
if (item->GetType() == DisplayItemType::TYPE_BACKGROUND_COLOR) {
|
||||
nsDisplayList tmpList;
|
||||
nsDisplayList tmpList(aBuilder);
|
||||
tmpList.AppendToTop(item);
|
||||
item = MakeDisplayItemWithIndex<nsDisplayOwnLayer>(
|
||||
aBuilder, aFrame, /* aIndex = */ nsDisplayOwnLayer::OwnLayerForSubdoc,
|
||||
|
@ -438,7 +438,7 @@ void nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
needsOwnLayer = true;
|
||||
}
|
||||
|
||||
nsDisplayList childItems;
|
||||
nsDisplayList childItems(aBuilder);
|
||||
|
||||
{
|
||||
DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder);
|
||||
|
|
|
@ -193,7 +193,7 @@ bool RetainedDisplayListBuilder::PreProcessDisplayList(
|
|||
// a merge.
|
||||
const bool initializeOldItems = aList->mOldItems.IsEmpty();
|
||||
if (initializeOldItems) {
|
||||
aList->mOldItems.SetCapacity(aList->Count());
|
||||
aList->mOldItems.SetCapacity(aList->Length());
|
||||
} else {
|
||||
MOZ_RELEASE_ASSERT(!initializeDAG);
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ bool RetainedDisplayListBuilder::PreProcessDisplayList(
|
|||
MOZ_RELEASE_ASSERT(
|
||||
initializeDAG ||
|
||||
aList->mDAG.Length() ==
|
||||
(initializeOldItems ? aList->Count() : aList->mOldItems.Length()));
|
||||
(initializeOldItems ? aList->Length() : aList->mOldItems.Length()));
|
||||
|
||||
nsDisplayList out;
|
||||
|
||||
|
@ -349,7 +349,6 @@ bool RetainedDisplayListBuilder::PreProcessDisplayList(
|
|||
}
|
||||
|
||||
MOZ_RELEASE_ASSERT(aList->mOldItems.Length() == aList->mDAG.Length());
|
||||
aList->RestoreState();
|
||||
|
||||
if (aKeepLinked) {
|
||||
aList->AppendToTop(&out);
|
||||
|
@ -462,6 +461,7 @@ class MergeState {
|
|||
mOldDAG(
|
||||
std::move(*reinterpret_cast<DirectedAcyclicGraph<OldListUnits>*>(
|
||||
&aOldList.mDAG))),
|
||||
mMergedItems(aBuilder->Builder()),
|
||||
mOuterItem(aOuterItem),
|
||||
mResultIsModified(false) {
|
||||
mMergedDAG.EnsureCapacityFor(mOldDAG);
|
||||
|
@ -538,7 +538,7 @@ class MergeState {
|
|||
}
|
||||
|
||||
Maybe<const ActiveScrolledRoot*> containerASRForChildren;
|
||||
nsDisplayList empty;
|
||||
nsDisplayList empty(mBuilder->Builder());
|
||||
const bool modified = mBuilder->MergeDisplayLists(
|
||||
aNewItem ? aNewItem->GetChildren() : &empty, aOldItem->GetChildren(),
|
||||
aOutItem->GetChildren(), containerASRForChildren, aOutItem);
|
||||
|
@ -636,10 +636,10 @@ class MergeState {
|
|||
ProcessOldNode(OldListIndex(i), std::move(directPredecessors));
|
||||
}
|
||||
|
||||
RetainedDisplayList result;
|
||||
RetainedDisplayList result(mBuilder->Builder());
|
||||
result.AppendToTop(&mMergedItems);
|
||||
result.mDAG = std::move(mMergedDAG);
|
||||
MOZ_RELEASE_ASSERT(result.mDAG.Length() == result.Count());
|
||||
MOZ_RELEASE_ASSERT(result.mDAG.Length() == result.Length());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1563,14 +1563,14 @@ void CollectStackingContextItems(nsDisplayListBuilder* aBuilder,
|
|||
int aDepth = 0, bool aParentReused = false) {
|
||||
nsDisplayList out;
|
||||
|
||||
while (nsDisplayItem* item = aList->RemoveBottom()) {
|
||||
for (nsDisplayItem* item : *aList) {
|
||||
if (DL_LOG_TEST(LogLevel::Debug)) {
|
||||
DL_LOGD(
|
||||
"%*s Preprocessing item %p (%s) (frame: %p) "
|
||||
"(children: %d) (depth: %d) (parentReused: %d)",
|
||||
"(children: %zu) (depth: %d) (parentReused: %d)",
|
||||
aDepth, "", item, item->Name(),
|
||||
item->HasDeletedFrame() ? nullptr : item->Frame(),
|
||||
item->GetChildren() ? item->GetChildren()->Count() : 0, aDepth,
|
||||
item->GetChildren() ? item->GetChildren()->Length() : 0, aDepth,
|
||||
aParentReused);
|
||||
}
|
||||
|
||||
|
@ -1616,8 +1616,8 @@ void CollectStackingContextItems(nsDisplayListBuilder* aBuilder,
|
|||
}
|
||||
}
|
||||
|
||||
aList->Clear();
|
||||
aList->AppendToTop(&out);
|
||||
aList->RestoreState();
|
||||
}
|
||||
|
||||
} // namespace RDL
|
||||
|
@ -1664,7 +1664,7 @@ PartialUpdateResult RetainedDisplayListBuilder::AttemptPartialUpdate(
|
|||
}
|
||||
|
||||
nsRect modifiedDirty;
|
||||
nsDisplayList modifiedDL;
|
||||
nsDisplayList modifiedDL(&mBuilder);
|
||||
nsIFrame* modifiedAGR = nullptr;
|
||||
PartialUpdateResult result = PartialUpdateResult::NoChange;
|
||||
const bool simpleUpdate =
|
||||
|
|
|
@ -177,7 +177,7 @@ struct RetainedDisplayListMetrics {
|
|||
struct RetainedDisplayListBuilder {
|
||||
RetainedDisplayListBuilder(nsIFrame* aReferenceFrame,
|
||||
nsDisplayListBuilderMode aMode, bool aBuildCaret)
|
||||
: mBuilder(aReferenceFrame, aMode, aBuildCaret, true) {}
|
||||
: mBuilder(aReferenceFrame, aMode, aBuildCaret, true), mList(&mBuilder) {}
|
||||
~RetainedDisplayListBuilder() { mList.DeleteAll(&mBuilder); }
|
||||
|
||||
nsDisplayListBuilder* Builder() { return &mBuilder; }
|
||||
|
|
|
@ -353,11 +353,12 @@ nsDisplayWrapper* nsDisplayWrapList::CreateShallowCopy(
|
|||
}
|
||||
|
||||
nsDisplayWrapList* nsDisplayListBuilder::MergeItems(
|
||||
nsTArray<nsDisplayWrapList*>& aItems) {
|
||||
nsTArray<nsDisplayItem*>& aItems) {
|
||||
// For merging, we create a temporary item by cloning the last item of the
|
||||
// mergeable items list. This ensures that the temporary item will have the
|
||||
// correct frame and bounds.
|
||||
nsDisplayWrapList* last = aItems.PopLastElement();
|
||||
nsDisplayWrapList* last = aItems.PopLastElement()->AsDisplayWrapList();
|
||||
MOZ_ASSERT(last);
|
||||
nsDisplayWrapList* merged = last->Clone(this);
|
||||
MOZ_ASSERT(merged);
|
||||
AddTemporaryItem(merged);
|
||||
|
@ -365,11 +366,13 @@ nsDisplayWrapList* nsDisplayListBuilder::MergeItems(
|
|||
// Create nsDisplayWrappers that point to the internal display lists of the
|
||||
// items we are merging. These nsDisplayWrappers are added to the display list
|
||||
// of the temporary item.
|
||||
for (nsDisplayWrapList* item : Reversed(aItems)) {
|
||||
for (nsDisplayItem* item : aItems) {
|
||||
MOZ_ASSERT(item);
|
||||
MOZ_ASSERT(merged->CanMerge(item));
|
||||
merged->Merge(item);
|
||||
merged->GetChildren()->AppendToTop(item->CreateShallowCopy(this));
|
||||
MOZ_ASSERT(item->AsDisplayWrapList());
|
||||
merged->GetChildren()->AppendToTop(
|
||||
static_cast<nsDisplayWrapList*>(item)->CreateShallowCopy(this));
|
||||
}
|
||||
|
||||
merged->GetChildren()->AppendToTop(last->CreateShallowCopy(this));
|
||||
|
@ -2322,21 +2325,6 @@ void nsDisplayList::PaintRoot(nsDisplayListBuilder* aBuilder, gfxContext* aCtx,
|
|||
}
|
||||
}
|
||||
|
||||
nsDisplayItem* nsDisplayList::RemoveBottom() {
|
||||
nsDisplayItem* item = mSentinel.mAbove;
|
||||
if (!item) {
|
||||
return nullptr;
|
||||
}
|
||||
mSentinel.mAbove = item->mAbove;
|
||||
if (item == mTop) {
|
||||
// must have been the only item
|
||||
mTop = &mSentinel;
|
||||
}
|
||||
item->mAbove = nullptr;
|
||||
mLength--;
|
||||
return item;
|
||||
}
|
||||
|
||||
void nsDisplayList::DeleteAll(nsDisplayListBuilder* aBuilder) {
|
||||
nsDisplayItem* item;
|
||||
while ((item = RemoveBottom()) != nullptr) {
|
||||
|
@ -2696,7 +2684,8 @@ nsRect nsDisplayItem::GetClippedBounds(nsDisplayListBuilder* aBuilder) const {
|
|||
nsDisplayContainer::nsDisplayContainer(
|
||||
nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
const ActiveScrolledRoot* aActiveScrolledRoot, nsDisplayList* aList)
|
||||
: nsDisplayItem(aBuilder, aFrame, aActiveScrolledRoot) {
|
||||
: nsDisplayItem(aBuilder, aFrame, aActiveScrolledRoot),
|
||||
mChildren(aBuilder) {
|
||||
MOZ_COUNT_CTOR(nsDisplayContainer);
|
||||
mChildren.AppendToTop(aList);
|
||||
UpdateBounds(aBuilder);
|
||||
|
@ -3151,7 +3140,7 @@ AppendedBackgroundType nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
|
|||
// An auxiliary list is necessary in case we have background blending; if that
|
||||
// is the case, background items need to be wrapped by a blend container to
|
||||
// isolate blending to the background
|
||||
nsDisplayList bgItemList;
|
||||
nsDisplayList bgItemList(aBuilder);
|
||||
// Even if we don't actually have a background color to paint, we may still
|
||||
// need to create an item for hit testing and we still need to create an item
|
||||
// for background-color animations.
|
||||
|
@ -3260,7 +3249,7 @@ AppendedBackgroundType nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
|
|||
willPaintBorder);
|
||||
}
|
||||
|
||||
nsDisplayList thisItemList;
|
||||
nsDisplayList thisItemList(aBuilder);
|
||||
nsDisplayBackgroundImage::InitData bgData =
|
||||
nsDisplayBackgroundImage::GetInitData(aBuilder, aFrame, i, bgOriginRect,
|
||||
bgSC);
|
||||
|
@ -3388,23 +3377,6 @@ static bool RoundedRectContainsRect(const nsRect& aRoundedRect,
|
|||
return rgn.Contains(aContainedRect);
|
||||
}
|
||||
|
||||
static void CheckForBorderItem(nsDisplayItem* aItem, uint32_t& aFlags) {
|
||||
// TODO(miko): Iterating over the display list like this is suspicious.
|
||||
for (nsDisplayList::Iterator it(aItem); it.HasNext(); ++it) {
|
||||
nsDisplayItem* next = *it;
|
||||
|
||||
if (next->GetType() == DisplayItemType::TYPE_BACKGROUND) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (next->GetType() == DisplayItemType::TYPE_BORDER) {
|
||||
aFlags |= nsCSSRendering::PAINTBG_WILL_PAINT_BORDER;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool nsDisplayBackgroundImage::CanApplyOpacity(
|
||||
WebRenderLayerManager* aManager, nsDisplayListBuilder* aBuilder) const {
|
||||
// Bug 1752919: WebRender does not properly handle opacity flattening for
|
||||
|
@ -3440,7 +3412,6 @@ bool nsDisplayBackgroundImage::CreateWebRenderCommands(
|
|||
|
||||
uint32_t paintFlags = aDisplayListBuilder->GetBackgroundPaintFlags();
|
||||
bool dummy;
|
||||
CheckForBorderItem(this, paintFlags);
|
||||
nsCSSRendering::PaintBGParams params =
|
||||
nsCSSRendering::PaintBGParams::ForSingleLayer(
|
||||
*StyleFrame()->PresContext(), GetBounds(aDisplayListBuilder, &dummy),
|
||||
|
@ -4592,6 +4563,7 @@ nsDisplayWrapList::nsDisplayWrapList(
|
|||
nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayList* aList,
|
||||
const ActiveScrolledRoot* aActiveScrolledRoot, bool aClearClipChain)
|
||||
: nsPaintedDisplayItem(aBuilder, aFrame, aActiveScrolledRoot),
|
||||
mList(aBuilder),
|
||||
mFrameActiveScrolledRoot(aBuilder->CurrentActiveScrolledRoot()),
|
||||
mOverrideZIndex(0),
|
||||
mHasZIndexOverride(false),
|
||||
|
@ -4610,6 +4582,7 @@ nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
|
|||
nsIFrame* aFrame, nsDisplayItem* aItem)
|
||||
: nsPaintedDisplayItem(aBuilder, aFrame,
|
||||
aBuilder->CurrentActiveScrolledRoot()),
|
||||
mList(aBuilder),
|
||||
mOverrideZIndex(0),
|
||||
mHasZIndexOverride(false) {
|
||||
MOZ_COUNT_CTOR(nsDisplayWrapList);
|
||||
|
@ -4855,7 +4828,7 @@ static bool CollectItemsWithOpacity(WebRenderLayerManager* aManager,
|
|||
nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayList* aList,
|
||||
nsTArray<nsPaintedDisplayItem*>& aArray) {
|
||||
if (aList->Count() > kOpacityMaxListSize) {
|
||||
if (aList->Length() > kOpacityMaxListSize) {
|
||||
// Exit early, since |aList| will likely contain more than
|
||||
// |kOpacityMaxChildCount| items.
|
||||
return false;
|
||||
|
@ -4941,7 +4914,7 @@ bool nsDisplayOpacity::CanApplyToChildren(WebRenderLayerManager* aManager,
|
|||
* opacity. In this case the opacity item can be optimized away.
|
||||
*/
|
||||
bool nsDisplayOpacity::ApplyToMask() {
|
||||
if (mList.Count() != 1) {
|
||||
if (mList.Length() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -5454,7 +5427,7 @@ nsDisplayFixedPosition* nsDisplayFixedPosition::CreateForFixedBackground(
|
|||
nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsIFrame* aSecondaryFrame,
|
||||
nsDisplayBackgroundImage* aImage, const uint16_t aIndex,
|
||||
const ActiveScrolledRoot* aScrollTargetASR) {
|
||||
nsDisplayList temp;
|
||||
nsDisplayList temp(aBuilder);
|
||||
temp.AppendToTop(aImage);
|
||||
|
||||
if (aSecondaryFrame) {
|
||||
|
@ -6027,6 +6000,7 @@ nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
|
|||
nsIFrame* aFrame, nsDisplayList* aList,
|
||||
const nsRect& aChildrenBuildingRect)
|
||||
: nsPaintedDisplayItem(aBuilder, aFrame),
|
||||
mChildren(aBuilder),
|
||||
mTransform(Some(Matrix4x4())),
|
||||
mChildrenBuildingRect(aChildrenBuildingRect),
|
||||
mPrerenderDecision(PrerenderDecision::No),
|
||||
|
@ -6043,6 +6017,7 @@ nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
|
|||
const nsRect& aChildrenBuildingRect,
|
||||
PrerenderDecision aPrerenderDecision)
|
||||
: nsPaintedDisplayItem(aBuilder, aFrame),
|
||||
mChildren(aBuilder),
|
||||
mChildrenBuildingRect(aChildrenBuildingRect),
|
||||
mPrerenderDecision(aPrerenderDecision),
|
||||
mIsTransformSeparator(false),
|
||||
|
@ -6059,6 +6034,7 @@ nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
|
|||
const nsRect& aChildrenBuildingRect,
|
||||
decltype(WithTransformGetter))
|
||||
: nsPaintedDisplayItem(aBuilder, aFrame),
|
||||
mChildren(aBuilder),
|
||||
mChildrenBuildingRect(aChildrenBuildingRect),
|
||||
mPrerenderDecision(PrerenderDecision::No),
|
||||
mIsTransformSeparator(false),
|
||||
|
@ -6773,7 +6749,8 @@ void nsDisplayTransform::Collect3DTransformLeaves(
|
|||
}
|
||||
|
||||
FlattenedDisplayListIterator iter(aBuilder, &mChildren);
|
||||
while (nsDisplayItem* item = iter.GetNextItem()) {
|
||||
while (iter.HasNext()) {
|
||||
nsDisplayItem* item = iter.GetNextItem();
|
||||
if (item->GetType() == DisplayItemType::TYPE_PERSPECTIVE) {
|
||||
auto* perspective = static_cast<nsDisplayPerspective*>(item);
|
||||
if (!perspective->GetChildren()->GetTop()) {
|
||||
|
@ -7349,9 +7326,9 @@ void nsDisplayTransform::WriteDebugInfo(std::stringstream& aStream) {
|
|||
nsDisplayPerspective::nsDisplayPerspective(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame,
|
||||
nsDisplayList* aList)
|
||||
: nsPaintedDisplayItem(aBuilder, aFrame) {
|
||||
: nsPaintedDisplayItem(aBuilder, aFrame), mList(aBuilder) {
|
||||
mList.AppendToTop(aList);
|
||||
MOZ_ASSERT(mList.Count() == 1);
|
||||
MOZ_ASSERT(mList.Length() == 1);
|
||||
MOZ_ASSERT(mList.GetTop()->GetType() == DisplayItemType::TYPE_TRANSFORM);
|
||||
}
|
||||
|
||||
|
@ -7816,8 +7793,8 @@ static void ComputeMaskGeometry(PaintFramesParams& aParams) {
|
|||
auto cssToDevScale = frame->PresContext()->CSSToDevPixelScale();
|
||||
int32_t appUnitsPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
|
||||
|
||||
gfxPoint devPixelOffsetToUserSpace = nsLayoutUtils::PointToGfxPoint(
|
||||
offsetToUserSpace, appUnitsPerDevPixel);
|
||||
gfxPoint devPixelOffsetToUserSpace =
|
||||
nsLayoutUtils::PointToGfxPoint(offsetToUserSpace, appUnitsPerDevPixel);
|
||||
|
||||
gfxContextMatrixAutoSaveRestore matSR(&ctx);
|
||||
ctx.SetMatrixDouble(
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "gfxContext.h"
|
||||
#include "mozilla/ArenaAllocator.h"
|
||||
#include "mozilla/Array.h"
|
||||
#include "mozilla/ArrayIterator.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
@ -257,11 +258,17 @@ enum class nsDisplayListBuilderMode : uint8_t {
|
|||
GenerateGlyph,
|
||||
};
|
||||
|
||||
using ListArenaAllocator = ArenaAllocator<4096, 8>;
|
||||
|
||||
class nsDisplayItem;
|
||||
class nsPaintedDisplayItem;
|
||||
class nsDisplayList;
|
||||
class nsDisplayWrapList;
|
||||
class nsDisplayTableBackgroundSet;
|
||||
class nsDisplayTableItem;
|
||||
|
||||
class RetainedDisplayList;
|
||||
|
||||
/**
|
||||
* This manages a display list and is passed as a parameter to
|
||||
* nsIFrame::BuildDisplayList.
|
||||
|
@ -958,7 +965,7 @@ class nsDisplayListBuilder {
|
|||
* display item.
|
||||
* The display items in |aMergedItems| have to be mergeable with each other.
|
||||
*/
|
||||
nsDisplayWrapList* MergeItems(nsTArray<nsDisplayWrapList*>& aItems);
|
||||
nsDisplayWrapList* MergeItems(nsTArray<nsDisplayItem*>& aItems);
|
||||
|
||||
/**
|
||||
* A helper class used to temporarily set nsDisplayListBuilder properties for
|
||||
|
@ -1723,6 +1730,8 @@ class nsDisplayListBuilder {
|
|||
*/
|
||||
void ReuseDisplayItem(nsDisplayItem* aItem);
|
||||
|
||||
ListArenaAllocator& GetListAllocator() { return mListPool; }
|
||||
|
||||
private:
|
||||
bool MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame,
|
||||
const nsRect& aVisibleRect,
|
||||
|
@ -1921,12 +1930,9 @@ class nsDisplayListBuilder {
|
|||
|
||||
// Stores reusable items collected during display list preprocessing.
|
||||
nsTHashSet<nsDisplayItem*> mReuseableItems;
|
||||
};
|
||||
|
||||
class nsDisplayItem;
|
||||
class nsPaintedDisplayItem;
|
||||
class nsDisplayList;
|
||||
class RetainedDisplayList;
|
||||
ArenaAllocator<4096, 8> mListPool;
|
||||
};
|
||||
|
||||
// All types are defined in nsDisplayItemTypes.h
|
||||
#define NS_DISPLAY_DECL_NAME(n, e) \
|
||||
|
@ -2047,23 +2053,6 @@ MOZ_ALWAYS_INLINE T* MakeDisplayItem(nsDisplayListBuilder* aBuilder, F* aFrame,
|
|||
std::forward<Args>(aArgs)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* nsDisplayItems are put in singly-linked lists rooted in an nsDisplayList.
|
||||
* nsDisplayItemLink holds the link. The lists are linked from lowest to
|
||||
* highest in z-order.
|
||||
*/
|
||||
class nsDisplayItemLink {
|
||||
// This is never instantiated directly, so no need to count constructors and
|
||||
// destructors.
|
||||
protected:
|
||||
nsDisplayItemLink() : mAbove(nullptr) {}
|
||||
nsDisplayItemLink(const nsDisplayItemLink&) : mAbove(nullptr) {}
|
||||
~nsDisplayItemLink() { MOZ_RELEASE_ASSERT(!mAbove); }
|
||||
nsDisplayItem* mAbove;
|
||||
|
||||
friend class nsDisplayList;
|
||||
};
|
||||
|
||||
/*
|
||||
* nsDisplayItemBase is a base-class for all display items. It is mainly
|
||||
* responsible for handling the frame-display item 1:n relationship, as well as
|
||||
|
@ -2077,7 +2066,7 @@ class nsDisplayItemLink {
|
|||
* Display items belong to a list at all times (except temporarily as they
|
||||
* move from one list to another).
|
||||
*/
|
||||
class nsDisplayItem : public nsDisplayItemLink {
|
||||
class nsDisplayItem {
|
||||
public:
|
||||
using Layer = layers::Layer;
|
||||
using LayerManager = layers::LayerManager;
|
||||
|
@ -2106,6 +2095,12 @@ class nsDisplayItem : public nsDisplayItemLink {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given display item can be merged with this item.
|
||||
* @return true if the merging is possible, otherwise false.
|
||||
*/
|
||||
virtual bool CanMerge(const nsDisplayItem* aItem) const { return false; }
|
||||
|
||||
/**
|
||||
* Frees the memory allocated for this display item.
|
||||
* The given display list builder must have allocated this display item.
|
||||
|
@ -2706,8 +2701,6 @@ class nsDisplayItem : public nsDisplayItemLink {
|
|||
|
||||
virtual void WriteDebugInfo(std::stringstream& aStream) {}
|
||||
|
||||
nsDisplayItem* GetAbove() { return mAbove; }
|
||||
|
||||
/**
|
||||
* Returns the result of aBuilder->ToReferenceFrame(GetUnderlyingFrame())
|
||||
*/
|
||||
|
@ -2989,147 +2982,134 @@ class nsPaintedDisplayItem : public nsDisplayItem {
|
|||
Maybe<uint16_t> mCacheIndex;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct MOZ_HEAP_CLASS LinkedListNode {
|
||||
explicit LinkedListNode(T aValue) : mNext(nullptr), mValue(aValue) {}
|
||||
LinkedListNode* mNext;
|
||||
T mValue;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct LinkedListIterator {
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = T;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
using Node = LinkedListNode<T>;
|
||||
|
||||
explicit LinkedListIterator(Node* aNode = nullptr) : mNode(aNode) {}
|
||||
|
||||
LinkedListIterator<T>& operator++() {
|
||||
MOZ_ASSERT(mNode);
|
||||
mNode = mNode->mNext;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const LinkedListIterator<T>& aOther) const {
|
||||
return mNode == aOther.mNode;
|
||||
}
|
||||
|
||||
bool operator!=(const LinkedListIterator<T>& aOther) const {
|
||||
return mNode != aOther.mNode;
|
||||
}
|
||||
|
||||
const T operator*() const {
|
||||
MOZ_ASSERT(mNode);
|
||||
return mNode->mValue;
|
||||
}
|
||||
|
||||
T operator*() {
|
||||
MOZ_ASSERT(mNode);
|
||||
return mNode->mValue;
|
||||
}
|
||||
|
||||
Node* mNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Manages a singly-linked list of display list items.
|
||||
*
|
||||
* mSentinel is the sentinel list value, the first value in the null-terminated
|
||||
* linked list of items. mTop is the last item in the list (whose 'above'
|
||||
* pointer is null). This class has no virtual methods. So list objects are just
|
||||
* two pointers.
|
||||
*
|
||||
* Stepping upward through this list is very fast. Stepping downward is very
|
||||
* slow so we don't support it. The methods that need to step downward
|
||||
* (HitTest()) internally build a temporary array of all
|
||||
* the items while they do the downward traversal, so overall they're still
|
||||
* linear time. We have optimized for efficient AppendToTop() of both
|
||||
* items and lists, with minimal codesize.
|
||||
*
|
||||
* Internal linked list nodes are allocated using arena allocator.
|
||||
* */
|
||||
class nsDisplayList {
|
||||
public:
|
||||
class Iterator {
|
||||
public:
|
||||
constexpr Iterator() : mCurrent(nullptr), mEnd(nullptr) {}
|
||||
~Iterator() = default;
|
||||
Iterator(const Iterator& aOther) = default;
|
||||
Iterator& operator=(const Iterator& aOther) = default;
|
||||
using Node = LinkedListNode<nsDisplayItem*>;
|
||||
using iterator = LinkedListIterator<nsDisplayItem*>;
|
||||
using const_iterator = iterator;
|
||||
|
||||
explicit Iterator(const nsDisplayList* aList)
|
||||
: mCurrent(aList->GetBottom()), mEnd(nullptr) {}
|
||||
explicit Iterator(nsDisplayItem* aStart)
|
||||
: mCurrent(aStart), mEnd(nullptr) {}
|
||||
iterator begin() { return iterator(mBottom); }
|
||||
iterator end() { return iterator(nullptr); }
|
||||
const_iterator begin() const { return iterator(mBottom); }
|
||||
const_iterator end() const { return iterator(nullptr); }
|
||||
|
||||
Iterator& operator++() {
|
||||
mCurrent = Next();
|
||||
return *this;
|
||||
}
|
||||
explicit nsDisplayList(nsDisplayListBuilder* aBuilder)
|
||||
: mPool(aBuilder->GetListAllocator()) {}
|
||||
|
||||
nsDisplayItem* operator*() {
|
||||
MOZ_ASSERT(mCurrent);
|
||||
return mCurrent;
|
||||
}
|
||||
|
||||
bool operator==(const Iterator& aOther) const {
|
||||
return mCurrent == aOther.mCurrent;
|
||||
}
|
||||
|
||||
bool operator!=(const Iterator& aOther) const {
|
||||
return !operator==(aOther);
|
||||
}
|
||||
|
||||
bool HasNext() const { return mCurrent != nullptr; }
|
||||
|
||||
nsDisplayItem* GetNext() {
|
||||
MOZ_ASSERT(HasNext());
|
||||
auto* next = mCurrent;
|
||||
operator++();
|
||||
return next;
|
||||
}
|
||||
|
||||
protected:
|
||||
Iterator(nsDisplayItem* aStart, nsDisplayItem* aEnd)
|
||||
: mCurrent(aStart), mEnd(aEnd) {}
|
||||
|
||||
nsDisplayItem* Next() const {
|
||||
if (!mCurrent) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto* next = mCurrent->GetAbove();
|
||||
if (next == mEnd) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
private:
|
||||
nsDisplayItem* mCurrent;
|
||||
nsDisplayItem* mEnd;
|
||||
};
|
||||
|
||||
class Range final : public Iterator {
|
||||
public:
|
||||
Range(nsDisplayItem* aStart, nsDisplayItem* aEnd)
|
||||
: Iterator(aStart, aEnd) {}
|
||||
};
|
||||
|
||||
Iterator begin() const { return Iterator(this); }
|
||||
constexpr Iterator end() const { return Iterator(); }
|
||||
|
||||
/**
|
||||
* Create an empty list.
|
||||
*/
|
||||
nsDisplayList() : mLength(0), mForceTransparentSurface(false) {
|
||||
mTop = &mSentinel;
|
||||
mSentinel.mAbove = nullptr;
|
||||
}
|
||||
nsDisplayList() = delete;
|
||||
nsDisplayList(const nsDisplayList&) = delete;
|
||||
nsDisplayList& operator=(const nsDisplayList&) = delete;
|
||||
|
||||
virtual ~nsDisplayList() {
|
||||
MOZ_RELEASE_ASSERT(!mSentinel.mAbove, "Nonempty list left over?");
|
||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
if (!mAllowNonEmptyDestruction) {
|
||||
MOZ_RELEASE_ASSERT(IsEmpty(), "Nonempty list left over?");
|
||||
}
|
||||
#endif
|
||||
Clear();
|
||||
}
|
||||
|
||||
nsDisplayList(nsDisplayList&& aOther) {
|
||||
mForceTransparentSurface = aOther.mForceTransparentSurface;
|
||||
|
||||
if (aOther.mSentinel.mAbove) {
|
||||
AppendToTop(&aOther);
|
||||
} else {
|
||||
mTop = &mSentinel;
|
||||
mLength = 0;
|
||||
}
|
||||
nsDisplayList(nsDisplayList&& aOther)
|
||||
: mBottom(aOther.mBottom),
|
||||
mTop(aOther.mTop),
|
||||
mLength(aOther.mLength),
|
||||
mPool(aOther.mPool) {
|
||||
aOther.SetEmpty();
|
||||
}
|
||||
|
||||
nsDisplayList& operator=(nsDisplayList&& aOther) {
|
||||
MOZ_RELEASE_ASSERT(&mPool == &aOther.mPool);
|
||||
|
||||
if (this != &aOther) {
|
||||
if (aOther.mSentinel.mAbove) {
|
||||
nsDisplayList tmp;
|
||||
tmp.AppendToTop(&aOther);
|
||||
aOther.AppendToTop(this);
|
||||
AppendToTop(&tmp);
|
||||
} else {
|
||||
mTop = &mSentinel;
|
||||
mLength = 0;
|
||||
}
|
||||
mForceTransparentSurface = aOther.mForceTransparentSurface;
|
||||
MOZ_RELEASE_ASSERT(IsEmpty());
|
||||
mBottom = std::move(aOther.mBottom);
|
||||
mTop = std::move(aOther.mTop);
|
||||
mLength = std::move(aOther.mLength);
|
||||
aOther.SetEmpty();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
nsDisplayList(const nsDisplayList&) = delete;
|
||||
nsDisplayList& operator=(const nsDisplayList& aOther) = delete;
|
||||
|
||||
/**
|
||||
* Append an item to the top of the list. The item must not currently
|
||||
* be in a list and cannot be null.
|
||||
*/
|
||||
* Append an item to the top of the list.
|
||||
**/
|
||||
void AppendToTop(nsDisplayItem* aItem) {
|
||||
if (!aItem) {
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(!aItem->mAbove, "Already in a list!");
|
||||
mTop->mAbove = aItem;
|
||||
mTop = aItem;
|
||||
|
||||
auto* next = Allocate(aItem);
|
||||
MOZ_ASSERT(next);
|
||||
|
||||
if (IsEmpty()) {
|
||||
mBottom = next;
|
||||
mTop = next;
|
||||
} else {
|
||||
mTop->mNext = next;
|
||||
mTop = next;
|
||||
}
|
||||
|
||||
mLength++;
|
||||
|
||||
MOZ_ASSERT(mBottom && mTop);
|
||||
MOZ_ASSERT(mTop->mNext == nullptr);
|
||||
}
|
||||
|
||||
template <typename T, typename F, typename... Args>
|
||||
|
@ -3144,61 +3124,84 @@ class nsDisplayList {
|
|||
const uint16_t aIndex, Args&&... aArgs) {
|
||||
nsDisplayItem* item = MakeDisplayItemWithIndex<T>(
|
||||
aBuilder, aFrame, aIndex, std::forward<Args>(aArgs)...);
|
||||
|
||||
if (item) {
|
||||
AppendToTop(item);
|
||||
}
|
||||
AppendToTop(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all items from aList and appends them to the top of this list
|
||||
* Removes all items from aList and appends them to the top of this list.
|
||||
*/
|
||||
void AppendToTop(nsDisplayList* aList) {
|
||||
if (aList->mSentinel.mAbove) {
|
||||
mTop->mAbove = aList->mSentinel.mAbove;
|
||||
MOZ_ASSERT(aList != this);
|
||||
MOZ_RELEASE_ASSERT(&mPool == &aList->mPool);
|
||||
|
||||
if (aList->IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsEmpty()) {
|
||||
std::swap(mBottom, aList->mBottom);
|
||||
std::swap(mTop, aList->mTop);
|
||||
std::swap(mLength, aList->mLength);
|
||||
} else {
|
||||
MOZ_ASSERT(mTop && mTop->mNext == nullptr);
|
||||
mTop->mNext = aList->mBottom;
|
||||
mTop = aList->mTop;
|
||||
aList->mTop = &aList->mSentinel;
|
||||
aList->mSentinel.mAbove = nullptr;
|
||||
mLength += aList->mLength;
|
||||
aList->mLength = 0;
|
||||
|
||||
aList->SetEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an item from the bottom of the list and return it.
|
||||
* Clears the display list.
|
||||
*/
|
||||
nsDisplayItem* RemoveBottom();
|
||||
void Clear() {
|
||||
Node* current = mBottom;
|
||||
Node* next = nullptr;
|
||||
|
||||
while (current) {
|
||||
next = current->mNext;
|
||||
Deallocate(current);
|
||||
current = next;
|
||||
}
|
||||
|
||||
SetEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all items from the list and call their destructors.
|
||||
*/
|
||||
virtual void DeleteAll(nsDisplayListBuilder* aBuilder);
|
||||
|
||||
/**
|
||||
* @return the item at the top of the list, or null if the list is empty
|
||||
*/
|
||||
nsDisplayItem* GetTop() const {
|
||||
return mTop != &mSentinel ? static_cast<nsDisplayItem*>(mTop) : nullptr;
|
||||
}
|
||||
/**
|
||||
* @return the item at the bottom of the list, or null if the list is empty
|
||||
*/
|
||||
nsDisplayItem* GetBottom() const { return mSentinel.mAbove; }
|
||||
bool IsEmpty() const { return mTop == &mSentinel; }
|
||||
nsDisplayItem* GetBottom() const {
|
||||
return mBottom ? mBottom->mValue : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the item at the top of the list, or null if the list is empty
|
||||
*/
|
||||
nsDisplayItem* GetTop() const { return mTop ? mTop->mValue : nullptr; }
|
||||
|
||||
bool IsEmpty() const { return mBottom == nullptr; }
|
||||
|
||||
/**
|
||||
* @return the number of items in the list
|
||||
*/
|
||||
uint32_t Count() const { return mLength; }
|
||||
size_t Length() const { return mLength; }
|
||||
|
||||
/**
|
||||
* Stable sort the list by the z-order of GetUnderlyingFrame() on
|
||||
* Stable sort the list by the z-order of Frame() on
|
||||
* each item. 'auto' is counted as zero.
|
||||
* It is assumed that the list is already in content document order.
|
||||
*/
|
||||
void SortByZOrder();
|
||||
|
||||
/**
|
||||
* Stable sort the list by the tree order of the content of
|
||||
* GetUnderlyingFrame() on each item. z-index is ignored.
|
||||
* Frame() on each item. z-index is ignored.
|
||||
* @param aCommonAncestor a common ancestor of all the content elements
|
||||
* associated with the display items, for speeding up tree order
|
||||
* checks, or nullptr if not known; it's only a hint, if it is not an
|
||||
|
@ -3207,15 +3210,14 @@ class nsDisplayList {
|
|||
void SortByContentOrder(nsIContent* aCommonAncestor);
|
||||
|
||||
/**
|
||||
* Sort the display list using a stable sort. Take care, because some of the
|
||||
* items might be nsDisplayLists themselves.
|
||||
* Sort the display list using a stable sort.
|
||||
* aComparator(Item item1, Item item2) should return true if item1 should go
|
||||
* before item2.
|
||||
* We sort the items into increasing order.
|
||||
*/
|
||||
template <typename Item, typename Comparator>
|
||||
void Sort(const Comparator& aComparator) {
|
||||
if (Count() < 2) {
|
||||
if (Length() < 2) {
|
||||
// Only sort lists with more than one item.
|
||||
return;
|
||||
}
|
||||
|
@ -3225,7 +3227,7 @@ class nsDisplayList {
|
|||
// here.
|
||||
AutoTArray<Item, 20> items;
|
||||
|
||||
while (nsDisplayItem* item = RemoveBottom()) {
|
||||
for (nsDisplayItem* item : TakeItems()) {
|
||||
items.AppendElement(Item(item));
|
||||
}
|
||||
|
||||
|
@ -3236,10 +3238,14 @@ class nsDisplayList {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if any display item requires the surface to be transparent.
|
||||
*/
|
||||
bool NeedsTransparentSurface() const { return mForceTransparentSurface; }
|
||||
nsDisplayList TakeItems() {
|
||||
nsDisplayList list = std::move(*this);
|
||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
list.mAllowNonEmptyDestruction = true;
|
||||
#endif
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,
|
||||
|
@ -3335,19 +3341,32 @@ class nsDisplayList {
|
|||
*/
|
||||
nsRect GetBuildingRect() const;
|
||||
|
||||
void SetNeedsTransparentSurface() { mForceTransparentSurface = true; }
|
||||
|
||||
void RestoreState() { mForceTransparentSurface = false; }
|
||||
|
||||
private:
|
||||
nsDisplayItemLink mSentinel;
|
||||
nsDisplayItemLink* mTop;
|
||||
inline Node* Allocate(nsDisplayItem* aItem) {
|
||||
void* ptr = mPool.Allocate(sizeof(Node));
|
||||
return new (ptr) Node(aItem);
|
||||
}
|
||||
|
||||
uint32_t mLength;
|
||||
inline void Deallocate(Node* aNode) {
|
||||
aNode->~Node();
|
||||
// Memory remains reserved by the arena allocator.
|
||||
}
|
||||
|
||||
// This is set to true by FrameLayerBuilder if any display item in this
|
||||
// list needs to force the surface containing this list to be transparent.
|
||||
bool mForceTransparentSurface;
|
||||
void SetEmpty() {
|
||||
mBottom = nullptr;
|
||||
mTop = nullptr;
|
||||
mLength = 0;
|
||||
}
|
||||
|
||||
Node* mBottom = nullptr;
|
||||
Node* mTop = nullptr;
|
||||
size_t mLength = 0;
|
||||
ListArenaAllocator& mPool;
|
||||
|
||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
// This checks that the invariant of display lists owning their items is held.
|
||||
bool mAllowNonEmptyDestruction = false;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -3453,13 +3472,17 @@ class nsDisplayListSet {
|
|||
struct nsDisplayListCollection : public nsDisplayListSet {
|
||||
explicit nsDisplayListCollection(nsDisplayListBuilder* aBuilder)
|
||||
: nsDisplayListSet(&mLists[0], &mLists[1], &mLists[2], &mLists[3],
|
||||
&mLists[4], &mLists[5]) {}
|
||||
&mLists[4], &mLists[5]),
|
||||
mLists{nsDisplayList{aBuilder}, nsDisplayList{aBuilder},
|
||||
nsDisplayList{aBuilder}, nsDisplayList{aBuilder},
|
||||
nsDisplayList{aBuilder}, nsDisplayList{aBuilder}} {}
|
||||
|
||||
/*
|
||||
explicit nsDisplayListCollection(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayList* aBorderBackground)
|
||||
: nsDisplayListSet(aBorderBackground, &mLists[1], &mLists[2], &mLists[3],
|
||||
&mLists[4], &mLists[5]) {}
|
||||
|
||||
*/
|
||||
/**
|
||||
* Sort all lists by content order.
|
||||
*/
|
||||
|
@ -3497,29 +3520,33 @@ struct nsDisplayListCollection : public nsDisplayListSet {
|
|||
*/
|
||||
class RetainedDisplayList : public nsDisplayList {
|
||||
public:
|
||||
RetainedDisplayList() = default;
|
||||
RetainedDisplayList(RetainedDisplayList&& aOther) {
|
||||
AppendToTop(&aOther);
|
||||
mDAG = std::move(aOther.mDAG);
|
||||
}
|
||||
explicit RetainedDisplayList(nsDisplayListBuilder* aBuilder)
|
||||
: nsDisplayList(aBuilder) {}
|
||||
|
||||
RetainedDisplayList(RetainedDisplayList&& aOther)
|
||||
: nsDisplayList(std::move(aOther)), mDAG(std::move(aOther.mDAG)) {}
|
||||
|
||||
RetainedDisplayList(const RetainedDisplayList&) = delete;
|
||||
RetainedDisplayList& operator=(const RetainedDisplayList&) = delete;
|
||||
|
||||
~RetainedDisplayList() override {
|
||||
MOZ_ASSERT(mOldItems.IsEmpty(), "Must empty list before destroying");
|
||||
}
|
||||
|
||||
RetainedDisplayList& operator=(RetainedDisplayList&& aOther) {
|
||||
MOZ_ASSERT(!Count(), "Can only move into an empty list!");
|
||||
MOZ_ASSERT(IsEmpty(), "Can only move into an empty list!");
|
||||
MOZ_ASSERT(mOldItems.IsEmpty(), "Can only move into an empty list!");
|
||||
AppendToTop(&aOther);
|
||||
|
||||
nsDisplayList::operator=(std::move(aOther));
|
||||
mDAG = std::move(aOther.mDAG);
|
||||
mOldItems = std::move(aOther.mOldItems);
|
||||
return *this;
|
||||
}
|
||||
|
||||
RetainedDisplayList& operator=(nsDisplayList&& aOther) {
|
||||
MOZ_ASSERT(!Count(), "Can only move into an empty list!");
|
||||
MOZ_ASSERT(IsEmpty(), "Can only move into an empty list!");
|
||||
MOZ_ASSERT(mOldItems.IsEmpty(), "Can only move into an empty list!");
|
||||
AppendToTop(&aOther);
|
||||
nsDisplayList::operator=(std::move(aOther));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -4721,6 +4748,7 @@ class nsDisplayWrapList : public nsPaintedDisplayItem {
|
|||
|
||||
nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
|
||||
: nsPaintedDisplayItem(aBuilder, aFrame),
|
||||
mList(aBuilder),
|
||||
mFrameActiveScrolledRoot(aBuilder->CurrentActiveScrolledRoot()),
|
||||
mOverrideZIndex(0),
|
||||
mHasZIndexOverride(false) {
|
||||
|
@ -4740,6 +4768,7 @@ class nsDisplayWrapList : public nsPaintedDisplayItem {
|
|||
nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayWrapList& aOther)
|
||||
: nsPaintedDisplayItem(aBuilder, aOther),
|
||||
mList(aBuilder),
|
||||
mListPtr(&mList),
|
||||
mFrameActiveScrolledRoot(aOther.mFrameActiveScrolledRoot),
|
||||
mMergedFrames(aOther.mMergedFrames.Clone()),
|
||||
|
@ -4813,12 +4842,6 @@ class nsDisplayWrapList : public nsPaintedDisplayItem {
|
|||
bool* aSnap) const override;
|
||||
Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override;
|
||||
|
||||
/**
|
||||
* Checks if the given display item can be merged with this item.
|
||||
* @return true if the merging is possible, otherwise false.
|
||||
*/
|
||||
virtual bool CanMerge(const nsDisplayItem* aItem) const { return false; }
|
||||
|
||||
/**
|
||||
* Try to merge with the other item (which is below us in the display
|
||||
* list). This gets used by nsDisplayClip to coalesce clipping operations
|
||||
|
@ -6390,12 +6413,12 @@ class nsDisplayTransform : public nsPaintedDisplayItem {
|
|||
void CollectSorted3DTransformLeaves(nsDisplayListBuilder* aBuilder,
|
||||
nsTArray<TransformPolygon>& aLeaves);
|
||||
|
||||
mutable RetainedDisplayList mChildren;
|
||||
mutable Maybe<Matrix4x4Flagged> mTransform;
|
||||
mutable Maybe<Matrix4x4Flagged> mInverseTransform;
|
||||
// Accumulated transform of ancestors on the preserves-3d chain.
|
||||
UniquePtr<Matrix4x4> mTransformPreserves3D;
|
||||
nsRect mChildrenBuildingRect;
|
||||
mutable RetainedDisplayList mChildren;
|
||||
|
||||
// The untransformed bounds of |mChildren|.
|
||||
nsRect mChildBounds;
|
||||
|
@ -6693,50 +6716,58 @@ class FlattenedDisplayListIterator {
|
|||
public:
|
||||
FlattenedDisplayListIterator(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayList* aList)
|
||||
: FlattenedDisplayListIterator(aBuilder, aList, true) {}
|
||||
: mBuilder(aBuilder), mStart(aList->begin()), mEnd(aList->end()) {
|
||||
ResolveFlattening();
|
||||
}
|
||||
|
||||
virtual bool HasNext() const { return mNext || !mStack.IsEmpty(); }
|
||||
bool HasNext() const { return !AtEndOfCurrentList(); }
|
||||
|
||||
nsDisplayItem* GetNextItem() {
|
||||
if (!mNext) {
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_ASSERT(HasNext());
|
||||
|
||||
nsDisplayItem* next = mNext;
|
||||
mNext = next->GetAbove();
|
||||
nsDisplayItem* current = NextItem();
|
||||
Advance();
|
||||
|
||||
if (mNext && next->HasChildren() && mNext->HasChildren()) {
|
||||
// Since |next| and |mNext| are container items in the same list,
|
||||
// merging them might be possible.
|
||||
next = TryMergingFrom(next);
|
||||
if (!AtEndOfCurrentList() && current->CanMerge(NextItem())) {
|
||||
// Since we can merge at least two display items, create an array and
|
||||
// collect mergeable display items there.
|
||||
AutoTArray<nsDisplayItem*, 2> willMerge{current};
|
||||
|
||||
auto it = mStart;
|
||||
while (it != mEnd) {
|
||||
nsDisplayItem* next = *it;
|
||||
if (current->CanMerge(next)) {
|
||||
willMerge.AppendElement(next);
|
||||
++it;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
mStart = it;
|
||||
|
||||
current = mBuilder->MergeItems(willMerge);
|
||||
}
|
||||
|
||||
ResolveFlattening();
|
||||
|
||||
return next;
|
||||
return current;
|
||||
}
|
||||
|
||||
nsDisplayItem* PeekNext() { return mNext; }
|
||||
|
||||
protected:
|
||||
FlattenedDisplayListIterator(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayList* aList,
|
||||
const bool aResolveFlattening)
|
||||
: mBuilder(aBuilder), mNext(aList->GetBottom()) {
|
||||
if (aResolveFlattening) {
|
||||
// This is done conditionally in case subclass overrides
|
||||
// ShouldFlattenNextItem().
|
||||
ResolveFlattening();
|
||||
}
|
||||
void Advance() { ++mStart; }
|
||||
|
||||
bool AtEndOfNestedList() const {
|
||||
return AtEndOfCurrentList() && mStack.Length() > 0;
|
||||
}
|
||||
|
||||
virtual void EnterChildList(nsDisplayItem* aContainerItem) {}
|
||||
virtual void ExitChildList() {}
|
||||
bool AtEndOfCurrentList() const { return mStart == mEnd; }
|
||||
|
||||
bool AtEndOfNestedList() const { return !mNext && mStack.Length() > 0; }
|
||||
nsDisplayItem* NextItem() {
|
||||
MOZ_ASSERT(HasNext());
|
||||
return *mStart;
|
||||
}
|
||||
|
||||
virtual bool ShouldFlattenNextItem() {
|
||||
return mNext && mNext->ShouldFlattenAway(mBuilder);
|
||||
bool ShouldFlattenNextItem() {
|
||||
return HasNext() && NextItem()->ShouldFlattenAway(mBuilder);
|
||||
}
|
||||
|
||||
void ResolveFlattening() {
|
||||
|
@ -6745,60 +6776,36 @@ class FlattenedDisplayListIterator {
|
|||
// item, or the very end of the outer list.
|
||||
while (AtEndOfNestedList() || ShouldFlattenNextItem()) {
|
||||
if (AtEndOfNestedList()) {
|
||||
ExitChildList();
|
||||
|
||||
// We reached the end of the list, pop the next item from the stack.
|
||||
mNext = mStack.PopLastElement();
|
||||
// We reached the end of the list, pop the next list from the stack.
|
||||
std::tie(mStart, mEnd) = mStack.PopLastElement();
|
||||
} else {
|
||||
EnterChildList(mNext);
|
||||
// The next item wants to be flattened. This means that we will skip the
|
||||
// flattened item and directly iterate over its sublist.
|
||||
MOZ_ASSERT(ShouldFlattenNextItem());
|
||||
|
||||
// This item wants to be flattened. Store the next item on the stack,
|
||||
// and use the first item in the child list instead.
|
||||
mStack.AppendElement(mNext->GetAbove());
|
||||
mNext = mNext->GetChildren()->GetBottom();
|
||||
nsDisplayList* sublist = NextItem()->GetChildren();
|
||||
MOZ_ASSERT(sublist);
|
||||
|
||||
// Skip the flattened item.
|
||||
Advance();
|
||||
|
||||
// Store the current position on the stack.
|
||||
if (!AtEndOfCurrentList()) {
|
||||
mStack.AppendElement(std::make_pair(mStart, mEnd));
|
||||
}
|
||||
|
||||
// Iterate over the sublist.
|
||||
mStart = sublist->begin();
|
||||
mEnd = sublist->end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to merge display items starting from |aCurrent|.
|
||||
* Updates the internal pointer to the next display item.
|
||||
*/
|
||||
nsDisplayItem* TryMergingFrom(nsDisplayItem* aCurrent) {
|
||||
MOZ_ASSERT(aCurrent);
|
||||
MOZ_ASSERT(aCurrent->GetAbove());
|
||||
|
||||
nsDisplayWrapList* current = aCurrent->AsDisplayWrapList();
|
||||
nsDisplayWrapList* next = mNext->AsDisplayWrapList();
|
||||
|
||||
if (!current || !next) {
|
||||
// Either the current or the next item do not support merging.
|
||||
return aCurrent;
|
||||
}
|
||||
|
||||
// Attempt to merge |next| with |current|.
|
||||
if (current->CanMerge(next)) {
|
||||
// Merging is possible, collect all the successive mergeable items.
|
||||
AutoTArray<nsDisplayWrapList*, 2> willMerge{current};
|
||||
|
||||
do {
|
||||
willMerge.AppendElement(next);
|
||||
mNext = next->GetAbove();
|
||||
next = mNext ? mNext->AsDisplayWrapList() : nullptr;
|
||||
} while (next && current->CanMerge(next));
|
||||
|
||||
current = mBuilder->MergeItems(willMerge);
|
||||
}
|
||||
|
||||
// Here |mNext| will be either the first item that could not be merged with
|
||||
// |current|, or nullptr.
|
||||
return current;
|
||||
}
|
||||
|
||||
private:
|
||||
nsDisplayListBuilder* mBuilder;
|
||||
nsDisplayItem* mNext;
|
||||
AutoTArray<nsDisplayItem*, 16> mStack;
|
||||
nsDisplayList::iterator mStart;
|
||||
nsDisplayList::iterator mEnd;
|
||||
nsTArray<std::pair<nsDisplayList::iterator, nsDisplayList::iterator>> mStack;
|
||||
};
|
||||
|
||||
class PaintTelemetry {
|
||||
|
|
|
@ -154,7 +154,7 @@ void SVGForeignObjectFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
if (!static_cast<const SVGElement*>(GetContent())->HasValidDimensions()) {
|
||||
return;
|
||||
}
|
||||
nsDisplayList newList;
|
||||
nsDisplayList newList(aBuilder);
|
||||
nsDisplayListSet set(&newList, &newList, &newList, &newList, &newList,
|
||||
&newList);
|
||||
DisplayOutline(aBuilder, set);
|
||||
|
|
|
@ -997,7 +997,7 @@ void SVGOuterSVGAnonChildFrame::BuildDisplayList(
|
|||
// inside the nsDisplayTransform for our viewbox transform. The
|
||||
// nsDisplaySVGWrapper's reference frame is this frame, because this frame
|
||||
// always returns true from IsSVGTransformed.
|
||||
nsDisplayList newList;
|
||||
nsDisplayList newList(aBuilder);
|
||||
nsDisplayListSet set(&newList, &newList, &newList, &newList, &newList,
|
||||
&newList);
|
||||
BuildDisplayListForNonBlockChildren(aBuilder, set);
|
||||
|
|
|
@ -7520,7 +7520,9 @@ void nsDisplayTableItem::ComputeInvalidationRegion(
|
|||
|
||||
nsDisplayTableBackgroundSet::nsDisplayTableBackgroundSet(
|
||||
nsDisplayListBuilder* aBuilder, nsIFrame* aTable)
|
||||
: mBuilder(aBuilder) {
|
||||
: mBuilder(aBuilder),
|
||||
mColGroupBackgrounds(aBuilder),
|
||||
mColBackgrounds(aBuilder) {
|
||||
mPrevTableBackgroundSet = mBuilder->SetTableBackgroundSet(this);
|
||||
mozilla::DebugOnly<const nsIFrame*> reference =
|
||||
mBuilder->FindReferenceFrameFor(aTable, &mToReferenceFrame);
|
||||
|
|
|
@ -961,7 +961,7 @@ void nsBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
// and merge them into a single Content() list. This can cause us
|
||||
// to violate CSS stacking order, but forceLayer is a magic
|
||||
// XUL-only extension anyway.
|
||||
nsDisplayList masterList;
|
||||
nsDisplayList masterList(aBuilder);
|
||||
masterList.AppendToTop(tempLists.BorderBackground());
|
||||
masterList.AppendToTop(tempLists.BlockBorderBackgrounds());
|
||||
masterList.AppendToTop(tempLists.Floats());
|
||||
|
|
|
@ -330,7 +330,7 @@ void nsImageBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox clip(
|
||||
aBuilder, this, clipFlags);
|
||||
|
||||
nsDisplayList list;
|
||||
nsDisplayList list(aBuilder);
|
||||
list.AppendNewToTop<nsDisplayXULImage>(aBuilder, this);
|
||||
|
||||
CreateOwnLayerIfNeeded(aBuilder, &list,
|
||||
|
|
|
@ -500,7 +500,7 @@ void nsSliderFrame::BuildDisplayListForChildren(
|
|||
|
||||
// This is a bit of a hack. Collect up all descendant display items
|
||||
// and merge them into a single Content() list.
|
||||
nsDisplayList masterList;
|
||||
nsDisplayList masterList(aBuilder);
|
||||
masterList.AppendToTop(tempLists.BorderBackground());
|
||||
masterList.AppendToTop(tempLists.BlockBorderBackgrounds());
|
||||
masterList.AppendToTop(tempLists.Floats());
|
||||
|
|
Загрузка…
Ссылка в новой задаче