diff options
author | win7-7 <win7-7@users.noreply.github.com> | 2020-02-25 00:17:54 +0200 |
---|---|---|
committer | wolfbeast <mcwerewolf@wolfbeast.com> | 2020-04-14 12:58:11 +0200 |
commit | cbb61ab832508e9c231a256fb161d38d35faeabf (patch) | |
tree | fe4ffc233045d9b461460e19d31fcfbe64cae59f /layout/base/nsDisplayList.cpp | |
parent | cf288a1847afc0f101ff64afc29d8a2c3f7ffb03 (diff) | |
download | UXP-cbb61ab832508e9c231a256fb161d38d35faeabf.tar UXP-cbb61ab832508e9c231a256fb161d38d35faeabf.tar.gz UXP-cbb61ab832508e9c231a256fb161d38d35faeabf.tar.lz UXP-cbb61ab832508e9c231a256fb161d38d35faeabf.tar.xz UXP-cbb61ab832508e9c231a256fb161d38d35faeabf.zip |
Issue #1355 - Better way to create display items for column backgrounds
Part 1: Remove current table item, as it's never set.
Part 2: Get rid of generic table painting code, and handle each class separately.
Part 4: Hoist outline skipping into col(group) frame code.
Part 5: Skip box-shadow for table column and column groups.
Part 6: Store column and column group backgrounds separately, and then append them before the rest of the table contents.
Part 7: Pass rects in display list coordinates to AppendBackgroundItemsToTop.
Part 8: Create column and column group background display items as part of the cell's BuildDisplayList.
Part 9: Used cached values instead of calling nsDisplayListBuilder::ToReferenceFrame when possible, since it can be expensive when the requested frame isn't the builder's current frame.
Part 10: Make sure we build display items for table parts where only the normal position is visible, since we may need to create background items for ancestors at that position.
Part 11: Create an AutoBuildingDisplayList when we create background items for table columns and column groups, so that we initialize the invalidation state correctly.
Diffstat (limited to 'layout/base/nsDisplayList.cpp')
-rw-r--r-- | layout/base/nsDisplayList.cpp | 120 |
1 files changed, 78 insertions, 42 deletions
diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 8a34d108f..f870c6d97 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -721,7 +721,6 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame, : mReferenceFrame(aReferenceFrame), mIgnoreScrollFrame(nullptr), mLayerEventRegions(nullptr), - mCurrentTableItem(nullptr), mCurrentFrame(aReferenceFrame), mCurrentReferenceFrame(aReferenceFrame), mCurrentAGR(&mRootAGR), @@ -731,6 +730,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame, mGlassDisplayItem(nullptr), mScrollInfoItemsForHoisting(nullptr), mMode(aMode), + mTableBackgroundSet(nullptr), mCurrentScrollParentId(FrameMetrics::NULL_SCROLL_ID), mCurrentScrollbarTarget(FrameMetrics::NULL_SCROLL_ID), mCurrentScrollbarFlags(0), @@ -783,7 +783,10 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame, "Check nsDisplayItem::TYPE_MAX should not overflow"); } -static void MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame) { +void +nsDisplayListBuilder::MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame) +{ + mFramesMarkedForDisplay.AppendElement(aFrame); for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetParentOrPlaceholderFor(f)) { if (f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) @@ -796,6 +799,22 @@ static void MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame) { } } +void +nsDisplayListBuilder::MarkFrameForDisplayIfVisible(nsIFrame* aFrame, nsIFrame* aStopAtFrame) +{ + mFramesMarkedForDisplay.AppendElement(aFrame); + for (nsIFrame* f = aFrame; f; + f = nsLayoutUtils::GetParentOrPlaceholderFor(f)) { + if (f->ForceDescendIntoIfVisible()) + return; + f->SetForceDescendIntoIfVisible(true); + if (f == aStopAtFrame) { + // we've reached a frame that we know will be painted, so we can stop. + break; + } + } +} + bool nsDisplayListBuilder::NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem) { return aItem == mGlassDisplayItem || aItem->ClearsBackground(); @@ -864,10 +883,10 @@ nsDisplayListBuilder::FindAnimatedGeometryRootFor(nsDisplayItem* aItem) void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, - nsIFrame* aFrame, - const nsRect& aDirtyRect) + nsIFrame* aFrame) { - nsRect dirtyRectRelativeToDirtyFrame = aDirtyRect; + nsRect visible = GetVisibleRect(); + nsRect dirtyRectRelativeToDirtyFrame = GetDirtyRect(); if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(aFrame) && IsPaintingToWindow()) { NS_ASSERTION(aDirtyFrame == aFrame->GetParent(), "Dirty frame should be viewport frame"); @@ -881,8 +900,14 @@ void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, } else { dirtyRectRelativeToDirtyFrame.SizeTo(aDirtyFrame->GetSize()); } + // TODO: We probably don't want visible and dirty to be the same here, figure + // out what to do. + visible = dirtyRectRelativeToDirtyFrame; } - nsRect dirty = dirtyRectRelativeToDirtyFrame - aFrame->GetOffsetTo(aDirtyFrame); + + nsPoint offset = aFrame->GetOffsetTo(aDirtyFrame); + visible -= offset; + nsRect dirty = dirtyRectRelativeToDirtyFrame - offset; nsRect overflowRect = aFrame->GetVisualOverflowRect(); if (aFrame->IsTransformed() && @@ -895,15 +920,18 @@ void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, */ overflowRect.Inflate(nsPresContext::CSSPixelsToAppUnits(32)); } - - if (!dirty.IntersectRect(dirty, overflowRect) && - !(aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) { + visible.IntersectRect(visible, overflowRect); + dirty.IntersectRect(dirty, overflowRect); + if (!(aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) && + dirty.IsEmpty() && + (!aFrame->ForceDescendIntoIfVisible() || + visible.IsEmpty())) { return; } const DisplayItemClip* oldClip = mClipState.GetClipForContainingBlockDescendants(); const DisplayItemScrollClip* sc = mClipState.GetCurrentInnermostScrollClip(); - OutOfFlowDisplayData* data = new OutOfFlowDisplayData(oldClip, sc, dirty); + OutOfFlowDisplayData* data = new OutOfFlowDisplayData(oldClip, sc, visible, dirty); aFrame->SetProperty(nsDisplayListBuilder::OutOfFlowDisplayDataProperty(), data); MarkFrameForDisplay(aFrame, aDirtyFrame); @@ -914,9 +942,11 @@ static void UnmarkFrameForDisplay(nsIFrame* aFrame) { for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetParentOrPlaceholderFor(f)) { - if (!(f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) + if (!(f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) && + !f->ForceDescendIntoIfVisible()) return; f->RemoveStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO); + f->SetForceDescendIntoIfVisible(false); } } @@ -925,7 +955,6 @@ nsDisplayListBuilder::~nsDisplayListBuilder() { "All frames should have been unmarked"); NS_ASSERTION(mPresShellStates.Length() == 0, "All presshells should have been exited"); - NS_ASSERTION(!mCurrentTableItem, "No table item should be active"); nsCSSRendering::EndFrameTreesLocked(); @@ -1008,22 +1037,27 @@ nsDisplayListBuilder::EnterPresShell(nsIFrame* aReferenceFrame, } state->mInsidePointerEventsNoneDoc = pointerEventsNone; + state->mPresShellIgnoreScrollFrame = + state->mPresShell->IgnoringViewportScrolling() + ? state->mPresShell->GetRootScrollFrame() + : nullptr; + + nsPresContext* pc = aReferenceFrame->PresContext(); + nsCOMPtr<nsIDocShell> docShell = pc->GetDocShell(); + if (docShell) { + docShell->GetWindowDraggingAllowed(&mWindowDraggingAllowed); + } + + mIsInChromePresContext = pc->IsChrome(); + if (!buildCaret) return; RefPtr<nsCaret> caret = state->mPresShell->GetCaret(); state->mCaretFrame = caret->GetPaintGeometry(&state->mCaretRect); if (state->mCaretFrame) { - mFramesMarkedForDisplay.AppendElement(state->mCaretFrame); MarkFrameForDisplay(state->mCaretFrame, nullptr); } - - nsPresContext* pc = aReferenceFrame->PresContext(); - nsCOMPtr<nsIDocShell> docShell = pc->GetDocShell(); - if (docShell) { - docShell->GetWindowDraggingAllowed(&mWindowDraggingAllowed); - } - mIsInChromePresContext = pc->IsChrome(); } // A non-blank paint is a paint that does not just contain the canvas background. @@ -1094,8 +1128,7 @@ nsDisplayListBuilder::ResetMarkedFramesForDisplayList() void nsDisplayListBuilder::MarkFramesForDisplayList(nsIFrame* aDirtyFrame, - const nsFrameList& aFrames, - const nsRect& aDirtyRect) { + const nsFrameList& aFrames) { for (nsIFrame* e : aFrames) { // Skip the AccessibleCaret frame when building no caret. if (!IsBuildingCaret()) { @@ -1108,8 +1141,7 @@ nsDisplayListBuilder::MarkFramesForDisplayList(nsIFrame* aDirtyFrame, } } - mFramesMarkedForDisplay.AppendElement(e); - MarkOutOfFlowFrameForDisplay(aDirtyFrame, e, aDirtyRect); + MarkOutOfFlowFrameForDisplay(aDirtyFrame, e); } } @@ -1132,7 +1164,6 @@ nsDisplayListBuilder::MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame) for (; !childFrames.AtEnd(); childFrames.Next()) { nsIFrame *child = childFrames.get(); if (child->Combines3DTransformWithAncestors()) { - mFramesMarkedForDisplay.AppendElement(child); MarkFrameForDisplay(child, aDirtyFrame); } } @@ -2318,11 +2349,11 @@ nsDisplayItem::nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, mAnimatedGeometryRoot = aBuilder->FindAnimatedGeometryRootFor(aFrame); MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(aBuilder->RootReferenceFrame(), *mAnimatedGeometryRoot), "Bad"); - NS_ASSERTION(aBuilder->GetDirtyRect().width >= 0 || - !aBuilder->IsForPainting(), "dirty rect not set"); - // The dirty rect is for mCurrentFrame, so we have to use + NS_ASSERTION(aBuilder->GetVisibleRect().width >= 0 || + !aBuilder->IsForPainting(), "visible rect not set"); + // The visible rect is for mCurrentFrame, so we have to use // mCurrentOffsetToReferenceFrame - mVisibleRect = aBuilder->GetDirtyRect() + + mVisibleRect = aBuilder->GetVisibleRect() + aBuilder->GetCurrentFrameOffsetToReferenceFrame(); } @@ -2573,8 +2604,7 @@ static nsStyleContext* GetBackgroundStyleContext(nsIFrame* aFrame) /* static */ void SetBackgroundClipRegion(DisplayListClipState::AutoSaveRestore& aClipState, - nsIFrame* aFrame, const nsPoint& aToReferenceFrame, - const nsStyleImageLayers::Layer& aLayer, + nsIFrame* aFrame, const nsStyleImageLayers::Layer& aLayer, const nsRect& aBackgroundRect, bool aWillPaintBorder) { @@ -2626,7 +2656,6 @@ SpecialCutoutRegionCase(nsDisplayListBuilder* aBuilder, return true; } - /*static*/ bool nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, @@ -2635,14 +2664,16 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil bool aAllowWillPaintBorderOptimization, nsStyleContext* aStyleContext, const nsRect& aBackgroundOriginRect, - nsIFrame* aSecondaryReferenceFrame) + nsIFrame* aSecondaryReferenceFrame, + Maybe<nsDisplayListBuilder::AutoBuildingDisplayList>* + aAutoBuildingDisplayList) { nsStyleContext* bgSC = aStyleContext; const nsStyleBackground* bg = nullptr; - nsRect bgRect = aBackgroundRect + aBuilder->ToReferenceFrame(aFrame); + nsRect bgRect = aBackgroundRect; nsRect bgOriginRect = bgRect; if (!aBackgroundOriginRect.IsEmpty()) { - bgOriginRect = aBackgroundOriginRect + aBuilder->ToReferenceFrame(aFrame); + bgOriginRect = aBackgroundOriginRect; } nsPresContext* presContext = aFrame->PresContext(); bool isThemed = aFrame->IsThemed(); @@ -2678,8 +2709,6 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil !isThemed && !hasInsetShadow && borderStyle->HasBorder(); - nsPoint toRef = aBuilder->ToReferenceFrame(aFrame); - // 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 @@ -2688,6 +2717,9 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil // to create an item for hit testing. if ((drawBackgroundColor && color != NS_RGBA(0,0,0,0)) || aBuilder->IsForEventDelivery()) { + if (aAutoBuildingDisplayList && !*aAutoBuildingDisplayList) { + aAutoBuildingDisplayList->emplace(aBuilder, aFrame); + } DisplayListClipState::AutoSaveRestore clipState(aBuilder); if (bg && !aBuilder->IsForEventDelivery()) { // Disable the will-paint-border optimization for background @@ -2699,7 +2731,7 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil // artifacts along the rounded corners. bool useWillPaintBorderOptimization = willPaintBorder && nsLayoutUtils::HasNonZeroCorner(borderStyle->mBorderRadius); - SetBackgroundClipRegion(clipState, aFrame, toRef, + SetBackgroundClipRegion(clipState, aFrame, bg->BottomLayer(), bgRect, useWillPaintBorderOptimization); } @@ -2752,6 +2784,10 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil continue; } + if (aAutoBuildingDisplayList && !*aAutoBuildingDisplayList) { + aAutoBuildingDisplayList->emplace(aBuilder, aFrame); + } + if (bg->mImage.mLayers[i].mBlendMode != NS_STYLE_BLEND_NORMAL) { needBlendContainer = true; } @@ -2759,8 +2795,8 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil DisplayListClipState::AutoSaveRestore clipState(aBuilder); if (!aBuilder->IsForEventDelivery()) { const nsStyleImageLayers::Layer& layer = bg->mImage.mLayers[i]; - SetBackgroundClipRegion(clipState, aFrame, toRef, - layer, bgRect, willPaintBorder); + SetBackgroundClipRegion(clipState, aFrame, layer, bgRect, + willPaintBorder); } nsDisplayList thisItemList; @@ -4342,7 +4378,7 @@ nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder, mReferenceFrame = i->ReferenceFrame(); mToReferenceFrame = i->ToReferenceFrame(); } - mVisibleRect = aBuilder->GetDirtyRect() + + mVisibleRect = aBuilder->GetVisibleRect() + aBuilder->GetCurrentFrameOffsetToReferenceFrame(); } @@ -4368,7 +4404,7 @@ nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder, mReferenceFrame = aItem->ReferenceFrame(); mToReferenceFrame = aItem->ToReferenceFrame(); } - mVisibleRect = aBuilder->GetDirtyRect() + + mVisibleRect = aBuilder->GetVisibleRect() + aBuilder->GetCurrentFrameOffsetToReferenceFrame(); } |