/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* vim: set ts=8 sts=2 et sw=2 tw=80: *//* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. *//* * structures that represent things to be painted (ordered in z-order), * used during painting and hit testing */#ifndef NSDISPLAYLIST_H_#define NSDISPLAYLIST_H_#include"DisplayItemClipChain.h"#include"DisplayListClipState.h"#include"FrameMetrics.h"#include"HitTestInfo.h"#include"ImgDrawResult.h"#include"LayerState.h"#include"RetainedDisplayListHelpers.h"#include"Units.h"#include"gfxContext.h"#include"mozilla/ArenaAllocator.h"#include"mozilla/Array.h"#include"mozilla/Assertions.h"#include"mozilla/Attributes.h"#include"mozilla/DebugOnly.h"#include"mozilla/EffectCompositor.h"#include"mozilla/EnumSet.h"#include"mozilla/EnumeratedArray.h"#include"mozilla/Maybe.h"#include"mozilla/MotionPathUtils.h"#include"mozilla/RefPtr.h"#include"mozilla/TemplateLib.h"#include"mozilla/TimeStamp.h"#include"mozilla/UniquePtr.h"#include"mozilla/dom/EffectsInfo.h"#include"mozilla/dom/RemoteBrowser.h"#include"mozilla/gfx/UserData.h"#include"mozilla/layers/BSPTree.h"#include"mozilla/layers/LayerAttributes.h"#include"mozilla/layers/ScrollableLayerGuid.h"#include"nsAutoLayoutPhase.h"#include"nsCOMPtr.h"#include"nsCSSRenderingBorders.h"#include"nsContainerFrame.h"#include"nsDisplayItemTypes.h"#include"nsDisplayListInvalidation.h"#include"nsPoint.h"#include"nsPresArena.h"#include"nsRect.h"#include"nsRegion.h"#include"nsClassHashtable.h"#include"nsTHashSet.h"#include"nsTHashMap.h"#include<algorithm>#include<unordered_set>// XXX Includes that could be avoided by moving function implementations to the// cpp file.#include"gfxPlatform.h"classgfxContext;classnsIContent;classnsIScrollableFrame;classnsSubDocumentFrame;classnsCaret;structWrFiltersHolder;namespacensStyleTransformMatrix{classTransformReferenceBox;}namespacemozilla{enumclassnsDisplayOwnLayerFlags;classnsDisplayCompositorHitTestInfo;classnsDisplayScrollInfoLayer;classPresShell;classStickyScrollContainer;namespacelayers{structFrameMetrics;classRenderRootStateManager;classLayer;classImageLayer;classImageContainer;classStackingContextHelper;classWebRenderScrollData;classWebRenderLayerScrollData;classWebRenderLayerManager;}// namespace layersnamespacewr{classDisplayListBuilder;}// namespace wrnamespacedom{classSelection;}// namespace domenumclassDisplayListArenaObjectId{#define DISPLAY_LIST_ARENA_OBJECT(name_) name_,#include"nsDisplayListArenaTypes.h"#undef DISPLAY_LIST_ARENA_OBJECTCOUNT};/* * An nsIFrame can have many different visual parts. For example an image frame * can have a background, border, and outline, the image itself, and a * translucent selection overlay. In general these parts can be drawn at * discontiguous z-levels; see CSS2.1 appendix E: * http://www.w3.org/TR/CSS21/zindex.html * * We construct a display list for a frame tree that contains one item * for each visual part. The display list is itself a tree since some items * are containers for other items; however, its structure does not match * the structure of its source frame tree. The display list items are sorted * by z-order. A display list can be used to paint the frames, to determine * which frame is the target of a mouse event, and to determine what areas * need to be repainted when scrolling. The display lists built for each task * may be different for efficiency; in particular some frames need special * display list items only for event handling, and do not create these items * when the display list will be used for painting (the common case). For * example, when painting we avoid creating nsDisplayBackground items for * frames that don't display a visible background, but for event handling * we need those backgrounds because they are not transparent to events. * * We could avoid constructing an explicit display list by traversing the * frame tree multiple times in clever ways. However, reifying the display list * reduces code complexity and reduces the number of times each frame must be * traversed to one, which seems to be good for performance. It also means * we can share code for painting, event handling and scroll analysis. * * Display lists are short-lived; content and frame trees cannot change * between a display list being created and destroyed. Display lists should * not be created during reflow because the frame tree may be in an * inconsistent state (e.g., a frame's stored overflow-area may not include * the bounds of all its children). However, it should be fine to create * a display list while a reflow is pending, before it starts. * * A display list covers the "extended" frame tree; the display list for * a frame tree containing FRAME/IFRAME elements can include frames from * the subdocuments. * * Display item's coordinates are relative to their nearest reference frame * ancestor. Both the display root and any frame with a transform act as a * reference frame for their frame subtrees. *//** * Represents a frame that is considered to have (or will have) "animated * geometry" for itself and descendant frames. * * For example the scrolled frames of scrollframes which are actively being * scrolled fall into this category. Frames with certain CSS properties that are * being animated (e.g. 'left'/'top' etc) are also placed in this category. * Frames with different active geometry roots are in different PaintedLayers, * so that we can animate the geometry root by changing its transform (either on * the main thread or in the compositor). * * nsDisplayListBuilder constructs a tree of these (for fast traversals) and * assigns one for each display item. * * The animated geometry root for a display item is required to be a descendant * (or equal to) the item's ReferenceFrame(), which means that we will fall back * to returning aItem->ReferenceFrame() when we can't find another animated * geometry root. * * The animated geometry root isn't strongly defined for a frame as transforms * and background-attachment:fixed can cause it to vary between display items * for a given frame. */structAnimatedGeometryRoot{staticalready_AddRefed<AnimatedGeometryRoot>CreateAGRForFrame(nsIFrame*aFrame,AnimatedGeometryRoot*aParent,boolaIsAsync,boolaIsRetained){RefPtr<AnimatedGeometryRoot>result;if(aIsRetained){result=aFrame->GetProperty(AnimatedGeometryRootCache());}if(result){result->mParentAGR=aParent;result->mIsAsync=aIsAsync;}else{result=newAnimatedGeometryRoot(aFrame,aParent,aIsAsync,aIsRetained);}returnresult.forget();}operatornsIFrame*(){returnmFrame;}nsIFrame*operator->()const{returnmFrame;}AnimatedGeometryRoot*GetAsyncAGR(){AnimatedGeometryRoot*agr=this;while(!agr->mIsAsync&&agr->mParentAGR){agr=agr->mParentAGR;}returnagr;}NS_INLINE_DECL_REFCOUNTING(AnimatedGeometryRoot)nsIFrame*mFrame;RefPtr<AnimatedGeometryRoot>mParentAGR;boolmIsAsync;boolmIsRetained;protected:staticvoidDetachAGR(AnimatedGeometryRoot*aAGR){aAGR->mFrame=nullptr;aAGR->mParentAGR=nullptr;NS_RELEASE(aAGR);}NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(AnimatedGeometryRootCache,AnimatedGeometryRoot,DetachAGR)AnimatedGeometryRoot(nsIFrame*aFrame,AnimatedGeometryRoot*aParent,boolaIsAsync,boolaIsRetained):mFrame(aFrame),mParentAGR(aParent),mIsAsync(aIsAsync),mIsRetained(aIsRetained){MOZ_ASSERT(mParentAGR||mIsAsync,"The root AGR should always be treated as an async AGR.");if(mIsRetained){NS_ADDREF(this);aFrame->SetProperty(AnimatedGeometryRootCache(),this);}}~AnimatedGeometryRoot(){if(mFrame&&mIsRetained){mFrame->RemoveProperty(AnimatedGeometryRootCache());}}};/** * An active scrolled root (ASR) is similar to an animated geometry root (AGR). * The differences are: * - ASRs are only created for async-scrollable scroll frames. This is a * (hopefully) temporary restriction. In the future we will want to create * ASRs for all the things that are currently creating AGRs, and then * replace AGRs with ASRs and rename them from "active scrolled root" to * "animated geometry root". * - ASR objects are created during display list construction by the nsIFrames * that induce ASRs. This is done using AutoCurrentActiveScrolledRootSetter. * The current ASR is returned by * nsDisplayListBuilder::CurrentActiveScrolledRoot(). * - There is no way to go from an nsIFrame pointer to the ASR of that frame. * If you need to look up an ASR after display list construction, you need * to store it while the AutoCurrentActiveScrolledRootSetter that creates it * is on the stack. */structActiveScrolledRoot{staticalready_AddRefed<ActiveScrolledRoot>CreateASRForFrame(constActiveScrolledRoot*aParent,nsIScrollableFrame*aScrollableFrame,boolaIsRetained);staticconstActiveScrolledRoot*PickAncestor(constActiveScrolledRoot*aOne,constActiveScrolledRoot*aTwo){MOZ_ASSERT(IsAncestor(aOne,aTwo)||IsAncestor(aTwo,aOne));returnDepth(aOne)<=Depth(aTwo)?aOne:aTwo;}staticconstActiveScrolledRoot*PickDescendant(constActiveScrolledRoot*aOne,constActiveScrolledRoot*aTwo){MOZ_ASSERT(IsAncestor(aOne,aTwo)||IsAncestor(aTwo,aOne));returnDepth(aOne)>=Depth(aTwo)?aOne:aTwo;}staticboolIsAncestor(constActiveScrolledRoot*aAncestor,constActiveScrolledRoot*aDescendant);staticboolIsProperAncestor(constActiveScrolledRoot*aAncestor,constActiveScrolledRoot*aDescendant);staticnsCStringToString(constActiveScrolledRoot*aActiveScrolledRoot);// Call this when inserting an ancestor.voidIncrementDepth(){mDepth++;}/** * Find the view ID (or generate a new one) for the content element * corresponding to the ASR. */layers::ScrollableLayerGuid::ViewIDGetViewId()const{if(!mViewId.isSome()){mViewId=Some(ComputeViewId());}return*mViewId;}RefPtr<constActiveScrolledRoot>mParent;nsIScrollableFrame*mScrollableFrame;NS_INLINE_DECL_REFCOUNTING(ActiveScrolledRoot)private:ActiveScrolledRoot():mScrollableFrame(nullptr),mDepth(0),mRetained(false){}~ActiveScrolledRoot();staticvoidDetachASR(ActiveScrolledRoot*aASR){aASR->mParent=nullptr;aASR->mScrollableFrame=nullptr;NS_RELEASE(aASR);}NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(ActiveScrolledRootCache,ActiveScrolledRoot,DetachASR)staticuint32_tDepth(constActiveScrolledRoot*aActiveScrolledRoot){returnaActiveScrolledRoot?aActiveScrolledRoot->mDepth:0;}layers::ScrollableLayerGuid::ViewIDComputeViewId()const;// This field is lazily populated in GetViewId(). We don't want to do the// work of populating if webrender is disabled, because it is often not// needed.mutableMaybe<layers::ScrollableLayerGuid::ViewID>mViewId;uint32_tmDepth;boolmRetained;};enumclassnsDisplayListBuilderMode:uint8_t{Painting,PaintForPrinting,EventDelivery,FrameVisibility,TransformComputation,GenerateGlyph,};classnsDisplayList;classnsDisplayWrapList;classnsDisplayTableBackgroundSet;classnsDisplayTableItem;/** * This manages a display list and is passed as a parameter to * nsIFrame::BuildDisplayList. * It contains the parameters that don't change from frame to frame and manages * the display list memory using an arena. It also establishes the reference * coordinate system for all display list items. Some of the parameters are * available from the prescontext/presshell, but we copy them into the builder * for faster/more convenient access. */classnsDisplayListBuilder{/** * This manages status of a 3d context to collect visible rects of * descendants and passing a dirty rect. * * Since some transforms maybe singular, passing visible rects or * the dirty rect level by level from parent to children may get a * wrong result, being different from the result of appling with * effective transform directly. * * nsIFrame::BuildDisplayListForStackingContext() uses * AutoPreserves3DContext to install an instance on the builder. * * \see AutoAccumulateTransform, AutoAccumulateRect, * AutoPreserves3DContext, Accumulate, GetCurrentTransform, * StartRoot. */classPreserves3DContext{public:Preserves3DContext():mAccumulatedRectLevels(0),mAllowAsyncAnimation(true){}Preserves3DContext(constPreserves3DContext&aOther):mAccumulatedTransform(),mAccumulatedRect(),mAccumulatedRectLevels(0),mVisibleRect(aOther.mVisibleRect),mAllowAsyncAnimation(aOther.mAllowAsyncAnimation){}// Accmulate transforms of ancestors on the preserves-3d chain.gfx::Matrix4x4mAccumulatedTransform;// Accmulate visible rect of descendants in the preserves-3d context.nsRectmAccumulatedRect;// How far this frame is from the root of the current 3d context.intmAccumulatedRectLevels;nsRectmVisibleRect;// Allow async animation for this 3D context.boolmAllowAsyncAnimation;};/** * A frame can be in one of three states of AGR. * AGR_NO means the frame is not an AGR for now. * AGR_YES means the frame is an AGR for now. */enumAGRState{AGR_NO,AGR_YES};public:usingViewID=layers::ScrollableLayerGuid::ViewID;/** * @param aReferenceFrame the frame at the root of the subtree; its origin * is the origin of the reference coordinate system for this display list * @param aMode encodes what the builder is being used for. * @param aBuildCaret whether or not we should include the caret in any * display lists that we make. */nsDisplayListBuilder(nsIFrame*aReferenceFrame,nsDisplayListBuilderModeaMode,boolaBuildCaret,boolaRetainingDisplayList=false);~nsDisplayListBuilder();voidBeginFrame();voidEndFrame();voidAddTemporaryItem(nsDisplayItem*aItem){mTemporaryItems.AppendElement(aItem);}WindowRenderer*GetWidgetWindowRenderer(nsView**aView=nullptr);layers::WebRenderLayerManager*GetWidgetLayerManager(nsView**aView=nullptr);/** * @return true if the display is being built in order to determine which * frame is under the mouse position. */boolIsForEventDelivery()const{returnmMode==nsDisplayListBuilderMode::EventDelivery;}/** * @return true if the display list is being built for painting. This * includes both painting to a window or other buffer and painting to * a print/pdf destination. */boolIsForPainting()const{returnmMode==nsDisplayListBuilderMode::Painting||mMode==nsDisplayListBuilderMode::PaintForPrinting;}/** * @return true if the display list is being built specifically for printing. */boolIsForPrinting()const{returnmMode==nsDisplayListBuilderMode::PaintForPrinting;}/** * @return true if the display list is being built for determining frame * visibility. */boolIsForFrameVisibility()const{returnmMode==nsDisplayListBuilderMode::FrameVisibility;}/** * @return true if the display list is being built for creating the glyph * mask from text items. */boolIsForGenerateGlyphMask()const{returnmMode==nsDisplayListBuilderMode::GenerateGlyph;}boolBuildCompositorHitTestInfo()const{returnmBuildCompositorHitTestInfo;}/** * @return true if "painting is suppressed" during page load and we * should paint only the background of the document. */boolIsBackgroundOnly(){NS_ASSERTION(mPresShellStates.Length()>0,"don't call this if we're not in a presshell");returnCurrentPresShellState()->mIsBackgroundOnly;}/** * @return the root of given frame's (sub)tree, whose origin * establishes the coordinate system for the child display items. */constnsIFrame*FindReferenceFrameFor(constnsIFrame*aFrame,nsPoint*aOffset=nullptr)const;constMaybe<nsPoint>&AdditionalOffset()const{returnmAdditionalOffset;}/** * @return the root of the display list's frame (sub)tree, whose origin * establishes the coordinate system for the display list */nsIFrame*RootReferenceFrame()const{returnmReferenceFrame;}/** * @return a point pt such that adding pt to a coordinate relative to aFrame * makes it relative to ReferenceFrame(), i.e., returns * aFrame->GetOffsetToCrossDoc(ReferenceFrame()). The returned point is in * the appunits of aFrame. */constnsPointToReferenceFrame(constnsIFrame*aFrame)const{nsPointresult;FindReferenceFrameFor(aFrame,&result);returnresult;}/** * When building the display list, the scrollframe aFrame will be "ignored" * for the purposes of clipping, and its scrollbars will be hidden. We use * this to allow RenderOffscreen to render a whole document without beign * clipped by the viewport or drawing the viewport scrollbars. */voidSetIgnoreScrollFrame(nsIFrame*aFrame){mIgnoreScrollFrame=aFrame;}/** * Get the scrollframe to ignore, if any. */nsIFrame*GetIgnoreScrollFrame(){returnmIgnoreScrollFrame;}voidSetIsRelativeToLayoutViewport();boolIsRelativeToLayoutViewport()const{returnmIsRelativeToLayoutViewport;}/** * Get the ViewID of the nearest scrolling ancestor frame. */ViewIDGetCurrentScrollParentId()const{returnmCurrentScrollParentId;}/** * Get and set the flag that indicates if scroll parents should have layers * forcibly created. This flag is set when a deeply nested scrollframe has * a displayport, and for scroll handoff to work properly the ancestor * scrollframes should also get their own scrollable layers. */voidForceLayerForScrollParent(){mForceLayerForScrollParent=true;}/** * Set the flag that indicates there is a non-minimal display port in the * current subtree. This is used to determine display port expiry. */voidSetContainsNonMinimalDisplayPort(){mContainsNonMinimalDisplayPort=true;}/** * Get the ViewID and the scrollbar flags corresponding to the scrollbar for * which we are building display items at the moment. */ViewIDGetCurrentScrollbarTarget()const{returnmCurrentScrollbarTarget;}Maybe<layers::ScrollDirection>GetCurrentScrollbarDirection()const{returnmCurrentScrollbarDirection;}/** * Returns true if building a scrollbar, and the scrollbar will not be * layerized. */boolIsBuildingNonLayerizedScrollbar()const{returnmIsBuildingScrollbar&&!mCurrentScrollbarWillHaveLayer;}/** * Calling this setter makes us include all out-of-flow descendant * frames in the display list, wherever they may be positioned (even * outside the dirty rects). */voidSetIncludeAllOutOfFlows(){mIncludeAllOutOfFlows=true;}boolGetIncludeAllOutOfFlows()const{returnmIncludeAllOutOfFlows;}/** * Calling this setter makes us exclude all leaf frames that aren't * selected. */voidSetSelectedFramesOnly(){mSelectedFramesOnly=true;}boolGetSelectedFramesOnly(){returnmSelectedFramesOnly;}/** * @return Returns true if we should include the caret in any display lists * that we make. */boolIsBuildingCaret()const{returnmBuildCaret;}boolIsRetainingDisplayList()const{returnmRetainingDisplayList;}boolIsPartialUpdate()const{returnmPartialUpdate;}voidSetPartialUpdate(boolaPartial){mPartialUpdate=aPartial;}boolIsBuilding()const{returnmIsBuilding;}voidSetIsBuilding(boolaIsBuilding){mIsBuilding=aIsBuilding;}boolInInvalidSubtree()const{returnmInInvalidSubtree;}/** * Allows callers to selectively override the regular paint suppression * checks, so that methods like GetFrameForPoint work when painting is * suppressed. */voidIgnorePaintSuppression(){mIgnoreSuppression=true;}/** * @return Returns if this builder will ignore paint suppression. */boolIsIgnoringPaintSuppression(){returnmIgnoreSuppression;}/** * Call this if we're doing normal painting to the window. */voidSetPaintingToWindow(boolaToWindow){mIsPaintingToWindow=aToWindow;}boolIsPaintingToWindow()const{returnmIsPaintingToWindow;}/** * Call this if we're using high quality scaling for image decoding. * It is also implied by IsPaintingToWindow. */voidSetUseHighQualityScaling(boolaUseHighQualityScaling){mUseHighQualityScaling=aUseHighQualityScaling;}boolUseHighQualityScaling()const{returnmIsPaintingToWindow||mUseHighQualityScaling;}/** * Call this if we're doing painting for WebRender */voidSetPaintingForWebRender(boolaForWebRender){mIsPaintingForWebRender=true;}boolIsPaintingForWebRender()const{returnmIsPaintingForWebRender;}/** * Call this to prevent descending into subdocuments. */voidSetDescendIntoSubdocuments(boolaDescend){mDescendIntoSubdocuments=aDescend;}boolGetDescendIntoSubdocuments(){returnmDescendIntoSubdocuments;}/** * Get dirty rect relative to current frame (the frame that we're calling * BuildDisplayList on right now). */constnsRect&GetVisibleRect(){returnmVisibleRect;}constnsRect&GetDirtyRect(){returnmDirtyRect;}voidSetVisibleRect(constnsRect&aVisibleRect){mVisibleRect=aVisibleRect;}voidIntersectVisibleRect(constnsRect&aVisibleRect){mVisibleRect.IntersectRect(mVisibleRect,aVisibleRect);}voidSetDirtyRect(constnsRect&aDirtyRect){mDirtyRect=aDirtyRect;}voidIntersectDirtyRect(constnsRect&aDirtyRect){mDirtyRect.IntersectRect(mDirtyRect,aDirtyRect);}constnsIFrame*GetCurrentFrame(){returnmCurrentFrame;}constnsIFrame*GetCurrentReferenceFrame(){returnmCurrentReferenceFrame;}constnsPoint&GetCurrentFrameOffsetToReferenceFrame()const{returnmCurrentOffsetToReferenceFrame;}AnimatedGeometryRoot*GetCurrentAnimatedGeometryRoot(){returnmCurrentAGR;}AnimatedGeometryRoot*GetRootAnimatedGeometryRoot(){returnmRootAGR;}voidRecomputeCurrentAnimatedGeometryRoot();voidCheck(){mPool.Check();}/** * Returns true if merging and flattening of display lists should be * performed while computing visibility. */boolAllowMergingAndFlattening(){returnmAllowMergingAndFlattening;}voidSetAllowMergingAndFlattening(boolaAllow){mAllowMergingAndFlattening=aAllow;}voidSetCompositorHitTestInfo(constgfx::CompositorHitTestInfo&aInfo){mCompositorHitTestInfo=aInfo;}constgfx::CompositorHitTestInfo&GetCompositorHitTestInfo()const{returnmCompositorHitTestInfo;}/** * Builds a new nsDisplayCompositorHitTestInfo for the frame |aFrame| if * needed, and adds it to the top of |aList|. */voidBuildCompositorHitTestInfoIfNeeded(nsIFrame*aFrame,nsDisplayList*aList);boolIsInsidePointerEventsNoneDoc(){returnCurrentPresShellState()->mInsidePointerEventsNoneDoc;}boolIsTouchEventPrefEnabledDoc(){returnCurrentPresShellState()->mTouchEventPrefEnabledDoc;}boolGetAncestorHasApzAwareEventHandler()const{returnmAncestorHasApzAwareEventHandler;}voidSetAncestorHasApzAwareEventHandler(boolaValue){mAncestorHasApzAwareEventHandler=aValue;}boolHaveScrollableDisplayPort()const{returnmHaveScrollableDisplayPort;}voidSetHaveScrollableDisplayPort(){mHaveScrollableDisplayPort=true;}voidClearHaveScrollableDisplayPort(){mHaveScrollableDisplayPort=false;}boolSetIsCompositingCheap(boolaCompositingCheap){booltemp=mIsCompositingCheap;mIsCompositingCheap=aCompositingCheap;returntemp;}boolIsCompositingCheap()const{returnmIsCompositingCheap;}/** * Display the caret if needed. */boolDisplayCaret(nsIFrame*aFrame,nsDisplayList*aList){nsIFrame*frame=GetCaretFrame();if(aFrame==frame&&!IsBackgroundOnly()){frame->DisplayCaret(this,aList);returntrue;}returnfalse;}/** * Get the frame that the caret is supposed to draw in. * If the caret is currently invisible, this will be null. */nsIFrame*GetCaretFrame(){returnmCaretFrame;}/** * Get the rectangle we're supposed to draw the caret into. */constnsRect&GetCaretRect(){returnmCaretRect;}/** * Get the caret associated with the current presshell. */nsCaret*GetCaret();/** * Returns the root scroll frame for the current PresShell, if the PresShell * is ignoring viewport scrolling. */nsIFrame*GetPresShellIgnoreScrollFrame(){returnCurrentPresShellState()->mPresShellIgnoreScrollFrame;}/** * Notify the display list builder that we're entering a presshell. * aReferenceFrame should be a frame in the new presshell. * aPointerEventsNoneDoc should be set to true if the frame generating this * document is pointer-events:none. */voidEnterPresShell(constnsIFrame*aReferenceFrame,boolaPointerEventsNoneDoc=false);/** * For print-preview documents, we sometimes need to build display items for * the same frames multiple times in the same presentation, with different * clipping. Between each such batch of items, call * ResetMarkedFramesForDisplayList to make sure that the results of * MarkFramesForDisplayList do not carry over between batches. */voidResetMarkedFramesForDisplayList(constnsIFrame*aReferenceFrame);/** * Notify the display list builder that we're leaving a presshell. */voidLeavePresShell(constnsIFrame*aReferenceFrame,nsDisplayList*aPaintedContents);voidIncrementPresShellPaintCount(PresShell*aPresShell);/** * Returns true if we're currently building a display list that's * directly or indirectly under an nsDisplayTransform. */boolIsInTransform()const{returnmInTransform;}boolInEventsOnly()const{returnmInEventsOnly;}/** * Indicate whether or not we're directly or indirectly under and * nsDisplayTransform or SVG foreignObject. */voidSetInTransform(boolaInTransform){mInTransform=aInTransform;}/** * Returns true if we're currently building a display list that's * under an nsDisplayFilters. */boolIsInFilter()const{returnmInFilter;}/** * Return true if we're currently building a display list for a * nested presshell. */boolIsInSubdocument()const{returnmPresShellStates.Length()>1;}voidSetDisablePartialUpdates(boolaDisable){mDisablePartialUpdates=aDisable;}boolDisablePartialUpdates()const{returnmDisablePartialUpdates;}voidSetPartialBuildFailed(boolaFailed){mPartialBuildFailed=aFailed;}boolPartialBuildFailed()const{returnmPartialBuildFailed;}boolIsInActiveDocShell()const{returnmIsInActiveDocShell;}voidSetInActiveDocShell(boolaActive){mIsInActiveDocShell=aActive;}/** * Return true if we're currently building a display list for the presshell * of a chrome document, or if we're building the display list for a popup. */boolIsInChromeDocumentOrPopup()const{returnmIsInChromePresContext||mIsBuildingForPopup;}/** * @return true if images have been set to decode synchronously. */boolShouldSyncDecodeImages()const{returnmSyncDecodeImages;}/** * Indicates whether we should synchronously decode images. If true, we decode * and draw whatever image data has been loaded. If false, we just draw * whatever has already been decoded. */voidSetSyncDecodeImages(boolaSyncDecodeImages){mSyncDecodeImages=aSyncDecodeImages;}nsDisplayTableBackgroundSet*SetTableBackgroundSet(nsDisplayTableBackgroundSet*aTableSet){nsDisplayTableBackgroundSet*old=mTableBackgroundSet;mTableBackgroundSet=aTableSet;returnold;}nsDisplayTableBackgroundSet*GetTableBackgroundSet()const{returnmTableBackgroundSet;}voidFreeClipChains();/* * Frees the temporary display items created during merging. */voidFreeTemporaryItems();/** * Helper method to generate background painting flags based on the * information available in the display list builder. */uint32_tGetBackgroundPaintFlags();/** * Helper method to generate nsImageRenderer flags based on the information * available in the display list builder. */uint32_tGetImageRendererFlags()const;/** * Helper method to generate image decoding flags based on the * information available in the display list builder. */uint32_tGetImageDecodeFlags()const;/** * Subtracts aRegion from *aVisibleRegion. We avoid letting * aVisibleRegion become overcomplex by simplifying it if necessary. */voidSubtractFromVisibleRegion(nsRegion*aVisibleRegion,constnsRegion&aRegion);/** * Mark the frames in aFrames to be displayed if they intersect aDirtyRect * (which is relative to aDirtyFrame). If the frames have placeholders * that might not be displayed, we mark the placeholders and their ancestors * to ensure that display list construction descends into them * anyway. nsDisplayListBuilder will take care of unmarking them when it is * destroyed. */voidMarkFramesForDisplayList(nsIFrame*aDirtyFrame,constnsFrameList&aFrames);voidMarkFrameForDisplay(nsIFrame*aFrame,constnsIFrame*aStopAtFrame);voidMarkFrameForDisplayIfVisible(nsIFrame*aFrame,constnsIFrame*aStopAtFrame);voidAddFrameMarkedForDisplayIfVisible(nsIFrame*aFrame);voidClearFixedBackgroundDisplayData();/** * Mark all child frames that Preserve3D() as needing display. * Because these frames include transforms set on their parent, dirty rects * for intermediate frames may be empty, yet child frames could still be * visible. */voidMarkPreserve3DFramesForDisplayList(nsIFrame*aDirtyFrame);/** * Returns true if we need to descend into this frame when building * the display list, even though it doesn't intersect the dirty * rect, because it may have out-of-flows that do so. */boolShouldDescendIntoFrame(nsIFrame*aFrame,boolaVisible)const{returnaFrame->HasAnyStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)||(aVisible&&aFrame->ForceDescendIntoIfVisible())||GetIncludeAllOutOfFlows();}/** * Returns the list of registered theme geometries. */nsTArray<nsIWidget::ThemeGeometry>GetThemeGeometries()const{nsTArray<nsIWidget::ThemeGeometry>geometries;for(constauto&data:mThemeGeometries.Values()){geometries.AppendElements(*data);}returngeometries;}/** * Notifies the builder that a particular themed widget exists * at the given rectangle within the currently built display list. * For certain appearance values (currently only StyleAppearance::Toolbar and * StyleAppearance::WindowTitlebar) this gets called during every display list * construction, for every themed widget of the right type within the * display list, except for themed widgets which are transformed or have * effects applied to them (e.g. CSS opacity or filters). * * @param aWidgetType the -moz-appearance value for the themed widget * @param aItem the item associated with the theme geometry * @param aRect the device-pixel rect relative to the widget's displayRoot * for the themed widget */voidRegisterThemeGeometry(uint8_taWidgetType,nsDisplayItem*aItem,constLayoutDeviceIntRect&aRect){if(!mIsPaintingToWindow){return;}nsTArray<nsIWidget::ThemeGeometry>*geometries=mThemeGeometries.GetOrInsertNew(aItem);geometries->AppendElement(nsIWidget::ThemeGeometry(aWidgetType,aRect));}/** * Removes theme geometries associated with the given display item |aItem|. */voidUnregisterThemeGeometry(nsDisplayItem*aItem){mThemeGeometries.Remove(aItem);}/** * Adjusts mWindowDraggingRegion to take into account aFrame. If aFrame's * -moz-window-dragging value is |drag|, its border box is added to the * collected dragging region; if the value is |no-drag|, the border box is * subtracted from the region; if the value is |default|, that frame does * not influence the window dragging region. */voidAdjustWindowDraggingRegion(nsIFrame*aFrame);LayoutDeviceIntRegionGetWindowDraggingRegion()const;voidRemoveModifiedWindowRegions();voidClearRetainedWindowRegions();constnsTHashMap<nsPtrHashKey<dom::RemoteBrowser>,dom::EffectsInfo>&GetEffectUpdates()const{returnmEffectsUpdates;}voidAddEffectUpdate(dom::RemoteBrowser*aBrowser,dom::EffectsInfoaUpdate){mEffectsUpdates.InsertOrUpdate(aBrowser,aUpdate);}/** * Allocate memory in our arena. It will only be freed when this display list * builder is destroyed. This memory holds nsDisplayItems and * DisplayItemClipChain objects. * * Destructors are called as soon as the item is no longer used. */void*Allocate(size_taSize,DisplayListArenaObjectIdaId){returnmPool.Allocate(aId,aSize);}void*Allocate(size_taSize,DisplayItemTypeaType){static_assert(size_t(DisplayItemType::TYPE_ZERO)==size_t(DisplayListArenaObjectId::CLIPCHAIN),"");#define DECLARE_DISPLAY_ITEM_TYPE(name_, ...) \ static_assert(size_t(DisplayItemType::TYPE_##name_) == \ size_t(DisplayListArenaObjectId::name_), \ "");#include"nsDisplayItemTypesList.h"#undef DECLARE_DISPLAY_ITEM_TYPEreturnAllocate(aSize,DisplayListArenaObjectId(size_t(aType)));}voidDestroy(DisplayListArenaObjectIdaId,void*aPtr){returnmPool.Free(aId,aPtr);}voidDestroy(DisplayItemTypeaType,void*aPtr){returnDestroy(DisplayListArenaObjectId(size_t(aType)),aPtr);}/** * Allocate a new ActiveScrolledRoot in the arena. Will be cleaned up * automatically when the arena goes away. */ActiveScrolledRoot*AllocateActiveScrolledRoot(constActiveScrolledRoot*aParent,nsIScrollableFrame*aScrollableFrame);/** * Allocate a new DisplayItemClipChain object in the arena. Will be cleaned * up automatically when the arena goes away. */constDisplayItemClipChain*AllocateDisplayItemClipChain(constDisplayItemClip&aClip,constActiveScrolledRoot*aASR,constDisplayItemClipChain*aParent);/** * Intersect two clip chains, allocating the new clip chain items in this * builder's arena. The result is parented to aAncestor, and no intersections * happen past aAncestor's ASR. * That means aAncestor has to be living in this builder's arena already. * aLeafClip1 and aLeafClip2 only need to outlive the call to this function, * their values are copied into the newly-allocated intersected clip chain * and this function does not hold on to any pointers to them. */constDisplayItemClipChain*CreateClipChainIntersection(constDisplayItemClipChain*aAncestor,constDisplayItemClipChain*aLeafClip1,constDisplayItemClipChain*aLeafClip2);/** * Clone the supplied clip chain's chain items into this builder's arena. */constDisplayItemClipChain*CopyWholeChain(constDisplayItemClipChain*aClipChain);/** * Returns a new clip chain containing an intersection of all clips of * |aClipChain| up to and including |aASR|. * If there is no clip, returns nullptr. */constDisplayItemClipChain*FuseClipChainUpTo(constDisplayItemClipChain*aClipChain,constActiveScrolledRoot*aASR);constActiveScrolledRoot*GetFilterASR()const{returnmFilterASR;}/** * Merges the display items in |aMergedItems| and returns a new temporary * display item. * The display items in |aMergedItems| have to be mergeable with each other. */nsDisplayWrapList*MergeItems(nsTArray<nsDisplayWrapList*>&aItems);/** * A helper class used to temporarily set nsDisplayListBuilder properties for * building display items. * aVisibleRect and aDirtyRect are relative to aForChild. */classAutoBuildingDisplayList{public:AutoBuildingDisplayList(nsDisplayListBuilder*aBuilder,nsIFrame*aForChild,constnsRect&aVisibleRect,constnsRect&aDirtyRect):AutoBuildingDisplayList(aBuilder,aForChild,aVisibleRect,aDirtyRect,aForChild->IsTransformed()){}AutoBuildingDisplayList(nsDisplayListBuilder*aBuilder,nsIFrame*aForChild,constnsRect&aVisibleRect,constnsRect&aDirtyRect,constboolaIsTransformed);voidSetReferenceFrameAndCurrentOffset(constnsIFrame*aFrame,constnsPoint&aOffset){mBuilder->mCurrentReferenceFrame=aFrame;mBuilder->mCurrentOffsetToReferenceFrame=aOffset;}voidSetAdditionalOffset(constnsPoint&aOffset){MOZ_ASSERT(!mBuilder->mAdditionalOffset);mBuilder->mAdditionalOffset=Some(aOffset);mBuilder->mCurrentOffsetToReferenceFrame+=aOffset;}boolIsAnimatedGeometryRoot()const{returnmCurrentAGRState==AGR_YES;}voidRestoreBuildingInvisibleItemsValue(){mBuilder->mBuildingInvisibleItems=mPrevBuildingInvisibleItems;}~AutoBuildingDisplayList(){mBuilder->mCurrentFrame=mPrevFrame;mBuilder->mCurrentReferenceFrame=mPrevReferenceFrame;mBuilder->mCurrentOffsetToReferenceFrame=mPrevOffset;mBuilder->mVisibleRect=mPrevVisibleRect;mBuilder->mDirtyRect=mPrevDirtyRect;mBuilder->mCurrentAGR=mPrevAGR;mBuilder->mAncestorHasApzAwareEventHandler=mPrevAncestorHasApzAwareEventHandler;mBuilder->mBuildingInvisibleItems=mPrevBuildingInvisibleItems;mBuilder->mInInvalidSubtree=mPrevInInvalidSubtree;mBuilder->mAdditionalOffset=mPrevAdditionalOffset;mBuilder->mCompositorHitTestInfo=mPrevCompositorHitTestInfo;}private:nsDisplayListBuilder*mBuilder;AGRStatemCurrentAGRState;constnsIFrame*mPrevFrame;constnsIFrame*mPrevReferenceFrame;nsPointmPrevOffset;Maybe<nsPoint>mPrevAdditionalOffset;nsRectmPrevVisibleRect;nsRectmPrevDirtyRect;RefPtr<AnimatedGeometryRoot>mPrevAGR;gfx::CompositorHitTestInfomPrevCompositorHitTestInfo;boolmPrevAncestorHasApzAwareEventHandler;boolmPrevBuildingInvisibleItems;boolmPrevInInvalidSubtree;};/** * A helper class to temporarily set the value of mInTransform. */classAutoInTransformSetter{public:AutoInTransformSetter(nsDisplayListBuilder*aBuilder,boolaInTransform):mBuilder(aBuilder),mOldValue(aBuilder->mInTransform){aBuilder->mInTransform=aInTransform;}~AutoInTransformSetter(){mBuilder->mInTransform=mOldValue;}private:nsDisplayListBuilder*mBuilder;boolmOldValue;};classAutoInEventsOnly{public:AutoInEventsOnly(nsDisplayListBuilder*aBuilder,boolaInEventsOnly):mBuilder(aBuilder),mOldValue(aBuilder->mInEventsOnly){aBuilder->mInEventsOnly|=aInEventsOnly;}~AutoInEventsOnly(){mBuilder->mInEventsOnly=mOldValue;}private:nsDisplayListBuilder*mBuilder;boolmOldValue;};/** * A helper class to temporarily set the value of mFilterASR and * mInFilter. */classAutoEnterFilter{public:AutoEnterFilter(nsDisplayListBuilder*aBuilder,boolaUsingFilter):mBuilder(aBuilder),mOldValue(aBuilder->mFilterASR),mOldInFilter(aBuilder->mInFilter){if(!aBuilder->mFilterASR&&aUsingFilter){aBuilder->mFilterASR=aBuilder->CurrentActiveScrolledRoot();aBuilder->mInFilter=true;}}~AutoEnterFilter(){mBuilder->mFilterASR=mOldValue;mBuilder->mInFilter=mOldInFilter;}private:nsDisplayListBuilder*mBuilder;constActiveScrolledRoot*mOldValue;boolmOldInFilter;};/** * A helper class to temporarily set the value of mCurrentScrollParentId. */classAutoCurrentScrollParentIdSetter{public:AutoCurrentScrollParentIdSetter(nsDisplayListBuilder*aBuilder,ViewIDaScrollId):mBuilder(aBuilder),mOldValue(aBuilder->mCurrentScrollParentId),mOldForceLayer(aBuilder->mForceLayerForScrollParent),mOldContainsNonMinimalDisplayPort(mBuilder->mContainsNonMinimalDisplayPort){// If this AutoCurrentScrollParentIdSetter has the same scrollId as the// previous one on the stack, then that means the scrollframe that// created this isn't actually scrollable and cannot participate in// scroll handoff. We set mCanBeScrollParent to false to indicate this.mCanBeScrollParent=(mOldValue!=aScrollId);aBuilder->mCurrentScrollParentId=aScrollId;aBuilder->mForceLayerForScrollParent=false;aBuilder->mContainsNonMinimalDisplayPort=false;}boolShouldForceLayerForScrollParent()const{// Only scrollframes participating in scroll handoff can be forced to// layerizereturnmCanBeScrollParent&&mBuilder->mForceLayerForScrollParent;}boolGetContainsNonMinimalDisplayPort()const{// Only for scrollframes participating in scroll handoff can we return// true.returnmCanBeScrollParent&&mBuilder->mContainsNonMinimalDisplayPort;}~AutoCurrentScrollParentIdSetter(){mBuilder->mCurrentScrollParentId=mOldValue;if(mCanBeScrollParent){// If this flag is set, caller code is responsible for having dealt// with the current value of mBuilder->mForceLayerForScrollParent, so// we can just restore the old value.mBuilder->mForceLayerForScrollParent=mOldForceLayer;}else{// Otherwise we need to keep propagating the force-layerization flag// upwards to the next ancestor scrollframe that does participate in// scroll handoff.mBuilder->mForceLayerForScrollParent|=mOldForceLayer;}mBuilder->mContainsNonMinimalDisplayPort|=mOldContainsNonMinimalDisplayPort;}private:nsDisplayListBuilder*mBuilder;ViewIDmOldValue;boolmOldForceLayer;boolmOldContainsNonMinimalDisplayPort;boolmCanBeScrollParent;};/** * Used to update the current active scrolled root on the display list * builder, and to create new active scrolled roots. */classAutoCurrentActiveScrolledRootSetter{public:explicitAutoCurrentActiveScrolledRootSetter(nsDisplayListBuilder*aBuilder):mBuilder(aBuilder),mSavedActiveScrolledRoot(aBuilder->mCurrentActiveScrolledRoot),mContentClipASR(aBuilder->ClipState().GetContentClipASR()),mDescendantsStartIndex(aBuilder->mActiveScrolledRoots.Length()),mUsed(false){}~AutoCurrentActiveScrolledRootSetter(){mBuilder->mCurrentActiveScrolledRoot=mSavedActiveScrolledRoot;}voidSetCurrentActiveScrolledRoot(constActiveScrolledRoot*aActiveScrolledRoot);voidEnterScrollFrame(nsIScrollableFrame*aScrollableFrame){MOZ_ASSERT(!mUsed);ActiveScrolledRoot*asr=mBuilder->AllocateActiveScrolledRoot(mBuilder->mCurrentActiveScrolledRoot,aScrollableFrame);mBuilder->mCurrentActiveScrolledRoot=asr;mUsed=true;}voidInsertScrollFrame(nsIScrollableFrame*aScrollableFrame);private:nsDisplayListBuilder*mBuilder;/** * The builder's mCurrentActiveScrolledRoot at construction time which * needs to be restored at destruction time. */constActiveScrolledRoot*mSavedActiveScrolledRoot;/** * If there's a content clip on the builder at construction time, then * mContentClipASR is that content clip's ASR, otherwise null. The * assumption is that the content clip doesn't get relaxed while this * object is on the stack. */constActiveScrolledRoot*mContentClipASR;/** * InsertScrollFrame needs to mutate existing ASRs (those that were * created while this object was on the stack), and mDescendantsStartIndex * makes it easier to skip ASRs that were created in the past. */size_tmDescendantsStartIndex;/** * Flag to make sure that only one of SetCurrentActiveScrolledRoot / * EnterScrollFrame / InsertScrollFrame is called per instance of this * class. */boolmUsed;};/** * Keeps track of the innermost ASR that can be used as the ASR for a * container item that wraps all items that were created while this * object was on the stack. * The rule is: all child items of the container item need to have * clipped bounds with respect to the container ASR. */classAutoContainerASRTracker{public:explicitAutoContainerASRTracker(nsDisplayListBuilder*aBuilder):mBuilder(aBuilder),mSavedContainerASR(aBuilder->mCurrentContainerASR){mBuilder->mCurrentContainerASR=ActiveScrolledRoot::PickDescendant(mBuilder->ClipState().GetContentClipASR(),mBuilder->mCurrentActiveScrolledRoot);}constActiveScrolledRoot*GetContainerASR(){returnmBuilder->mCurrentContainerASR;}~AutoContainerASRTracker(){mBuilder->mCurrentContainerASR=ActiveScrolledRoot::PickAncestor(mBuilder->mCurrentContainerASR,mSavedContainerASR);}private:nsDisplayListBuilder*mBuilder;constActiveScrolledRoot*mSavedContainerASR;};/** * A helper class to temporarily set the value of mCurrentScrollbarTarget * and mCurrentScrollbarFlags. */classAutoCurrentScrollbarInfoSetter{public:AutoCurrentScrollbarInfoSetter(nsDisplayListBuilder*aBuilder,ViewIDaScrollTargetID,constMaybe<layers::ScrollDirection>&aScrollbarDirection,boolaWillHaveLayer):mBuilder(aBuilder){aBuilder->mIsBuildingScrollbar=true;aBuilder->mCurrentScrollbarTarget=aScrollTargetID;aBuilder->mCurrentScrollbarDirection=aScrollbarDirection;aBuilder->mCurrentScrollbarWillHaveLayer=aWillHaveLayer;}~AutoCurrentScrollbarInfoSetter(){// No need to restore old values because scrollbars cannot be nested.mBuilder->mIsBuildingScrollbar=false;mBuilder->mCurrentScrollbarTarget=layers::ScrollableLayerGuid::NULL_SCROLL_ID;mBuilder->mCurrentScrollbarDirection.reset();mBuilder->mCurrentScrollbarWillHaveLayer=false;}private:nsDisplayListBuilder*mBuilder;};/** * A helper class to temporarily set mBuildingExtraPagesForPageNum. */classMOZ_RAIIAutoPageNumberSetter{public:AutoPageNumberSetter(nsDisplayListBuilder*aBuilder,constuint8_taPageNum):mBuilder(aBuilder),mOldPageNum(aBuilder->GetBuildingExtraPagesForPageNum()){mBuilder->SetBuildingExtraPagesForPageNum(aPageNum);}~AutoPageNumberSetter(){mBuilder->SetBuildingExtraPagesForPageNum(mOldPageNum);}private:nsDisplayListBuilder*mBuilder;uint8_tmOldPageNum;};/** * A helper class to track current effective transform for items. * * For frames that is Combines3DTransformWithAncestors(), we need to * apply all transforms of ancestors on the same preserves3D chain * on the bounds of current frame to the coordination of the 3D * context root. The 3D context root computes it's bounds from * these transformed bounds. */classAutoAccumulateTransform{public:explicitAutoAccumulateTransform(nsDisplayListBuilder*aBuilder):mBuilder(aBuilder),mSavedTransform(aBuilder->mPreserves3DCtx.mAccumulatedTransform){}~AutoAccumulateTransform(){mBuilder->mPreserves3DCtx.mAccumulatedTransform=mSavedTransform;}voidAccumulate(constgfx::Matrix4x4&aTransform){mBuilder->mPreserves3DCtx.mAccumulatedTransform=aTransform*mBuilder->mPreserves3DCtx.mAccumulatedTransform;}constgfx::Matrix4x4&GetCurrentTransform(){returnmBuilder->mPreserves3DCtx.mAccumulatedTransform;}voidStartRoot(){mBuilder->mPreserves3DCtx.mAccumulatedTransform=gfx::Matrix4x4();}private:nsDisplayListBuilder*mBuilder;gfx::Matrix4x4mSavedTransform;};/** * A helper class to collect bounds rects of descendants. * * For a 3D context root, it's bounds is computed from the bounds of * descendants. If we transform bounds frame by frame applying * transforms, the bounds may turn to empty for any singular * transform on the path, but it is not empty for the accumulated * transform. */classAutoAccumulateRect{public:explicitAutoAccumulateRect(nsDisplayListBuilder*aBuilder):mBuilder(aBuilder),mSavedRect(aBuilder->mPreserves3DCtx.mAccumulatedRect){aBuilder->mPreserves3DCtx.mAccumulatedRect=nsRect();aBuilder->mPreserves3DCtx.mAccumulatedRectLevels++;}~AutoAccumulateRect(){mBuilder->mPreserves3DCtx.mAccumulatedRect=mSavedRect;mBuilder->mPreserves3DCtx.mAccumulatedRectLevels--;}private:nsDisplayListBuilder*mBuilder;nsRectmSavedRect;};voidAccumulateRect(constnsRect&aRect){mPreserves3DCtx.mAccumulatedRect.UnionRect(mPreserves3DCtx.mAccumulatedRect,aRect);}constnsRect&GetAccumulatedRect(){returnmPreserves3DCtx.mAccumulatedRect;}/** * The level is increased by one for items establishing 3D rendering * context and starting a new accumulation. */intGetAccumulatedRectLevels(){returnmPreserves3DCtx.mAccumulatedRectLevels;}structOutOfFlowDisplayData{OutOfFlowDisplayData(constDisplayItemClipChain*aContainingBlockClipChain,constDisplayItemClipChain*aCombinedClipChain,constActiveScrolledRoot*aContainingBlockActiveScrolledRoot,constnsRect&aVisibleRect,constnsRect&aDirtyRect):mContainingBlockClipChain(aContainingBlockClipChain),mCombinedClipChain(aCombinedClipChain),mContainingBlockActiveScrolledRoot(aContainingBlockActiveScrolledRoot),mVisibleRect(aVisibleRect),mDirtyRect(aDirtyRect){}constDisplayItemClipChain*mContainingBlockClipChain;constDisplayItemClipChain*mCombinedClipChain;// only necessary for the special case of top layerconstActiveScrolledRoot*mContainingBlockActiveScrolledRoot;// If this OutOfFlowDisplayData is associated with the ViewportFrame// of a document that has a resolution (creating separate visual and// layout viewports with their own coordinate spaces), these rects// are in layout coordinates. Similarly, GetVisibleRectForFrame() in// such a case returns a quantity in layout coordinates.nsRectmVisibleRect;nsRectmDirtyRect;staticnsRectComputeVisibleRectForFrame(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constnsRect&aVisibleRect,constnsRect&aDirtyRect,nsRect*aOutDirtyRect);nsRectGetVisibleRectForFrame(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsRect*aDirtyRect){returnComputeVisibleRectForFrame(aBuilder,aFrame,mVisibleRect,mDirtyRect,aDirtyRect);}};NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutOfFlowDisplayDataProperty,OutOfFlowDisplayData)structDisplayListBuildingData{RefPtr<AnimatedGeometryRoot>mModifiedAGR=nullptr;nsRectmDirtyRect;};NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingRect,DisplayListBuildingData)NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingDisplayPortRect,nsRect)staticOutOfFlowDisplayData*GetOutOfFlowData(nsIFrame*aFrame){if(!aFrame->GetParent()){returnnullptr;}returnaFrame->GetParent()->GetProperty(OutOfFlowDisplayDataProperty());}nsPresContext*CurrentPresContext();OutOfFlowDisplayData*GetCurrentFixedBackgroundDisplayData(){auto&displayData=CurrentPresShellState()->mFixedBackgroundDisplayData;returndisplayData?displayData.ptr():nullptr;}/** * Accumulates the bounds of box frames that have moz-appearance * -moz-win-exclude-glass style. Used in setting glass margins on * Windows. * * We set the window opaque region (from which glass margins are computed) * to the intersection of the glass region specified here and the opaque * region computed during painting. So the excluded glass region actually * *limits* the extent of the opaque area reported to Windows. We limit it * so that changes to the computed opaque region (which can vary based on * region optimizations and the placement of UI elements) outside the * -moz-win-exclude-glass area don't affect the glass margins reported to * Windows; changing those margins willy-nilly can cause the Windows 7 glass * haze effect to jump around disconcertingly. */voidAddWindowExcludeGlassRegion(nsIFrame*aFrame,constnsRect&aBounds){mWindowExcludeGlassRegion.Add(aFrame,aBounds);}/** * Returns the window exclude glass region. */nsRegionGetWindowExcludeGlassRegion()const{returnmWindowExcludeGlassRegion.ToRegion();}/** * Accumulates opaque stuff into the window opaque region. */voidAddWindowOpaqueRegion(nsIFrame*aFrame,constnsRect&aBounds){if(IsRetainingDisplayList()){mRetainedWindowOpaqueRegion.Add(aFrame,aBounds);return;}mWindowOpaqueRegion.Or(mWindowOpaqueRegion,aBounds);}/** * Returns the window opaque region built so far. This may be incomplete * since the opaque region is built during layer construction. */constnsRegionGetWindowOpaqueRegion(){returnIsRetainingDisplayList()?mRetainedWindowOpaqueRegion.ToRegion():mWindowOpaqueRegion;}voidSetGlassDisplayItem(nsDisplayItem*aItem);voidClearGlassDisplayItem(){mGlassDisplayItem=nullptr;}nsDisplayItem*GetGlassDisplayItem(){returnmGlassDisplayItem;}boolNeedToForceTransparentSurfaceForItem(nsDisplayItem*aItem);/** * mContainsBlendMode is true if we processed a display item that * has a blend mode attached. We do this so we can insert a * nsDisplayBlendContainer in the parent stacking context. */voidSetContainsBlendMode(boolaContainsBlendMode){mContainsBlendMode=aContainsBlendMode;}boolContainsBlendMode()const{returnmContainsBlendMode;}/** * mContainsBackdropFilter is true if we proccessed a display item that * has a backdrop filter set. We track this so we can insert a * nsDisplayBackdropRootContainer in the stacking context of the nearest * ancestor that forms a backdrop root. */voidSetContainsBackdropFilter(boolaContainsBackdropFilter){mContainsBackdropFilter=aContainsBackdropFilter;}boolContainsBackdropFilter()const{returnmContainsBackdropFilter;}DisplayListClipState&ClipState(){returnmClipState;}constActiveScrolledRoot*CurrentActiveScrolledRoot(){returnmCurrentActiveScrolledRoot;}constActiveScrolledRoot*CurrentAncestorASRStackingContextContents(){returnmCurrentContainerASR;}/** * Add the current frame to the will-change budget if possible and * remeber the outcome. Subsequent calls to IsInWillChangeBudget * will return the same value as return here. */boolAddToWillChangeBudget(nsIFrame*aFrame,constnsSize&aSize);/** * This will add the current frame to the will-change budget the first * time it is seen. On subsequent calls this will return the same * answer. This effectively implements a first-come, first-served * allocation of the will-change budget. */boolIsInWillChangeBudget(nsIFrame*aFrame,constnsSize&aSize);/** * Clears the will-change budget status for the given |aFrame|. * This will also remove the frame from will-change budgets. */voidClearWillChangeBudgetStatus(nsIFrame*aFrame);/** * Removes the given |aFrame| from will-change budgets. */voidRemoveFromWillChangeBudgets(constnsIFrame*aFrame);/** * Clears the will-change budgets. */voidClearWillChangeBudgets();voidEnterSVGEffectsContents(nsIFrame*aEffectsFrame,nsDisplayList*aHoistedItemsStorage);voidExitSVGEffectsContents();boolShouldBuildScrollInfoItemsForHoisting()const;voidAppendNewScrollInfoItemForHoisting(nsDisplayScrollInfoLayer*aScrollInfoItem);/** * A helper class to install/restore nsDisplayListBuilder::mPreserves3DCtx. * * mPreserves3DCtx is used by class AutoAccumulateTransform & * AutoAccumulateRect to passing data between frames in the 3D * context. If a frame create a new 3D context, it should restore * the value of mPreserves3DCtx before returning back to the parent. * This class do it for the users. */classAutoPreserves3DContext{public:explicitAutoPreserves3DContext(nsDisplayListBuilder*aBuilder):mBuilder(aBuilder),mSavedCtx(aBuilder->mPreserves3DCtx){}~AutoPreserves3DContext(){mBuilder->mPreserves3DCtx=mSavedCtx;}private:nsDisplayListBuilder*mBuilder;Preserves3DContextmSavedCtx;};constnsRectGetPreserves3DRect()const{returnmPreserves3DCtx.mVisibleRect;}voidSavePreserves3DRect(){mPreserves3DCtx.mVisibleRect=mVisibleRect;}voidSavePreserves3DAllowAsyncAnimation(boolaValue){mPreserves3DCtx.mAllowAsyncAnimation=aValue;}boolGetPreserves3DAllowAsyncAnimation()const{returnmPreserves3DCtx.mAllowAsyncAnimation;}boolIsBuildingInvisibleItems()const{returnmBuildingInvisibleItems;}voidSetBuildingInvisibleItems(boolaBuildingInvisibleItems){mBuildingInvisibleItems=aBuildingInvisibleItems;}voidSetBuildingExtraPagesForPageNum(uint8_taPageNum){mBuildingExtraPagesForPageNum=aPageNum;}uint8_tGetBuildingExtraPagesForPageNum()const{returnmBuildingExtraPagesForPageNum;}/** * This is a convenience function to ease the transition until AGRs and ASRs * are unified. */AnimatedGeometryRoot*AnimatedGeometryRootForASR(constActiveScrolledRoot*aASR);boolHitTestIsForVisibility()const{returnmVisibleThreshold.isSome();}floatVisibilityThreshold()const{MOZ_DIAGNOSTIC_ASSERT(HitTestIsForVisibility());returnmVisibleThreshold.valueOr(1.0f);}voidSetHitTestIsForVisibility(floataVisibleThreshold){mVisibleThreshold=Some(aVisibleThreshold);}boolShouldBuildAsyncZoomContainer()const{returnmBuildAsyncZoomContainer;}voidUpdateShouldBuildAsyncZoomContainer();voidUpdateShouldBuildBackdropRootContainer();boolShouldRebuildDisplayListDueToPrefChange();/** * Represents a region composed of frame/rect pairs. * WeakFrames are used to track whether a rect still belongs to the region. * Modified frames and rects are removed and re-added to the region if needed. */structWeakFrameRegion{/** * A wrapper to store WeakFrame and the pointer to the underlying frame. * This is needed because WeakFrame does not store the frame pointer after * the frame has been deleted. */structWeakFrameWrapper{explicitWeakFrameWrapper(nsIFrame*aFrame):mWeakFrame(newWeakFrame(aFrame)),mFrame(aFrame){}UniquePtr<WeakFrame>mWeakFrame;void*mFrame;};nsTHashSet<void*>mFrameSet;nsTArray<WeakFrameWrapper>mFrames;nsTArray<pixman_box32_t>mRects;template<typenameRectType>voidAdd(nsIFrame*aFrame,constRectType&aRect){if(mFrameSet.Contains(aFrame)){return;}mFrameSet.Insert(aFrame);mFrames.AppendElement(WeakFrameWrapper(aFrame));mRects.AppendElement(nsRegion::RectToBox(aRect));}voidClear(){mFrameSet.Clear();mFrames.Clear();mRects.Clear();}voidRemoveModifiedFramesAndRects();size_tSizeOfExcludingThis(MallocSizeOf)const;typedefgfx::ArrayView<pixman_box32_t>BoxArrayView;nsRegionToRegion()const{returnnsRegion(BoxArrayView(mRects));}LayoutDeviceIntRegionToLayoutDeviceIntRegion()const{returnLayoutDeviceIntRegion(BoxArrayView(mRects));}};voidAddScrollFrameToNotify(nsIScrollableFrame*aScrollFrame);voidNotifyAndClearScrollFrames();// Helper class to find what link spec (if any) to associate with a frame,// recording it in the builder, and generate the corresponding DisplayItem.// This also takes care of generating a named destination for internal links// if the element has an id or name attribute.classLinkifier{public:Linkifier(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList);~Linkifier(){if(mBuilderToReset){mBuilderToReset->mLinkSpec.Truncate(0);}}voidMaybeAppendLink(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame);private:nsDisplayListBuilder*mBuilderToReset=nullptr;nsDisplayList*mList;};private:boolMarkOutOfFlowFrameForDisplay(nsIFrame*aDirtyFrame,nsIFrame*aFrame,constnsRect&aVisibleRect,constnsRect&aDirtyRect);/** * Returns whether a frame acts as an animated geometry root, optionally * returning the next ancestor to check. */AGRStateIsAnimatedGeometryRoot(nsIFrame*aFrame,bool&aIsAsync,nsIFrame**aParent=nullptr);/** * Returns the nearest ancestor frame to aFrame that is considered to have * (or will have) animated geometry. This can return aFrame. */nsIFrame*FindAnimatedGeometryRootFrameFor(nsIFrame*aFrame,bool&aIsAsync);friendclassnsDisplayCanvasBackgroundImage;friendclassnsDisplayBackgroundImage;friendclassnsDisplayFixedPosition;friendclassnsDisplayPerspective;AnimatedGeometryRoot*FindAnimatedGeometryRootFor(nsDisplayItem*aItem);friendclassnsDisplayItem;friendclassnsDisplayOwnLayer;friendstructRetainedDisplayListBuilder;AnimatedGeometryRoot*FindAnimatedGeometryRootFor(nsIFrame*aFrame);AnimatedGeometryRoot*WrapAGRForFrame(nsIFrame*aAnimatedGeometryRoot,boolaIsAsync,AnimatedGeometryRoot*aParent=nullptr);nsTHashMap<nsIFrame*,RefPtr<AnimatedGeometryRoot>>mFrameToAnimatedGeometryRootMap;/** * Add the current frame to the AGR budget if possible and remember * the outcome. Subsequent calls will return the same value as * returned here. */boolAddToAGRBudget(nsIFrame*aFrame);structPresShellState{PresShell*mPresShell;#ifdef DEBUGMaybe<nsAutoLayoutPhase>mAutoLayoutPhase;#endifMaybe<OutOfFlowDisplayData>mFixedBackgroundDisplayData;uint32_tmFirstFrameMarkedForDisplay;uint32_tmFirstFrameWithOOFData;boolmIsBackgroundOnly;// This is a per-document flag turning off event handling for all content// in the document, and is set when we enter a subdocument for a pointer-// events:none frame.boolmInsidePointerEventsNoneDoc;boolmTouchEventPrefEnabledDoc;nsIFrame*mPresShellIgnoreScrollFrame;};PresShellState*CurrentPresShellState(){NS_ASSERTION(mPresShellStates.Length()>0,"Someone forgot to enter a presshell");return&mPresShellStates[mPresShellStates.Length()-1];}voidAddSizeOfExcludingThis(nsWindowSizes&)const;structFrameWillChangeBudget{FrameWillChangeBudget():mPresContext(nullptr),mUsage(0){}FrameWillChangeBudget(constnsPresContext*aPresContext,uint32_taUsage):mPresContext(aPresContext),mUsage(aUsage){}constnsPresContext*mPresContext;uint32_tmUsage;};nsIFrame*constmReferenceFrame;nsIFrame*mIgnoreScrollFrame;usingArena=nsPresArena<32768,DisplayListArenaObjectId,size_t(DisplayListArenaObjectId::COUNT)>;ArenamPool;AutoTArray<PresShellState,8>mPresShellStates;AutoTArray<nsIFrame*,400>mFramesMarkedForDisplay;AutoTArray<nsIFrame*,40>mFramesMarkedForDisplayIfVisible;AutoTArray<nsIFrame*,20>mFramesWithOOFData;nsClassHashtable<nsPtrHashKey<nsDisplayItem>,nsTArray<nsIWidget::ThemeGeometry>>mThemeGeometries;DisplayListClipStatemClipState;constActiveScrolledRoot*mCurrentActiveScrolledRoot;constActiveScrolledRoot*mCurrentContainerASR;// mCurrentFrame is the frame that we're currently calling (or about to call)// BuildDisplayList on.constnsIFrame*mCurrentFrame;// The reference frame for mCurrentFrame.constnsIFrame*mCurrentReferenceFrame;// The offset from mCurrentFrame to mCurrentReferenceFrame.nsPointmCurrentOffsetToReferenceFrame;Maybe<nsPoint>mAdditionalOffset;RefPtr<AnimatedGeometryRoot>mRootAGR;RefPtr<AnimatedGeometryRoot>mCurrentAGR;// will-change budget trackertypedefuint32_tDocumentWillChangeBudget;nsTHashMap<nsPtrHashKey<constnsPresContext>,DocumentWillChangeBudget>mDocumentWillChangeBudgets;// Any frame listed in this set is already counted in the budget// and thus is in-budget.nsTHashMap<nsPtrHashKey<constnsIFrame>,FrameWillChangeBudget>mFrameWillChangeBudgets;uint8_tmBuildingExtraPagesForPageNum;// Area of animated geometry root budget already allocateduint32_tmUsedAGRBudget;// Set of frames already counted in budgetnsTHashSet<nsIFrame*>mAGRBudgetSet;nsTHashMap<nsPtrHashKey<dom::RemoteBrowser>,dom::EffectsInfo>mEffectsUpdates;// Relative to mCurrentFrame.nsRectmVisibleRect;nsRectmDirtyRect;// Tracked regions used for retained display list.WeakFrameRegionmWindowExcludeGlassRegion;WeakFrameRegionmRetainedWindowDraggingRegion;WeakFrameRegionmRetainedWindowNoDraggingRegion;// Window opaque region is calculated during layer building.WeakFrameRegionmRetainedWindowOpaqueRegion;// Optimized versions for non-retained display list.LayoutDeviceIntRegionmWindowDraggingRegion;LayoutDeviceIntRegionmWindowNoDraggingRegion;nsRegionmWindowOpaqueRegion;// The display item for the Windows window glass background, if any// Set during full display list builds or during display list merging only,// partial display list builds don't touch this.nsDisplayItem*mGlassDisplayItem;// If we've encountered a glass item yet, only used during partial display// list builds.boolmHasGlassItemDuringPartial;nsIFrame*mCaretFrame;nsRectmCaretRect;// A temporary list that we append scroll info items to while building// display items for the contents of frames with SVG effects.// Only non-null when ShouldBuildScrollInfoItemsForHoisting() is true.// This is a pointer and not a real nsDisplayList value because the// nsDisplayList class is defined below this class, so we can't use it here.nsDisplayList*mScrollInfoItemsForHoisting;nsTArray<RefPtr<ActiveScrolledRoot>>mActiveScrolledRoots;std::unordered_set<constDisplayItemClipChain*,DisplayItemClipChainHasher,DisplayItemClipChainEqualer>mClipDeduplicator;DisplayItemClipChain*mFirstClipChainToDestroy;nsTArray<nsDisplayItem*>mTemporaryItems;nsDisplayListBuilderModemMode;nsDisplayTableBackgroundSet*mTableBackgroundSet;ViewIDmCurrentScrollParentId;ViewIDmCurrentScrollbarTarget;Maybe<layers::ScrollDirection>mCurrentScrollbarDirection;Preserves3DContextmPreserves3DCtx;nsTArray<nsIFrame*>mSVGEffectsFrames;// When we are inside a filter, the current ASR at the time we entered the// filter. Otherwise nullptr.constActiveScrolledRoot*mFilterASR;std::unordered_set<nsIScrollableFrame*>mScrollFramesToNotify;nsCStringmLinkSpec;// Destination of link currently being emitted, if any.nsTHashSet<nsCString>mDestinations;// Destination names emitted.boolmContainsBlendMode;boolmIsBuildingScrollbar;boolmCurrentScrollbarWillHaveLayer;boolmBuildCaret;boolmRetainingDisplayList;boolmPartialUpdate;boolmIgnoreSuppression;boolmIncludeAllOutOfFlows;boolmDescendIntoSubdocuments;boolmSelectedFramesOnly;boolmAllowMergingAndFlattening;// True when we're building a display list that's directly or indirectly// under an nsDisplayTransformboolmInTransform;boolmInEventsOnly;boolmInFilter;boolmInPageSequence;boolmIsInChromePresContext;boolmSyncDecodeImages;boolmIsPaintingToWindow;boolmUseHighQualityScaling;boolmIsPaintingForWebRender;boolmIsCompositingCheap;boolmAncestorHasApzAwareEventHandler;// True when the first async-scrollable scroll frame for which we build a// display list has a display port. An async-scrollable scroll frame is one// which WantsAsyncScroll().boolmHaveScrollableDisplayPort;boolmWindowDraggingAllowed;boolmIsBuildingForPopup;boolmForceLayerForScrollParent;boolmContainsNonMinimalDisplayPort;boolmAsyncPanZoomEnabled;boolmBuildingInvisibleItems;boolmIsBuilding;boolmInInvalidSubtree;boolmBuildCompositorHitTestInfo;boolmDisablePartialUpdates;boolmPartialBuildFailed;boolmIsInActiveDocShell;boolmBuildAsyncZoomContainer;boolmContainsBackdropFilter;boolmIsRelativeToLayoutViewport;boolmUseOverlayScrollbars;boolmAlwaysLayerizeScrollbars;Maybe<float>mVisibleThreshold;gfx::CompositorHitTestInfomCompositorHitTestInfo;};classnsDisplayItem;classnsPaintedDisplayItem;classnsDisplayList;classRetainedDisplayList;// All types are defined in nsDisplayItemTypes.h#define NS_DISPLAY_DECL_NAME(n, e) \ const char* Name() const override { return n; } \ constexpr static DisplayItemType ItemType() { return DisplayItemType::e; } \ \ private: \ void* operator new(size_t aSize, nsDisplayListBuilder* aBuilder) { \ return aBuilder->Allocate(aSize, DisplayItemType::e); \ } \ \ template <typename T, typename F, typename... Args> \ friend T* mozilla::MakeDisplayItemWithIndex( \ nsDisplayListBuilder* aBuilder, F* aFrame, const uint16_t aIndex, \ Args&&... aArgs); \ \ public:#define NS_DISPLAY_ALLOW_CLONING() \ template <typename T> \ friend T* mozilla::MakeClone(nsDisplayListBuilder* aBuilder, \ const T* aItem); \ \ nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override { \ return MakeClone(aBuilder, this); \ }template<typenameT>MOZ_ALWAYS_INLINET*MakeClone(nsDisplayListBuilder*aBuilder,constT*aItem){static_assert(std::is_base_of<nsDisplayWrapList,T>::value,"Display item type should be derived from nsDisplayWrapList");T*item=new(aBuilder)T(aBuilder,*aItem);item->SetType(T::ItemType());returnitem;}#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLEDvoidAssertUniqueItem(nsDisplayItem*aItem);#endif/** * Returns true, if a display item of given |aType| needs to be built within * opacity:0 container. */boolShouldBuildItemForEvents(constDisplayItemTypeaType);/** * Initializes the hit test information of |aItem| if the item type supports it. */voidInitializeHitTestInfo(nsDisplayListBuilder*aBuilder,nsPaintedDisplayItem*aItem,constDisplayItemTypeaType);template<typenameT,typenameF,typename...Args>MOZ_ALWAYS_INLINET*MakeDisplayItemWithIndex(nsDisplayListBuilder*aBuilder,F*aFrame,constuint16_taIndex,Args&&...aArgs){static_assert(std::is_base_of<nsDisplayItem,T>::value,"Display item type should be derived from nsDisplayItem");static_assert(std::is_base_of<nsIFrame,F>::value,"Frame type should be derived from nsIFrame");constDisplayItemTypetype=T::ItemType();if(aBuilder->InEventsOnly()&&!ShouldBuildItemForEvents(type)){// This item is not needed for events.returnnullptr;}T*item=new(aBuilder)T(aBuilder,aFrame,std::forward<Args>(aArgs)...);if(type!=DisplayItemType::TYPE_GENERIC){item->SetType(type);}item->SetPerFrameIndex(aIndex);item->SetExtraPageForPageNum(aBuilder->GetBuildingExtraPagesForPageNum());nsPaintedDisplayItem*paintedItem=item->AsPaintedDisplayItem();if(paintedItem){InitializeHitTestInfo(aBuilder,paintedItem,type);}if(aBuilder->InInvalidSubtree()||item->FrameForInvalidation()->IsFrameModified()){item->SetModifiedFrame(true);}#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLEDif(aBuilder->IsRetainingDisplayList()&&aBuilder->IsBuilding()){AssertUniqueItem(item);}// Verify that InInvalidSubtree matches invalidation frame's modified state.if(aBuilder->InInvalidSubtree()){MOZ_DIAGNOSTIC_ASSERT(AnyContentAncestorModified(item->FrameForInvalidation()));}DebugOnly<bool>isContainerType=(GetDisplayItemFlagsForType(type)&TYPE_IS_CONTAINER);MOZ_ASSERT(item->HasChildren()==isContainerType,"Container items must have container display item flag set.");#endifreturnitem;}template<typenameT,typenameF,typename...Args>MOZ_ALWAYS_INLINET*MakeDisplayItem(nsDisplayListBuilder*aBuilder,F*aFrame,Args&&...aArgs){returnMakeDisplayItemWithIndex<T>(aBuilder,aFrame,0,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. */classnsDisplayItemLink{// This is never instantiated directly, so no need to count constructors and// destructors.protected:nsDisplayItemLink():mAbove(nullptr){}nsDisplayItemLink(constnsDisplayItemLink&):mAbove(nullptr){}~nsDisplayItemLink(){MOZ_RELEASE_ASSERT(!mAbove);}nsDisplayItem*mAbove;friendclassnsDisplayList;};/* * 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 * storing the state needed for display list merging. * * Display items are arena-allocated during display list construction. * * Display items can be containers --- i.e., they can perform hit testing * and painting by recursively traversing a list of child items. * * Display items belong to a list at all times (except temporarily as they * move from one list to another). */classnsDisplayItem:publicnsDisplayItemLink{public:usingLayer=layers::Layer;usingLayerManager=layers::LayerManager;usingStackingContextHelper=layers::StackingContextHelper;usingViewID=layers::ScrollableLayerGuid::ViewID;/** * Downcasts this item to nsPaintedDisplayItem, if possible. */virtualnsPaintedDisplayItem*AsPaintedDisplayItem(){returnnullptr;}virtualconstnsPaintedDisplayItem*AsPaintedDisplayItem()const{returnnullptr;}/** * Downcasts this item to nsDisplayWrapList, if possible. */virtualnsDisplayWrapList*AsDisplayWrapList(){returnnullptr;}virtualconstnsDisplayWrapList*AsDisplayWrapList()const{returnnullptr;}/** * Create a clone of this item. */virtualnsDisplayWrapList*Clone(nsDisplayListBuilder*aBuilder)const{returnnullptr;}/** * Frees the memory allocated for this display item. * The given display list builder must have allocated this display item. */virtualvoidDestroy(nsDisplayListBuilder*aBuilder){constDisplayItemTypetype=GetType();this->~nsDisplayItem();aBuilder->Destroy(type,this);}/** * Returns the frame that this display item was created for. * Never returns null. */inlinensIFrame*Frame()const{MOZ_ASSERT(mFrame,"Trying to use display item after deletion!");returnmFrame;}/** * Called when the display item is prepared for deletion. The display item * should not be used after calling this function. */virtualvoidRemoveFrame(nsIFrame*aFrame){MOZ_ASSERT(aFrame);if(mFrame&&aFrame==mFrame){mFrame=nullptr;SetDeletedFrame();}}/** * A display item can depend on multiple different frames for invalidation. */virtualnsIFrame*GetDependentFrame(){returnnullptr;}/** * Returns the frame that provides the style data, and should * be checked when deciding if this display item can be reused. */virtualnsIFrame*FrameForInvalidation()const{returnFrame();}/** * Returns the printable name of this display item. */virtualconstchar*Name()const=0;/** * Some consecutive items should be rendered together as a unit, e.g., * outlines for the same element. For this, we need a way for items to * identify their type. We use the type for other purposes too. */DisplayItemTypeGetType()const{MOZ_ASSERT(mType!=DisplayItemType::TYPE_ZERO,"Display item should have a valid type!");returnmType;}/** * Pairing this with the Frame() pointer gives a key that * uniquely identifies this display item in the display item tree. */uint32_tGetPerFrameKey()const{// 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>(mExtraPageForPageNum)<<(TYPE_BITS+(sizeof(mPerFrameIndex)*8)))|(static_cast<uint32_t>(mPerFrameIndex)<<TYPE_BITS)|static_cast<uint32_t>(mType);}/** * Returns true if this item was reused during display list merging. */boolIsReused()const{returnmItemFlags.contains(ItemFlag::ReusedItem);}voidSetReused(boolaReused){SetItemFlag(ItemFlag::ReusedItem,aReused);}/** * Returns true if this item can be reused during display list merging. */boolCanBeReused()const{return!mItemFlags.contains(ItemFlag::CantBeReused);}voidSetCantBeReused(){mItemFlags+=ItemFlag::CantBeReused;}boolCanBeCached()const{return!mItemFlags.contains(ItemFlag::CantBeCached);}voidSetCantBeCached(){mItemFlags+=ItemFlag::CantBeCached;}boolIsOldItem()const{return!!mOldList;}/** * Returns true if the frame of this display item is in a modified subtree. */boolHasModifiedFrame()const{returnmItemFlags.contains(ItemFlag::ModifiedFrame);}voidSetModifiedFrame(boolaModified){SetItemFlag(ItemFlag::ModifiedFrame,aModified);}boolHasDeletedFrame()const;/** * Set the nsDisplayList that this item belongs to, and what index it is * within that list. * Temporary state for merging used by RetainedDisplayListBuilder. */voidSetOldListIndex(nsDisplayList*aList,OldListIndexaIndex,uint32_taListKey,uint32_taNestingDepth){#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLEDmOldListKey=aListKey;mOldNestingDepth=aNestingDepth;#endifmOldList=reinterpret_cast<uintptr_t>(aList);mOldListIndex=aIndex;}boolGetOldListIndex(nsDisplayList*aList,uint32_taListKey,OldListIndex*aOutIndex){if(mOldList!=reinterpret_cast<uintptr_t>(aList)){#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLEDMOZ_CRASH_UNSAFE_PRINTF("Item found was in the wrong list! type %d ""(outer type was %d at depth %d, now is %d)",GetPerFrameKey(),mOldListKey,mOldNestingDepth,aListKey);#endifreturnfalse;}*aOutIndex=mOldListIndex;returntrue;}/** * Returns the display list containing the children of this display item. * The children may be in a different coordinate system than this item. */virtualRetainedDisplayList*GetChildren()const{returnnullptr;}boolHasChildren()const{returnGetChildren();}/** * Display items with children may return true here. This causes the * display list iterator to descend into the child display list. */virtualboolShouldFlattenAway(nsDisplayListBuilder*aBuilder){returnfalse;}virtualboolCreatesStackingContextHelper(){returnfalse;}protected:// This is never instantiated directly (it has pure virtual methods), so no// need to count constructors and destructors.nsDisplayItem(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame);nsDisplayItem(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constActiveScrolledRoot*aActiveScrolledRoot);/** * The custom copy-constructor is implemented to prevent copying the saved * state of the item. * This is currently only used when creating temporary items for merging. */nsDisplayItem(nsDisplayListBuilder*aBuilder,constnsDisplayItem&aOther):mFrame(aOther.mFrame),mItemFlags(aOther.mItemFlags),mType(aOther.mType),mExtraPageForPageNum(aOther.mExtraPageForPageNum),mPerFrameIndex(aOther.mPerFrameIndex),mBuildingRect(aOther.mBuildingRect),mReferenceFrame(aOther.mReferenceFrame),mToReferenceFrame(aOther.mToReferenceFrame),mAnimatedGeometryRoot(aOther.mAnimatedGeometryRoot),mActiveScrolledRoot(aOther.mActiveScrolledRoot),mClipChain(aOther.mClipChain),mClip(aOther.mClip){MOZ_COUNT_CTOR(nsDisplayItem);// TODO: It might be better to remove the flags that aren't copied.if(aOther.ForceNotVisible()){mItemFlags+=ItemFlag::ForceNotVisible;}if(aOther.IsSubpixelAADisabled()){mItemFlags+=ItemFlag::DisableSubpixelAA;}if(mFrame->In3DContextAndBackfaceIsHidden()){mItemFlags+=ItemFlag::BackfaceHidden;}if(aOther.Combines3DTransformWithAncestors()){mItemFlags+=ItemFlag::Combines3DTransformWithAncestors;}}virtual~nsDisplayItem(){MOZ_COUNT_DTOR(nsDisplayItem);if(mFrame){mFrame->RemoveDisplayItem(this);}}voidSetType(constDisplayItemTypeaType){mType=aType;}voidSetPerFrameIndex(constuint16_taIndex){mPerFrameIndex=aIndex;}// 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.voidSetExtraPageForPageNum(constuint8_taPageNum){mExtraPageForPageNum=aPageNum;}voidSetDeletedFrame();public:nsDisplayItem()=delete;nsDisplayItem(constnsDisplayItem&)=delete;/** * Roll back side effects carried out by processing the display list. * * @return true if the rollback actually modified anything, to help the caller * decide whether to invalidate cached information about this node. */virtualboolRestoreState(){if(mClipChain==mState.mClipChain&&mClip==mState.mClip&&!mItemFlags.contains(ItemFlag::DisableSubpixelAA)){returnfalse;}mClipChain=mState.mClipChain;mClip=mState.mClip;mItemFlags-=ItemFlag::DisableSubpixelAA;returntrue;}/** * Invalidate cached information that depends on this node's contents, after * a mutation of those contents. * * Specifically, if you mutate an |nsDisplayItem| in a way that would change * the WebRender display list items generated for it, you should call this * method. * * If a |RestoreState| method exists to restore some piece of state, that's a * good indication that modifications to said state should be accompanied by a * call to this method. Opacity flattening's effects on * |nsDisplayBackgroundColor| items are one example. */virtualvoidInvalidateItemCacheEntry(){}structHitTestState{explicitHitTestState()=default;~HitTestState(){NS_ASSERTION(mItemBuffer.Length()==0,"mItemBuffer should have been cleared");}// Handling transform items for preserve 3D frames.boolmInPreserves3D=false;// When hit-testing for visibility, we may hit an fully opaque item in a// nested display list. We want to stop at that point, without looking// further on other items.boolmHitOccludingItem=false;floatmCurrentOpacity=1.0f;AutoTArray<nsDisplayItem*,100>mItemBuffer;};uint8_tGetFlags()const{returnGetDisplayItemFlagsForType(GetType());}virtualboolIsContentful()const{returnGetFlags()&TYPE_IS_CONTENTFUL;}/** * This is called after we've constructed a display list for event handling. * When this is called, we've already ensured that aRect intersects the * item's bounds and that clipping has been taking into account. * * @param aRect the point or rect being tested, relative to the reference * frame. If the width and height are both 1 app unit, it indicates we're * hit testing a point, not a rect. * @param aState must point to a HitTestState. If you don't have one, * just create one with the default constructor and pass it in. * @param aOutFrames each item appends the frame(s) in this display item that * the rect is considered over (if any) to aOutFrames. */virtualvoidHitTest(nsDisplayListBuilder*aBuilder,constnsRect&aRect,HitTestState*aState,nsTArray<nsIFrame*>*aOutFrames){}virtualnsIFrame*StyleFrame()const{returnmFrame;}/** * Compute the used z-index of our frame; returns zero for elements to which * z-index does not apply, and for z-index:auto. * @note This can be overridden, @see nsDisplayWrapList::SetOverrideZIndex. */virtualint32_tZIndex()const;/** * The default bounds is the frame border rect. * @param aSnap *aSnap is set to true if the returned rect will be * snapped to nearest device pixel edges during actual drawing. * It might be set to false and snap anyway, so code computing the set of * pixels affected by this display item needs to round outwards to pixel * boundaries when *aSnap is set to false. * This does not take the item's clipping into account. * @return a rectangle relative to aBuilder->ReferenceFrame() that * contains the area drawn by this display item */virtualnsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)const{*aSnap=false;returnnsRect(ToReferenceFrame(),Frame()->GetSize());}/** * Returns the untransformed bounds of this display item. */virtualnsRectGetUntransformedBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)const{returnGetBounds(aBuilder,aSnap);}virtualnsRegionGetTightBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)const{*aSnap=false;returnnsRegion();}/** * Returns true if nothing will be rendered inside aRect, false if uncertain. * aRect is assumed to be contained in this item's bounds. */virtualboolIsInvisibleInRect(constnsRect&aRect)const{returnfalse;}/** * Returns the result of GetBounds intersected with the item's clip. * The intersection is approximate since rounded corners are not taking into * account. */nsRectGetClippedBounds(nsDisplayListBuilder*aBuilder)const;nsRectGetBorderRect()const{returnnsRect(ToReferenceFrame(),Frame()->GetSize());}nsRectGetPaddingRect()const{returnFrame()->GetPaddingRectRelativeToSelf()+ToReferenceFrame();}nsRectGetContentRect()const{returnFrame()->GetContentRectRelativeToSelf()+ToReferenceFrame();}/** * Checks if the frame(s) owning this display item have been marked as * invalid, and needing repainting. */virtualboolIsInvalid(nsRect&aRect)const{boolresult=mFrame?mFrame->IsInvalid(aRect):false;aRect+=ToReferenceFrame();returnresult;}/** * Creates and initializes an nsDisplayItemGeometry object that retains the * current areas covered by this display item. These need to retain enough * information such that they can be compared against a future nsDisplayItem * of the same type, and determine if repainting needs to happen. * * Subclasses wishing to store more information need to override both this * and ComputeInvalidationRegion, as well as implementing an * nsDisplayItemGeometry subclass. * * The default implementation tracks both the display item bounds, and the * frame's border rect. */virtualnsDisplayItemGeometry*AllocateGeometry(nsDisplayListBuilder*aBuilder){returnnewnsDisplayItemGenericGeometry(this,aBuilder);}/** * Compares an nsDisplayItemGeometry object from a previous paint against the * current item. Computes if the geometry of the item has changed, and the * invalidation area required for correct repainting. * * The existing geometry will have been created from a display item with a * matching GetPerFrameKey()/mFrame pair to the current item. * * The default implementation compares the display item bounds, and the * frame's border rect, and invalidates the entire bounds if either rect * changes. * * @param aGeometry The geometry of the matching display item from the * previous paint. * @param aInvalidRegion Output param, the region to invalidate, or * unchanged if none. */virtualvoidComputeInvalidationRegion(nsDisplayListBuilder*aBuilder,constnsDisplayItemGeometry*aGeometry,nsRegion*aInvalidRegion)const{constnsDisplayItemGenericGeometry*geometry=static_cast<constnsDisplayItemGenericGeometry*>(aGeometry);boolsnap;if(!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder,&snap))||!geometry->mBorderRect.IsEqualInterior(GetBorderRect())){aInvalidRegion->Or(GetBounds(aBuilder,&snap),geometry->mBounds);}}/** * An alternative default implementation of ComputeInvalidationRegion, * that instead invalidates only the changed area between the two items. */voidComputeInvalidationRegionDifference(nsDisplayListBuilder*aBuilder,constnsDisplayItemBoundsGeometry*aGeometry,nsRegion*aInvalidRegion)const{boolsnap;nsRectbounds=GetBounds(aBuilder,&snap);if(!aGeometry->mBounds.IsEqualInterior(bounds)){nscoordradii[8];if(aGeometry->mHasRoundedCorners||Frame()->GetBorderRadii(radii)){aInvalidRegion->Or(aGeometry->mBounds,bounds);}else{aInvalidRegion->Xor(aGeometry->mBounds,bounds);}}}/** * This function is called when an item's list of children has been modified * by RetainedDisplayListBuilder. */virtualvoidInvalidateCachedChildInfo(nsDisplayListBuilder*aBuilder){}virtualvoidAddSizeOfExcludingThis(nsWindowSizes&)const{}/** * @param aSnap set to true if the edges of the rectangles of the opaque * region would be snapped to device pixels when drawing * @return a region of the item that is opaque --- that is, every pixel * that is visible is painted with an opaque * color. This is useful for determining when one piece * of content completely obscures another so that we can do occlusion * culling. * This does not take clipping into account. * This must return a simple region (1 rect) for painting display lists. * It is only allowed to be a complex region for hit testing. */virtualnsRegionGetOpaqueRegion(nsDisplayListBuilder*aBuilder,bool*aSnap)const{*aSnap=false;returnnsRegion();}/** * @return Some(nscolor) if the item is guaranteed to paint every pixel in its * bounds with the same (possibly translucent) color */virtualMaybe<nscolor>IsUniform(nsDisplayListBuilder*aBuilder)const{returnNothing();}/** * @return true if the contents of this item are rendered fixed relative * to the nearest viewport. */virtualboolShouldFixToViewport(nsDisplayListBuilder*aBuilder)const{returnfalse;}/** * Returns true if all layers that can be active should be forced to be * active. Requires setting the pref layers.force-active=true. */staticboolForceActiveLayers();#ifdef MOZ_DUMP_PAINTING/** * Mark this display item as being painted via * FrameLayerBuilder::DrawPaintedLayer. */boolPainted()const{returnmItemFlags.contains(ItemFlag::Painted);}/** * Check if this display item has been painted. */voidSetPainted(){mItemFlags+=ItemFlag::Painted;}#endifvoidSetIsGlassItem(){mItemFlags+=ItemFlag::IsGlassItem;}boolIsGlassItem(){returnmItemFlags.contains(ItemFlag::IsGlassItem);}/** * Function to create the WebRenderCommands. * We should check if the layer state is * active first and have an early return if the layer state is * not active. * * @return true if successfully creating webrender commands. */virtualboolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder){returnfalse;}/** * Updates the provided aLayerData with any APZ-relevant scroll data * that is specific to this display item. This is stuff that would normally * be put on the layer during BuildLayer, but this is only called in * layers-free webrender mode, where we don't have layers. * * This function returns true if and only if it has APZ-relevant scroll data * to provide. Note that the arguments passed in may be nullptr, in which case * the function should still return true if and only if it has APZ-relevant * scroll data, but obviously in this case it can't actually put the * data onto aLayerData, because there isn't one. * * This function assumes that aData and aLayerData will either both be null, * or will both be non-null. The caller is responsible for enforcing this. */virtualboolUpdateScrollData(layers::WebRenderScrollData*aData,layers::WebRenderLayerScrollData*aLayerData){returnfalse;}/** * Returns true if this item needs to have its geometry updated, despite * returning empty invalidation region. */virtualboolNeedsGeometryUpdates()const{returnfalse;}/** * Some items such as those calling into the native themed widget machinery * have to be painted on the content process. In this case it is best to avoid * allocating layers that serializes and forwards the work to the compositor. */virtualboolMustPaintOnContentSide()const{returnfalse;}/** * If this has a child list where the children are in the same coordinate * system as this item (i.e., they have the same reference frame), * return the list. */virtualRetainedDisplayList*GetSameCoordinateSystemChildren()const{returnnullptr;}virtualvoidUpdateBounds(nsDisplayListBuilder*aBuilder){}/** * Do UpdateBounds() for items with frames establishing or extending * 3D rendering context. * * This function is called by UpdateBoundsFor3D() of * nsDisplayTransform(), and it is called by * BuildDisplayListForStackingContext() on transform items * establishing 3D rendering context. * * The bounds of a transform item with the frame establishing 3D * rendering context should be computed by calling * DoUpdateBoundsPreserves3D() on all descendants that participate * the same 3d rendering context. */virtualvoidDoUpdateBoundsPreserves3D(nsDisplayListBuilder*aBuilder){}/** * Returns the building rectangle used by nsDisplayListBuilder when * this item was constructed. */constnsRect&GetBuildingRect()const{returnmBuildingRect;}voidSetBuildingRect(constnsRect&aBuildingRect){if(aBuildingRect==mBuildingRect){// Avoid unnecessary paint rect recompution when the// building rect is staying the same.return;}mBuildingRect=aBuildingRect;}/** * Returns the building rect for the children, relative to their * reference frame. Can be different from mBuildingRect for * nsDisplayTransform, since the reference frame for the children is different * from the reference frame for the item itself. */virtualconstnsRect&GetBuildingRectForChildren()const{returnmBuildingRect;}virtualvoidWriteDebugInfo(std::stringstream&aStream){}nsDisplayItem*GetAbove(){returnmAbove;}/** * Returns the result of aBuilder->ToReferenceFrame(GetUnderlyingFrame()) */constnsPoint&ToReferenceFrame()const{NS_ASSERTION(mFrame,"No frame?");returnmToReferenceFrame;}/** * @return the root of the display list's frame (sub)tree, whose origin * establishes the coordinate system for the display list */constnsIFrame*ReferenceFrame()const{returnmReferenceFrame;}/** * Returns the reference frame for display item children of this item. */virtualconstnsIFrame*ReferenceFrameForChildren()const{returnmReferenceFrame;}AnimatedGeometryRoot*GetAnimatedGeometryRoot()const{MOZ_ASSERT(mAnimatedGeometryRoot,"Must have cached AGR before accessing it!");returnmAnimatedGeometryRoot;}virtualstructAnimatedGeometryRoot*AnimatedGeometryRootForScrollMetadata()const{returnGetAnimatedGeometryRoot();}/** * Checks if this display item (or any children) contains content that might * be rendered with component alpha (e.g. subpixel antialiasing). Returns the * bounds of the area that needs component alpha, or an empty rect if nothing * in the item does. */virtualnsRectGetComponentAlphaBounds(nsDisplayListBuilder*aBuilder)const{returnnsRect();}/** * Disable usage of component alpha. Currently only relevant for items that * have text. */voidDisableComponentAlpha(){mItemFlags+=ItemFlag::DisableSubpixelAA;}boolIsSubpixelAADisabled()const{returnmItemFlags.contains(ItemFlag::DisableSubpixelAA);}/** * Check if we can add async animations to the layer for this display item. */virtualboolCanUseAsyncAnimations(nsDisplayListBuilder*aBuilder){returnfalse;}virtualboolSupportsOptimizingToImage()const{returnfalse;}constDisplayItemClip&GetClip()const{returnmClip?*mClip:DisplayItemClip::NoClip();}voidIntersectClip(nsDisplayListBuilder*aBuilder,constDisplayItemClipChain*aOther,boolaStore);virtualvoidSetActiveScrolledRoot(constActiveScrolledRoot*aActiveScrolledRoot){mActiveScrolledRoot=aActiveScrolledRoot;}constActiveScrolledRoot*GetActiveScrolledRoot()const{returnmActiveScrolledRoot;}virtualvoidSetClipChain(constDisplayItemClipChain*aClipChain,boolaStore);constDisplayItemClipChain*GetClipChain()const{returnmClipChain;}/** * Intersect all clips in our clip chain up to (and including) aASR and set * set the intersection as this item's clip. */voidFuseClipChainUpTo(nsDisplayListBuilder*aBuilder,constActiveScrolledRoot*aASR);boolBackfaceIsHidden()const{returnmItemFlags.contains(ItemFlag::BackfaceHidden);}boolCombines3DTransformWithAncestors()const{returnmItemFlags.contains(ItemFlag::Combines3DTransformWithAncestors);}boolForceNotVisible()const{returnmItemFlags.contains(ItemFlag::ForceNotVisible);}boolIn3DContextAndBackfaceIsHidden()const{returnmItemFlags.contains(ItemFlag::BackfaceHidden)&&mItemFlags.contains(ItemFlag::Combines3DTransformWithAncestors);}boolHasDifferentFrame(constnsDisplayItem*aOther)const{returnmFrame!=aOther->mFrame;}boolHasHitTestInfo()const{returnmItemFlags.contains(ItemFlag::HasHitTestInfo);}boolHasSameTypeAndClip(constnsDisplayItem*aOther)const{returnGetPerFrameKey()==aOther->GetPerFrameKey()&&GetClipChain()==aOther->GetClipChain();}boolHasSameContent(constnsDisplayItem*aOther)const{returnmFrame->GetContent()==aOther->Frame()->GetContent();}virtualvoidNotifyUsed(nsDisplayListBuilder*aBuilder){}virtualMaybe<nsRect>GetClipWithRespectToASR(nsDisplayListBuilder*aBuilder,constActiveScrolledRoot*aASR)const;constnsRect&GetPaintRect()const{returnmBuildingRect;}virtualconstnsRect&GetUntransformedPaintRect()const{returnGetPaintRect();}nsRectGetPaintRect(nsDisplayListBuilder*aBuilder,gfxContext*aCtx);virtualconstHitTestInfo&GetHitTestInfo(){returnHitTestInfo::Empty();}nsIFrame*mFrame;// 8private:enumclassItemFlag:uint16_t{CantBeReused,CantBeCached,DeletedFrame,ModifiedFrame,ReusedItem,#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLEDMergedItem,PreProcessedItem,#endifBackfaceHidden,Combines3DTransformWithAncestors,DisableSubpixelAA,ForceNotVisible,HasHitTestInfo,IsGlassItem,#ifdef MOZ_DUMP_PAINTING// True if this frame has been painted.Painted,#endif};EnumSet<ItemFlag,uint16_t>mItemFlags;// 2DisplayItemTypemType=DisplayItemType::TYPE_ZERO;// 1uint8_tmExtraPageForPageNum=0;// 1uint16_tmPerFrameIndex=0;// 2// 2 free bytes hereOldListIndexmOldListIndex;// 4uintptr_tmOldList=0;// 8// This is the rectangle that nsDisplayListBuilder was using as the visible// rect to decide which items to construct.nsRectmBuildingRect;protected:voidSetItemFlag(ItemFlagaFlag,constboolaValue){if(aValue){mItemFlags+=aFlag;}else{mItemFlags-=aFlag;}}voidSetHasHitTestInfo(){mItemFlags+=ItemFlag::HasHitTestInfo;}// Result of ToReferenceFrame(mFrame), if mFrame is non-nullconstnsIFrame*mReferenceFrame;nsPointmToReferenceFrame;RefPtr<AnimatedGeometryRoot>mAnimatedGeometryRoot;RefPtr<constActiveScrolledRoot>mActiveScrolledRoot;RefPtr<constDisplayItemClipChain>mClipChain;constDisplayItemClip*mClip=nullptr;struct{RefPtr<constDisplayItemClipChain>mClipChain;constDisplayItemClip*mClip;}mState;#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLEDpublic:boolIsMergedItem()const{returnmItemFlags.contains(ItemFlag::MergedItem);}boolIsPreProcessedItem()const{returnmItemFlags.contains(ItemFlag::PreProcessedItem);}voidSetMergedPreProcessed(boolaMerged,boolaPreProcessed){SetItemFlag(ItemFlag::MergedItem,aMerged);SetItemFlag(ItemFlag::PreProcessedItem,aPreProcessed);}uint32_tmOldListKey=0;uint32_tmOldNestingDepth=0;#endif};classnsPaintedDisplayItem:publicnsDisplayItem{public:nsPaintedDisplayItem*AsPaintedDisplayItem()final{returnthis;}constnsPaintedDisplayItem*AsPaintedDisplayItem()constfinal{returnthis;}/** * Stores the given opacity value to be applied when drawing. It is an error * to call this if CanApplyOpacity returned false. */virtualvoidApplyOpacity(nsDisplayListBuilder*aBuilder,floataOpacity,constDisplayItemClipChain*aClip){MOZ_ASSERT(CanApplyOpacity(),"ApplyOpacity is not supported on this type");}/** * Returns true if this display item would return true from ApplyOpacity * without actually applying the opacity. Otherwise returns false. */virtualboolCanApplyOpacity()const{returnfalse;}/** * Returns true if this item supports PaintWithClip, where the clipping * is used directly as the primitive geometry instead of needing an explicit * clip. */virtualboolCanPaintWithClip(constDisplayItemClip&aClip){returnfalse;}/** * Same as |Paint()|, except provides a clip to use the geometry to draw with. * Must not be called unless |CanPaintWithClip()| returned true. */virtualvoidPaintWithClip(nsDisplayListBuilder*aBuilder,gfxContext*aCtx,constDisplayItemClip&aClip){MOZ_ASSERT_UNREACHABLE("PaintWithClip() is not implemented!");}/** * Paint this item to some rendering context. */virtualvoidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)=0;/** * External storage used by |DisplayItemCache| to avoid hashmap lookups. * If an item is reused and has the cache index set, it means that * |DisplayItemCache| has assigned a cache slot for the item. */Maybe<uint16_t>&CacheIndex(){returnmCacheIndex;}voidInvalidateItemCacheEntry()override{// |nsPaintedDisplayItem|s may have |DisplayItemCache| entries// that no longer match after a mutation. The cache will notice// on its own that the entry is no longer in use, and free it.mCacheIndex=Nothing();}constHitTestInfo&GetHitTestInfo()final{returnmHitTestInfo;}voidInitializeHitTestInfo(nsDisplayListBuilder*aBuilder){mHitTestInfo.Initialize(aBuilder,Frame());SetHasHitTestInfo();}protected:nsPaintedDisplayItem(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame):nsPaintedDisplayItem(aBuilder,aFrame,aBuilder->CurrentActiveScrolledRoot()){}nsPaintedDisplayItem(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constActiveScrolledRoot*aActiveScrolledRoot):nsDisplayItem(aBuilder,aFrame,aActiveScrolledRoot){}nsPaintedDisplayItem(nsDisplayListBuilder*aBuilder,constnsPaintedDisplayItem&aOther):nsDisplayItem(aBuilder,aOther),mHitTestInfo(aOther.mHitTestInfo){}protected:HitTestInfomHitTestInfo;Maybe<uint16_t>mCacheIndex;};/** * 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. AppendToBottom() is efficient too. */classnsDisplayList{public:classIterator{public:constexprIterator():mCurrent(nullptr),mEnd(nullptr){}~Iterator()=default;Iterator(constIterator&aOther)=default;Iterator&operator=(constIterator&aOther)=default;explicitIterator(constnsDisplayList*aList):mCurrent(aList->GetBottom()),mEnd(nullptr){}explicitIterator(nsDisplayItem*aStart):mCurrent(aStart),mEnd(nullptr){}Iterator&operator++(){mCurrent=Next();return*this;}nsDisplayItem*operator*(){MOZ_ASSERT(mCurrent);returnmCurrent;}booloperator==(constIterator&aOther)const{returnmCurrent==aOther.mCurrent;}booloperator!=(constIterator&aOther)const{return!operator==(aOther);}boolHasNext()const{returnmCurrent!=nullptr;}nsDisplayItem*GetNext(){MOZ_ASSERT(HasNext());auto*next=mCurrent;operator++();returnnext;}protected:Iterator(nsDisplayItem*aStart,nsDisplayItem*aEnd):mCurrent(aStart),mEnd(aEnd){}nsDisplayItem*Next()const{if(!mCurrent){returnnullptr;}auto*next=mCurrent->GetAbove();if(next==mEnd){returnnullptr;}returnnext;}private:nsDisplayItem*mCurrent;nsDisplayItem*mEnd;};classRangefinal:publicIterator{public:Range(nsDisplayItem*aStart,nsDisplayItem*aEnd):Iterator(aStart,aEnd){}};Iteratorbegin()const{returnIterator(this);}constexprIteratorend()const{returnIterator();}/** * Create an empty list. */nsDisplayList():mLength(0),mForceTransparentSurface(false){mTop=&mSentinel;mSentinel.mAbove=nullptr;}virtual~nsDisplayList(){MOZ_RELEASE_ASSERT(!mSentinel.mAbove,"Nonempty list left over?");}nsDisplayList(nsDisplayList&&aOther){mForceTransparentSurface=aOther.mForceTransparentSurface;if(aOther.mSentinel.mAbove){AppendToTop(&aOther);}else{mTop=&mSentinel;mLength=0;}}nsDisplayList&operator=(nsDisplayList&&aOther){if(this!=&aOther){if(aOther.mSentinel.mAbove){nsDisplayListtmp;tmp.AppendToTop(&aOther);aOther.AppendToTop(this);AppendToTop(&tmp);}else{mTop=&mSentinel;mLength=0;}mForceTransparentSurface=aOther.mForceTransparentSurface;}return*this;}nsDisplayList(constnsDisplayList&)=delete;nsDisplayList&operator=(constnsDisplayList&aOther)=delete;/** * Append an item to the top of the list. The item must not currently * be in a list and cannot be null. */voidAppendToTop(nsDisplayItem*aItem){if(!aItem){return;}MOZ_ASSERT(!aItem->mAbove,"Already in a list!");mTop->mAbove=aItem;mTop=aItem;mLength++;}template<typenameT,typenameF,typename...Args>voidAppendNewToTop(nsDisplayListBuilder*aBuilder,F*aFrame,Args&&...aArgs){AppendNewToTopWithIndex<T>(aBuilder,aFrame,0,std::forward<Args>(aArgs)...);}template<typenameT,typenameF,typename...Args>voidAppendNewToTopWithIndex(nsDisplayListBuilder*aBuilder,F*aFrame,constuint16_taIndex,Args&&...aArgs){nsDisplayItem*item=MakeDisplayItemWithIndex<T>(aBuilder,aFrame,aIndex,std::forward<Args>(aArgs)...);if(item){AppendToTop(item);}}/** * Append a new item to the bottom of the list. The item must be non-null * and not already in a list. */voidAppendToBottom(nsDisplayItem*aItem){if(!aItem){return;}MOZ_ASSERT(!aItem->mAbove,"Already in a list!");aItem->mAbove=mSentinel.mAbove;mSentinel.mAbove=aItem;if(mTop==&mSentinel){mTop=aItem;}mLength++;}template<typenameT,typenameF,typename...Args>voidAppendNewToBottom(nsDisplayListBuilder*aBuilder,F*aFrame,Args&&...aArgs){AppendNewToBottomWithIndex<T>(aBuilder,aFrame,0,std::forward<Args>(aArgs)...);}template<typenameT,typenameF,typename...Args>voidAppendNewToBottomWithIndex(nsDisplayListBuilder*aBuilder,F*aFrame,constuint16_taIndex,Args&&...aArgs){nsDisplayItem*item=MakeDisplayItemWithIndex<T>(aBuilder,aFrame,aIndex,std::forward<Args>(aArgs)...);if(item){AppendToBottom(item);}}/** * Removes all items from aList and appends them to the top of this list */voidAppendToTop(nsDisplayList*aList){if(aList->mSentinel.mAbove){mTop->mAbove=aList->mSentinel.mAbove;mTop=aList->mTop;aList->mTop=&aList->mSentinel;aList->mSentinel.mAbove=nullptr;mLength+=aList->mLength;aList->mLength=0;}}/** * Removes all items from aList and prepends them to the bottom of this list */voidAppendToBottom(nsDisplayList*aList){if(aList->mSentinel.mAbove){aList->mTop->mAbove=mSentinel.mAbove;mSentinel.mAbove=aList->mSentinel.mAbove;if(mTop==&mSentinel){mTop=aList->mTop;}aList->mTop=&aList->mSentinel;aList->mSentinel.mAbove=nullptr;mLength+=aList->mLength;aList->mLength=0;}}/** * Remove an item from the bottom of the list and return it. */nsDisplayItem*RemoveBottom();/** * Remove all items from the list and call their destructors. */virtualvoidDeleteAll(nsDisplayListBuilder*aBuilder);/** * @return the item at the top of the list, or null if the list is empty */nsDisplayItem*GetTop()const{returnmTop!=&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{returnmSentinel.mAbove;}boolIsEmpty()const{returnmTop==&mSentinel;}/** * @return the number of items in the list */uint32_tCount()const{returnmLength;}/** * Stable sort the list by the z-order of GetUnderlyingFrame() on * each item. 'auto' is counted as zero. * It is assumed that the list is already in content document order. */voidSortByZOrder();/** * Stable sort the list by the tree order of the content of * GetUnderlyingFrame() 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 * ancestor of some elements, then we lose performance but not correctness */voidSortByContentOrder(nsIContent*aCommonAncestor);/** * Sort the display list using a stable sort. Take care, because some of the * items might be nsDisplayLists themselves. * aComparator(Item item1, Item item2) should return true if item1 should go * before item2. * We sort the items into increasing order. */template<typenameItem,typenameComparator>voidSort(constComparator&aComparator){if(Count()<2){// Only sort lists with more than one item.return;}// Some casual local browsing testing suggests that a local preallocated// array of 20 items should be able to avoid a lot of dynamic allocations// here.AutoTArray<Item,20>items;while(nsDisplayItem*item=RemoveBottom()){items.AppendElement(Item(item));}std::stable_sort(items.begin(),items.end(),aComparator);for(Item&item:items){AppendToTop(item);}}/** * Returns true if any display item requires the surface to be transparent. */boolNeedsTransparentSurface()const{returnmForceTransparentSurface;}/** * 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, * aCtx's current transform should make (0,0) pixel-aligned. The * rectangle in aDirtyRect is painted, which *must* be contained in the * dirty rect used to construct the display list. * * If aFlags contains PAINT_USE_WIDGET_LAYERS and * ShouldUseWidgetLayerManager() is set, then we will paint using * the reference frame's widget's layer manager (and ctx may be null), * otherwise we will use a temporary BasicLayerManager and ctx must * not be null. * * If PAINT_EXISTING_TRANSACTION is set, the reference frame's widget's * layer manager has already had BeginTransaction() called on it and * we should not call it again. * * If PAINT_COMPRESSED is set, the FrameLayerBuilder should be set to * compressed mode to avoid short cut optimizations. * * This must only be called on the root display list of the display list * tree. * * We return the layer manager used for painting --- mainly so that * callers can dump its layer tree if necessary. */enum{PAINT_DEFAULT=0,PAINT_USE_WIDGET_LAYERS=0x01,PAINT_EXISTING_TRANSACTION=0x04,PAINT_NO_COMPOSITE=0x08,PAINT_COMPRESSED=0x10,PAINT_IDENTICAL_DISPLAY_LIST=0x20};voidPaintRoot(nsDisplayListBuilder*aBuilder,gfxContext*aCtx,uint32_taFlags,Maybe<double>aDisplayListBuildTime);voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx,int32_taAppUnitsPerDevPixel);/** * Get the bounds. Takes the union of the bounds of all children. * The result is not cached. */nsRectGetClippedBounds(nsDisplayListBuilder*aBuilder)const;/** * Get this list's bounds, respecting clips relative to aASR. The result is * the union of each item's clipped bounds with respect to aASR. That means * that if an item can move asynchronously with an ASR that is a descendant * of aASR, then the clipped bounds with respect to aASR will be the clip of * that item for aASR, because the item can move anywhere inside that clip. * If there is an item in this list which is not bounded with respect to * aASR (i.e. which does not have "finite bounds" with respect to aASR), * then this method trigger an assertion failure. * The optional aBuildingRect out argument can be set to non-null if the * caller is also interested to know the building rect. This can be used * to get the visible rect efficiently without traversing the display list * twice. */nsRectGetClippedBoundsWithRespectToASR(nsDisplayListBuilder*aBuilder,constActiveScrolledRoot*aASR,nsRect*aBuildingRect=nullptr)const;/** * Returns the opaque region of this display list. */nsRegionGetOpaqueRegion(nsDisplayListBuilder*aBuilder){nsRegionresult;boolsnap;for(nsDisplayItem*item:*this){result.OrWith(item->GetOpaqueRegion(aBuilder,&snap));}returnresult;}/** * Returns the bounds of the area that needs component alpha. */nsRectGetComponentAlphaBounds(nsDisplayListBuilder*aBuilder)const{nsRectbounds;for(nsDisplayItem*item:*this){bounds.UnionRect(bounds,item->GetComponentAlphaBounds(aBuilder));}returnbounds;}/** * Find the topmost display item that returns a non-null frame, and return * the frame. */voidHitTest(nsDisplayListBuilder*aBuilder,constnsRect&aRect,nsDisplayItem::HitTestState*aState,nsTArray<nsIFrame*>*aOutFrames)const;/** * Compute the union of the visible rects of the items in the list. The * result is not cached. */nsRectGetBuildingRect()const;voidSetNeedsTransparentSurface(){mForceTransparentSurface=true;}voidRestoreState(){mForceTransparentSurface=false;}private:nsDisplayItemLinkmSentinel;nsDisplayItemLink*mTop;uint32_tmLength;// 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.boolmForceTransparentSurface;};/** * This is passed as a parameter to nsIFrame::BuildDisplayList. That method * will put any generated items onto the appropriate list given here. It's * basically just a collection with one list for each separate stacking layer. * The lists themselves are external to this object and thus can be shared * with others. Some of the list pointers may even refer to the same list. */classnsDisplayListSet{public:/** * @return a list where one should place the border and/or background for * this frame (everything from steps 1 and 2 of CSS 2.1 appendix E) */nsDisplayList*BorderBackground()const{returnmBorderBackground;}/** * @return a list where one should place the borders and/or backgrounds for * block-level in-flow descendants (step 4 of CSS 2.1 appendix E) */nsDisplayList*BlockBorderBackgrounds()const{returnmBlockBorderBackgrounds;}/** * @return a list where one should place descendant floats (step 5 of * CSS 2.1 appendix E) */nsDisplayList*Floats()const{returnmFloats;}/** * @return a list where one should place the (pseudo) stacking contexts * for descendants of this frame (everything from steps 3, 7 and 8 * of CSS 2.1 appendix E) */nsDisplayList*PositionedDescendants()const{returnmPositioned;}/** * @return a list where one should place the outlines * for this frame and its descendants (step 9 of CSS 2.1 appendix E) */nsDisplayList*Outlines()const{returnmOutlines;}/** * @return a list where one should place all other content */nsDisplayList*Content()const{returnmContent;}voidDeleteAll(nsDisplayListBuilder*aBuilder){BorderBackground()->DeleteAll(aBuilder);BlockBorderBackgrounds()->DeleteAll(aBuilder);Floats()->DeleteAll(aBuilder);PositionedDescendants()->DeleteAll(aBuilder);Outlines()->DeleteAll(aBuilder);Content()->DeleteAll(aBuilder);}nsDisplayListSet(nsDisplayList*aBorderBackground,nsDisplayList*aBlockBorderBackgrounds,nsDisplayList*aFloats,nsDisplayList*aContent,nsDisplayList*aPositionedDescendants,nsDisplayList*aOutlines):mBorderBackground(aBorderBackground),mBlockBorderBackgrounds(aBlockBorderBackgrounds),mFloats(aFloats),mContent(aContent),mPositioned(aPositionedDescendants),mOutlines(aOutlines){}/** * A copy constructor that lets the caller override the BorderBackground * list. */nsDisplayListSet(constnsDisplayListSet&aLists,nsDisplayList*aBorderBackground):mBorderBackground(aBorderBackground),mBlockBorderBackgrounds(aLists.BlockBorderBackgrounds()),mFloats(aLists.Floats()),mContent(aLists.Content()),mPositioned(aLists.PositionedDescendants()),mOutlines(aLists.Outlines()){}/** * Move all display items in our lists to top of the corresponding lists in * the destination. */voidMoveTo(constnsDisplayListSet&aDestination)const;private:// This class is only used on stack, so we don't have to worry about leaking// it. Don't let us be heap-allocated!void*operatornew(size_tsz)noexcept(true);protected:nsDisplayList*mBorderBackground;nsDisplayList*mBlockBorderBackgrounds;nsDisplayList*mFloats;nsDisplayList*mContent;nsDisplayList*mPositioned;nsDisplayList*mOutlines;};/** * A specialization of nsDisplayListSet where the lists are actually internal * to the object, and all distinct. */structnsDisplayListCollection:publicnsDisplayListSet{explicitnsDisplayListCollection(nsDisplayListBuilder*aBuilder):nsDisplayListSet(&mLists[0],&mLists[1],&mLists[2],&mLists[3],&mLists[4],&mLists[5]){}explicitnsDisplayListCollection(nsDisplayListBuilder*aBuilder,nsDisplayList*aBorderBackground):nsDisplayListSet(aBorderBackground,&mLists[1],&mLists[2],&mLists[3],&mLists[4],&mLists[5]){}/** * Sort all lists by content order. */voidSortAllByContentOrder(nsIContent*aCommonAncestor){for(auto&mList:mLists){mList.SortByContentOrder(aCommonAncestor);}}/** * Serialize this display list collection into a display list with the items * in the correct Z order. * @param aOutList the result display list * @param aContent the content element to use for content ordering */voidSerializeWithCorrectZOrder(nsDisplayList*aOutResultList,nsIContent*aContent);private:// This class is only used on stack, so we don't have to worry about leaking// it. Don't let us be heap-allocated!void*operatornew(size_tsz)noexcept(true);nsDisplayListmLists[6];};/** * A display list that also retains the partial build * information (in the form of a DAG) used to create it. * * Display lists built from a partial list aren't necessarily * in the same order as a full build, and the DAG retains * the information needing to interpret the current * order correctly. */classRetainedDisplayList:publicnsDisplayList{public:RetainedDisplayList()=default;RetainedDisplayList(RetainedDisplayList&&aOther){AppendToTop(&aOther);mDAG=std::move(aOther.mDAG);}~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(mOldItems.IsEmpty(),"Can only move into an empty list!");AppendToTop(&aOther);mDAG=std::move(aOther.mDAG);mOldItems=std::move(aOther.mOldItems);return*this;}voidDeleteAll(nsDisplayListBuilder*aBuilder)override{for(OldItemInfo&i:mOldItems){if(i.mItem&&i.mOwnsItem){i.mItem->Destroy(aBuilder);MOZ_ASSERT(!GetBottom(),"mOldItems should not be owning items if we also have items ""in the normal list");}}mOldItems.Clear();mDAG.Clear();nsDisplayList::DeleteAll(aBuilder);}voidAddSizeOfExcludingThis(nsWindowSizes&)const;DirectedAcyclicGraph<MergedListUnits>mDAG;// Temporary state initialized during the preprocess pass// of RetainedDisplayListBuilder and then used during merging.nsTArray<OldItemInfo>mOldItems;};classnsDisplayContainerfinal:publicnsDisplayItem{public:nsDisplayContainer(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constActiveScrolledRoot*aActiveScrolledRoot,nsDisplayList*aList);~nsDisplayContainer()override{MOZ_COUNT_DTOR(nsDisplayContainer);}NS_DISPLAY_DECL_NAME("nsDisplayContainer",TYPE_CONTAINER)voidDestroy(nsDisplayListBuilder*aBuilder)override{mChildren.DeleteAll(aBuilder);nsDisplayItem::Destroy(aBuilder);}boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;nsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;nsRectGetComponentAlphaBounds(nsDisplayListBuilder*aBuilder)constoverride;nsRegionGetOpaqueRegion(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;Maybe<nscolor>IsUniform(nsDisplayListBuilder*aBuilder)constoverride{returnNothing();}RetainedDisplayList*GetChildren()constoverride{return&mChildren;}RetainedDisplayList*GetSameCoordinateSystemChildren()constoverride{returnGetChildren();}Maybe<nsRect>GetClipWithRespectToASR(nsDisplayListBuilder*aBuilder,constActiveScrolledRoot*aASR)constoverride;voidHitTest(nsDisplayListBuilder*aBuilder,constnsRect&aRect,HitTestState*aState,nsTArray<nsIFrame*>*aOutFrames)override;boolShouldFlattenAway(nsDisplayListBuilder*aBuilder)override{returntrue;}voidSetClipChain(constDisplayItemClipChain*aClipChain,boolaStore)override{MOZ_ASSERT_UNREACHABLE("nsDisplayContainer does not support clipping");}voidUpdateBounds(nsDisplayListBuilder*aBuilder)override;private:mutableRetainedDisplayListmChildren;nsRectmBounds;};/** * Use this class to implement not-very-frequently-used display items * that are not opaque, do not receive events, and are bounded by a frame's * border-rect. * * This should not be used for display items which are created frequently, * because each item is one or two pointers bigger than an item from a * custom display item class could be, and fractionally slower. However it does * save code size. We use this for infrequently-used item types. */classnsDisplayGeneric:publicnsPaintedDisplayItem{public:typedefvoid(*PaintCallback)(nsIFrame*aFrame,gfx::DrawTarget*aDrawTarget,constnsRect&aDirtyRect,nsPointaFramePt);// XXX: should be removed eventuallytypedefvoid(*OldPaintCallback)(nsIFrame*aFrame,gfxContext*aCtx,constnsRect&aDirtyRect,nsPointaFramePt);nsDisplayGeneric(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,PaintCallbackaPaint,constchar*aName,DisplayItemTypeaType):nsPaintedDisplayItem(aBuilder,aFrame),mPaint(aPaint),mOldPaint(nullptr),mName(aName){MOZ_COUNT_CTOR(nsDisplayGeneric);SetType(aType);}// XXX: should be removed eventuallynsDisplayGeneric(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,OldPaintCallbackaOldPaint,constchar*aName,DisplayItemTypeaType):nsPaintedDisplayItem(aBuilder,aFrame),mPaint(nullptr),mOldPaint(aOldPaint),mName(aName){MOZ_COUNT_CTOR(nsDisplayGeneric);SetType(aType);}constexprstaticDisplayItemTypeItemType(){returnDisplayItemType::TYPE_GENERIC;}MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayGeneric)voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override{MOZ_ASSERT(!!mPaint!=!!mOldPaint);if(mPaint){mPaint(mFrame,aCtx->GetDrawTarget(),GetPaintRect(aBuilder,aCtx),ToReferenceFrame());}else{mOldPaint(mFrame,aCtx,GetPaintRect(aBuilder,aCtx),ToReferenceFrame());}}constchar*Name()constoverride{returnmName;}// This override is needed because GetType() for nsDisplayGeneric subclasses// does not match TYPE_GENERIC that was used to allocate the object.voidDestroy(nsDisplayListBuilder*aBuilder)override{this->~nsDisplayGeneric();aBuilder->Destroy(DisplayItemType::TYPE_GENERIC,this);}protected:void*operatornew(size_taSize,nsDisplayListBuilder*aBuilder){returnaBuilder->Allocate(aSize,DisplayItemType::TYPE_GENERIC);}template<typenameT,typenameF,typename...Args>friendT*MakeDisplayItemWithIndex(nsDisplayListBuilder*aBuilder,F*aFrame,constuint16_taIndex,Args&&...aArgs);PaintCallbackmPaint;OldPaintCallbackmOldPaint;// XXX: should be removed eventuallyconstchar*mName;};#if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)/** * This class implements painting of reflow counts. Ideally, we would simply * make all the frame names be those returned by nsIFrame::GetFrameName * (except that tosses in the content tag name!) and support only one color * and eliminate this class altogether in favor of nsDisplayGeneric, but for * the time being we can't pass args to a PaintCallback, so just have a * separate class to do the right thing. Sadly, this alsmo means we need to * hack all leaf frame classes to handle this. * * XXXbz the color thing is a bit of a mess, but 0 basically means "not set" * here... I could switch it all to nscolor, but why bother? */classnsDisplayReflowCount:publicnsPaintedDisplayItem{public:nsDisplayReflowCount(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constchar*aFrameName,uint32_taColor=0):nsPaintedDisplayItem(aBuilder,aFrame),mFrameName(aFrameName),mColor(aColor){MOZ_COUNT_CTOR(nsDisplayReflowCount);}MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayReflowCount)NS_DISPLAY_DECL_NAME("nsDisplayReflowCount",TYPE_REFLOW_COUNT)voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;protected:constchar*mFrameName;nscolormColor;};# define DO_GLOBAL_REFLOW_COUNT_DSP(_name) \ PR_BEGIN_MACRO \ if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \ PresShell()->IsPaintingFrameCounts()) { \ aLists.Outlines()->AppendNewToTop<nsDisplayReflowCount>(aBuilder, this, \ _name); \ } \ PR_END_MACRO# define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color) \ PR_BEGIN_MACRO \ if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \ PresShell()->IsPaintingFrameCounts()) { \ aLists.Outlines()->AppendNewToTop<nsDisplayReflowCount>(aBuilder, this, \ _name, _color); \ } \ PR_END_MACRO/* Macro to be used for classes that don't actually implement BuildDisplayList */# define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super) \ void BuildDisplayList(nsDisplayListBuilder* aBuilder, \ const nsRect& aDirtyRect, \ const nsDisplayListSet& aLists) { \ DO_GLOBAL_REFLOW_COUNT_DSP(#_class); \ _super::BuildDisplayList(aBuilder, aDirtyRect, aLists); \ }#else // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF# define DO_GLOBAL_REFLOW_COUNT_DSP(_name)# define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color)# define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super)#endif // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERFclassnsDisplayCaret:publicnsPaintedDisplayItem{public:nsDisplayCaret(nsDisplayListBuilder*aBuilder,nsIFrame*aCaretFrame);#ifdef NS_BUILD_REFCNT_LOGGING~nsDisplayCaret()override;#endifNS_DISPLAY_DECL_NAME("Caret",TYPE_CARET)nsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;protected:RefPtr<nsCaret>mCaret;nsRectmBounds;};/** * The standard display item to paint the CSS borders of a frame. */classnsDisplayBorder:publicnsPaintedDisplayItem{public:nsDisplayBorder(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame);MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBorder)NS_DISPLAY_DECL_NAME("Border",TYPE_BORDER)boolIsInvisibleInRect(constnsRect&aRect)constoverride;nsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;nsDisplayItemGeometry*AllocateGeometry(nsDisplayListBuilder*aBuilder)override;voidComputeInvalidationRegion(nsDisplayListBuilder*aBuilder,constnsDisplayItemGeometry*aGeometry,nsRegion*aInvalidRegion)constoverride;nsRegionGetTightBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride{*aSnap=true;returnCalculateBounds<nsRegion>(*mFrame->StyleBorder());}protected:template<typenameT>TCalculateBounds(constnsStyleBorder&aStyleBorder)const{nsRectborderBounds(ToReferenceFrame(),mFrame->GetSize());if(aStyleBorder.IsBorderImageSizeAvailable()){borderBounds.Inflate(aStyleBorder.GetImageOutset());returnborderBounds;}nsMarginborder=aStyleBorder.GetComputedBorder();Tresult;if(border.top>0){result=nsRect(borderBounds.X(),borderBounds.Y(),borderBounds.Width(),border.top);}if(border.right>0){result.OrWith(nsRect(borderBounds.XMost()-border.right,borderBounds.Y(),border.right,borderBounds.Height()));}if(border.bottom>0){result.OrWith(nsRect(borderBounds.X(),borderBounds.YMost()-border.bottom,borderBounds.Width(),border.bottom));}if(border.left>0){result.OrWith(nsRect(borderBounds.X(),borderBounds.Y(),border.left,borderBounds.Height()));}nscoordradii[8];if(mFrame->GetBorderRadii(radii)){if(border.left>0||border.top>0){nsSizecornerSize(radii[eCornerTopLeftX],radii[eCornerTopLeftY]);result.OrWith(nsRect(borderBounds.TopLeft(),cornerSize));}if(border.top>0||border.right>0){nsSizecornerSize(radii[eCornerTopRightX],radii[eCornerTopRightY]);result.OrWith(nsRect(borderBounds.TopRight()-nsPoint(cornerSize.width,0),cornerSize));}if(border.right>0||border.bottom>0){nsSizecornerSize(radii[eCornerBottomRightX],radii[eCornerBottomRightY]);result.OrWith(nsRect(borderBounds.BottomRight()-nsPoint(cornerSize.width,cornerSize.height),cornerSize));}if(border.bottom>0||border.left>0){nsSizecornerSize(radii[eCornerBottomLeftX],radii[eCornerBottomLeftY]);result.OrWith(nsRect(borderBounds.BottomLeft()-nsPoint(0,cornerSize.height),cornerSize));}}returnresult;}nsRectmBounds;};/** * A simple display item that just renders a solid color across the * specified bounds. For canvas frames (in the CSS sense) we split off the * drawing of the background color into this class (from nsDisplayBackground * via nsDisplayCanvasBackground). This is done so that we can always draw a * background color to avoid ugly flashes of white when we can't draw a full * frame tree (ie when a page is loading). The bounds can differ from the * frame's bounds -- this is needed when a frame/iframe is loading and there * is not yet a frame tree to go in the frame/iframe so we use the subdoc * frame of the parent document as a standin. */classnsDisplaySolidColorBase:publicnsPaintedDisplayItem{public:nsDisplaySolidColorBase(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nscoloraColor):nsPaintedDisplayItem(aBuilder,aFrame),mColor(aColor){}nsDisplayItemGeometry*AllocateGeometry(nsDisplayListBuilder*aBuilder)override{returnnewnsDisplaySolidColorGeometry(this,aBuilder,mColor);}voidComputeInvalidationRegion(nsDisplayListBuilder*aBuilder,constnsDisplayItemGeometry*aGeometry,nsRegion*aInvalidRegion)constoverride{constnsDisplaySolidColorGeometry*geometry=static_cast<constnsDisplaySolidColorGeometry*>(aGeometry);if(mColor!=geometry->mColor){booldummy;aInvalidRegion->Or(geometry->mBounds,GetBounds(aBuilder,&dummy));return;}ComputeInvalidationRegionDifference(aBuilder,geometry,aInvalidRegion);}nsRegionGetOpaqueRegion(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride{*aSnap=false;nsRegionresult;if(NS_GET_A(mColor)==255){result=GetBounds(aBuilder,aSnap);}returnresult;}Maybe<nscolor>IsUniform(nsDisplayListBuilder*aBuilder)constoverride{returnSome(mColor);}protected:nscolormColor;};classnsDisplaySolidColor:publicnsDisplaySolidColorBase{public:nsDisplaySolidColor(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constnsRect&aBounds,nscoloraColor,boolaCanBeReused=true):nsDisplaySolidColorBase(aBuilder,aFrame,aColor),mBounds(aBounds){NS_ASSERTION(NS_GET_A(aColor)>0,"Don't create invisible nsDisplaySolidColors!");MOZ_COUNT_CTOR(nsDisplaySolidColor);if(!aCanBeReused){SetCantBeReused();}}MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySolidColor)NS_DISPLAY_DECL_NAME("SolidColor",TYPE_SOLID_COLOR)nsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;voidWriteDebugInfo(std::stringstream&aStream)override;boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;int32_tZIndex()constoverride{if(mOverrideZIndex){returnmOverrideZIndex.value();}returnnsDisplaySolidColorBase::ZIndex();}voidSetOverrideZIndex(int32_taZIndex){mOverrideZIndex=Some(aZIndex);}private:nsRectmBounds;Maybe<int32_t>mOverrideZIndex;};/** * A display item that renders a solid color over a region. This is not * exposed through CSS, its only purpose is efficient invalidation of * the find bar highlighter dimmer. */classnsDisplaySolidColorRegion:publicnsPaintedDisplayItem{public:nsDisplaySolidColorRegion(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constnsRegion&aRegion,nscoloraColor):nsPaintedDisplayItem(aBuilder,aFrame),mRegion(aRegion),mColor(gfx::sRGBColor::FromABGR(aColor)){NS_ASSERTION(NS_GET_A(aColor)>0,"Don't create invisible nsDisplaySolidColorRegions!");MOZ_COUNT_CTOR(nsDisplaySolidColorRegion);}MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySolidColorRegion)NS_DISPLAY_DECL_NAME("SolidColorRegion",TYPE_SOLID_COLOR_REGION)nsDisplayItemGeometry*AllocateGeometry(nsDisplayListBuilder*aBuilder)override{returnnewnsDisplaySolidColorRegionGeometry(this,aBuilder,mRegion,mColor);}voidComputeInvalidationRegion(nsDisplayListBuilder*aBuilder,constnsDisplayItemGeometry*aGeometry,nsRegion*aInvalidRegion)constoverride{constnsDisplaySolidColorRegionGeometry*geometry=static_cast<constnsDisplaySolidColorRegionGeometry*>(aGeometry);if(mColor==geometry->mColor){aInvalidRegion->Xor(geometry->mRegion,mRegion);}else{aInvalidRegion->Or(geometry->mRegion.GetBounds(),mRegion.GetBounds());}}boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;protected:nsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;voidWriteDebugInfo(std::stringstream&aStream)override;private:nsRegionmRegion;gfx::sRGBColormColor;};enumclassAppendedBackgroundType:uint8_t{None,Background,ThemedBackground,};/** * A display item to paint one background-image for a frame. Each background * image layer gets its own nsDisplayBackgroundImage. */classnsDisplayBackgroundImage:publicnsPaintedDisplayItem{public:structInitData{nsDisplayListBuilder*builder;ComputedStyle*backgroundStyle;nsCOMPtr<imgIContainer>image;nsRectbackgroundRect;nsRectfillArea;nsRectdestArea;uint32_tlayer;boolisRasterImage;boolshouldFixToViewport;};/** * aLayer signifies which background layer this item represents. * aIsThemed should be the value of aFrame->IsThemed. * aBackgroundStyle should be the result of * nsCSSRendering::FindBackground, or null if FindBackground returned false. * aBackgroundRect is relative to aFrame. */staticInitDataGetInitData(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,uint16_taLayer,constnsRect&aBackgroundRect,ComputedStyle*aBackgroundStyle);explicitnsDisplayBackgroundImage(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constInitData&aInitData,nsIFrame*aFrameForBounds=nullptr);~nsDisplayBackgroundImage()override;boolRestoreState()override{boolsuperChanged=nsPaintedDisplayItem::RestoreState();boolopacityChanged=(mOpacity!=1.0f);mOpacity=1.0f;return(superChanged||opacityChanged);}NS_DISPLAY_DECL_NAME("Background",TYPE_BACKGROUND)/** * This will create and append new items for all the layers of the * background. Returns the type of background that was appended. * aAllowWillPaintBorderOptimization should usually be left at true, unless * aFrame has special border drawing that causes opaque borders to not * actually be opaque. */staticAppendedBackgroundTypeAppendBackgroundItemsToTop(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constnsRect&aBackgroundRect,nsDisplayList*aList,boolaAllowWillPaintBorderOptimization=true,ComputedStyle*aComputedStyle=nullptr,constnsRect&aBackgroundOriginRect=nsRect(),nsIFrame*aSecondaryReferenceFrame=nullptr,Maybe<nsDisplayListBuilder::AutoBuildingDisplayList>*aAutoBuildingDisplayList=nullptr);boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;voidHitTest(nsDisplayListBuilder*aBuilder,constnsRect&aRect,HitTestState*aState,nsTArray<nsIFrame*>*aOutFrames)override;nsRegionGetOpaqueRegion(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;Maybe<nscolor>IsUniform(nsDisplayListBuilder*aBuilder)constoverride;boolCanApplyOpacity()constoverride{returntrue;}voidApplyOpacity(nsDisplayListBuilder*aBuilder,floataOpacity,constDisplayItemClipChain*aClip)override{mOpacity=aOpacity;}/** * GetBounds() returns the background painting area. */nsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;/** * Return the background positioning area. * (GetBounds() returns the background painting area.) * Can be called only when mBackgroundStyle is non-null. */nsRectGetPositioningArea()const;/** * Returns true if existing rendered pixels of this display item may need * to be redrawn if the positioning area size changes but its position does * not. * If false, only the changed painting area needs to be redrawn when the * positioning area size changes but its position does not. */boolRenderingMightDependOnPositioningAreaSizeChange()const;nsDisplayItemGeometry*AllocateGeometry(nsDisplayListBuilder*aBuilder)override{returnnewnsDisplayBackgroundGeometry(this,aBuilder);}voidComputeInvalidationRegion(nsDisplayListBuilder*aBuilder,constnsDisplayItemGeometry*aGeometry,nsRegion*aInvalidRegion)constoverride;boolShouldFixToViewport(nsDisplayListBuilder*aBuilder)constoverride{returnmShouldFixToViewport;}nsRectGetDestRect()const{returnmDestRect;}nsIFrame*GetDependentFrame()override{returnmDependentFrame;}voidSetDependentFrame(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame){if(!aBuilder->IsRetainingDisplayList()){return;}mDependentFrame=aFrame;if(aFrame){mDependentFrame->AddDisplayItem(this);}}voidRemoveFrame(nsIFrame*aFrame)override{if(aFrame==mDependentFrame){mDependentFrame=nullptr;}nsPaintedDisplayItem::RemoveFrame(aFrame);}// Match https://w3c.github.io/paint-timing/#contentful-imageboolIsContentful()constoverride{constauto&styleImage=mBackgroundStyle->StyleBackground()->mImage.mLayers[mLayer].mImage;returnstyleImage.IsSizeAvailable()&&styleImage.FinalImage().IsUrl();}protected:boolCanBuildWebRenderDisplayItems(layers::WebRenderLayerManager*aManager,nsDisplayListBuilder*aBuilder);nsRectGetBoundsInternal(nsDisplayListBuilder*aBuilder,nsIFrame*aFrameForBounds=nullptr);voidPaintInternal(nsDisplayListBuilder*aBuilder,gfxContext*aCtx,constnsRect&aBounds,nsRect*aClipRect);// Cache the result of nsCSSRendering::FindBackground. Always null if// mIsThemed is true or if FindBackground returned false.RefPtr<ComputedStyle>mBackgroundStyle;nsCOMPtr<imgIContainer>mImage;nsIFrame*mDependentFrame;nsRectmBackgroundRect;// relative to the reference framensRectmFillRect;nsRectmDestRect;/* Bounds of this display item */nsRectmBounds;uint16_tmLayer;boolmIsRasterImage;/* Whether the image should be treated as fixed to the viewport. */boolmShouldFixToViewport;uint32_tmImageFlags;floatmOpacity;};/** * A display item to paint background image for table. For table parts, such * as row, row group, col, col group, when drawing its background, we'll * create separate background image display item for its containning cell. * Those background image display items will reference to same DisplayItemData * if we keep the mFrame point to cell's ancestor frame. We don't want to this * happened bacause share same DisplatItemData will cause many bugs. So that * we let mFrame point to cell frame and store the table type of the ancestor * frame. And use mFrame and table type as key to generate DisplayItemData to * avoid sharing DisplayItemData. * * Also store ancestor frame as mStyleFrame for all rendering informations. */classnsDisplayTableBackgroundImage:publicnsDisplayBackgroundImage{public:nsDisplayTableBackgroundImage(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constInitData&aData,nsIFrame*aCellFrame);~nsDisplayTableBackgroundImage()override;NS_DISPLAY_DECL_NAME("TableBackgroundImage",TYPE_TABLE_BACKGROUND_IMAGE)boolIsInvalid(nsRect&aRect)constoverride;nsIFrame*FrameForInvalidation()constoverride{returnmStyleFrame;}voidRemoveFrame(nsIFrame*aFrame)override{if(aFrame==mStyleFrame){mStyleFrame=nullptr;SetDeletedFrame();}nsDisplayBackgroundImage::RemoveFrame(aFrame);}protected:nsIFrame*StyleFrame()constoverride{returnmStyleFrame;}nsIFrame*mStyleFrame;};/** * A display item to paint the native theme background for a frame. */classnsDisplayThemedBackground:publicnsPaintedDisplayItem{public:nsDisplayThemedBackground(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constnsRect&aBackgroundRect);MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayThemedBackground)NS_DISPLAY_DECL_NAME("ThemedBackground",TYPE_THEMED_BACKGROUND)voidInit(nsDisplayListBuilder*aBuilder);voidDestroy(nsDisplayListBuilder*aBuilder)override{aBuilder->UnregisterThemeGeometry(this);nsPaintedDisplayItem::Destroy(aBuilder);}voidHitTest(nsDisplayListBuilder*aBuilder,constnsRect&aRect,HitTestState*aState,nsTArray<nsIFrame*>*aOutFrames)override;nsRegionGetOpaqueRegion(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;Maybe<nscolor>IsUniform(nsDisplayListBuilder*aBuilder)constoverride;boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;boolMustPaintOnContentSide()constoverride{returntrue;}/** * GetBounds() returns the background painting area. */nsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;/** * Return the background positioning area. * (GetBounds() returns the background painting area.) * Can be called only when mBackgroundStyle is non-null. */nsRectGetPositioningArea()const;/** * Return whether our frame's document does not have the state * NS_DOCUMENT_STATE_WINDOW_INACTIVE. */boolIsWindowActive()const;nsDisplayItemGeometry*AllocateGeometry(nsDisplayListBuilder*aBuilder)override{returnnewnsDisplayThemedBackgroundGeometry(this,aBuilder);}voidComputeInvalidationRegion(nsDisplayListBuilder*aBuilder,constnsDisplayItemGeometry*aGeometry,nsRegion*aInvalidRegion)constoverride;voidWriteDebugInfo(std::stringstream&aStream)override;protected:nsRectGetBoundsInternal();voidPaintInternal(nsDisplayListBuilder*aBuilder,gfxContext*aCtx,constnsRect&aBounds,nsRect*aClipRect);nsRectmBackgroundRect;nsRectmBounds;nsITheme::TransparencymThemeTransparency;StyleAppearancemAppearance;};classnsDisplayTableThemedBackground:publicnsDisplayThemedBackground{public:nsDisplayTableThemedBackground(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constnsRect&aBackgroundRect,nsIFrame*aAncestorFrame):nsDisplayThemedBackground(aBuilder,aFrame,aBackgroundRect),mAncestorFrame(aAncestorFrame){if(aBuilder->IsRetainingDisplayList()){mAncestorFrame->AddDisplayItem(this);}}~nsDisplayTableThemedBackground()override{if(mAncestorFrame){mAncestorFrame->RemoveDisplayItem(this);}}NS_DISPLAY_DECL_NAME("TableThemedBackground",TYPE_TABLE_THEMED_BACKGROUND_IMAGE)nsIFrame*FrameForInvalidation()constoverride{returnmAncestorFrame;}voidRemoveFrame(nsIFrame*aFrame)override{if(aFrame==mAncestorFrame){mAncestorFrame=nullptr;SetDeletedFrame();}nsDisplayThemedBackground::RemoveFrame(aFrame);}protected:nsIFrame*StyleFrame()constoverride{returnmAncestorFrame;}nsIFrame*mAncestorFrame;};classnsDisplayBackgroundColor:publicnsPaintedDisplayItem{public:nsDisplayBackgroundColor(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constnsRect&aBackgroundRect,constComputedStyle*aBackgroundStyle,constnscolor&aColor):nsPaintedDisplayItem(aBuilder,aFrame),mBackgroundRect(aBackgroundRect),mHasStyle(aBackgroundStyle),mDependentFrame(nullptr),mColor(gfx::sRGBColor::FromABGR(aColor)){mState.mColor=mColor;if(mHasStyle){mBottomLayerClip=aBackgroundStyle->StyleBackground()->BottomLayer().mClip;}else{MOZ_ASSERT(aBuilder->IsForEventDelivery());}}~nsDisplayBackgroundColor()override{if(mDependentFrame){mDependentFrame->RemoveDisplayItem(this);}}NS_DISPLAY_DECL_NAME("BackgroundColor",TYPE_BACKGROUND_COLOR)boolRestoreState()override{if(!nsPaintedDisplayItem::RestoreState()&&mColor==mState.mColor){returnfalse;}mColor=mState.mColor;returntrue;}boolHasBackgroundClipText()const{MOZ_ASSERT(mHasStyle);returnmBottomLayerClip==StyleGeometryBox::Text;}voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;voidPaintWithClip(nsDisplayListBuilder*aBuilder,gfxContext*aCtx,constDisplayItemClip&aClip)override;boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;nsRegionGetOpaqueRegion(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;Maybe<nscolor>IsUniform(nsDisplayListBuilder*aBuilder)constoverride;voidHitTest(nsDisplayListBuilder*aBuilder,constnsRect&aRect,HitTestState*aState,nsTArray<nsIFrame*>*aOutFrames)override;voidApplyOpacity(nsDisplayListBuilder*aBuilder,floataOpacity,constDisplayItemClipChain*aClip)override;boolCanApplyOpacity()constoverride;floatGetOpacity()const{returnmColor.a;}nsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride{*aSnap=true;returnmBackgroundRect;}boolCanPaintWithClip(constDisplayItemClip&aClip)override{if(HasBackgroundClipText()){returnfalse;}if(aClip.GetRoundedRectCount()>1){returnfalse;}returntrue;}nsDisplayItemGeometry*AllocateGeometry(nsDisplayListBuilder*aBuilder)override{returnnewnsDisplaySolidColorGeometry(this,aBuilder,mColor.ToABGR());}voidComputeInvalidationRegion(nsDisplayListBuilder*aBuilder,constnsDisplayItemGeometry*aGeometry,nsRegion*aInvalidRegion)constoverride{constnsDisplaySolidColorGeometry*geometry=static_cast<constnsDisplaySolidColorGeometry*>(aGeometry);if(mColor.ToABGR()!=geometry->mColor){booldummy;aInvalidRegion->Or(geometry->mBounds,GetBounds(aBuilder,&dummy));return;}ComputeInvalidationRegionDifference(aBuilder,geometry,aInvalidRegion);}nsIFrame*GetDependentFrame()override{returnmDependentFrame;}voidSetDependentFrame(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame){if(!aBuilder->IsRetainingDisplayList()){return;}mDependentFrame=aFrame;if(aFrame){mDependentFrame->AddDisplayItem(this);}}voidRemoveFrame(nsIFrame*aFrame)override{if(aFrame==mDependentFrame){mDependentFrame=nullptr;}nsPaintedDisplayItem::RemoveFrame(aFrame);}voidWriteDebugInfo(std::stringstream&aStream)override;boolCanUseAsyncAnimations(nsDisplayListBuilder*aBuilder)override;protected:constnsRectmBackgroundRect;constboolmHasStyle;StyleGeometryBoxmBottomLayerClip;nsIFrame*mDependentFrame;gfx::sRGBColormColor;struct{gfx::sRGBColormColor;}mState;};classnsDisplayTableBackgroundColor:publicnsDisplayBackgroundColor{public:nsDisplayTableBackgroundColor(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constnsRect&aBackgroundRect,constComputedStyle*aBackgroundStyle,constnscolor&aColor,nsIFrame*aAncestorFrame):nsDisplayBackgroundColor(aBuilder,aFrame,aBackgroundRect,aBackgroundStyle,aColor),mAncestorFrame(aAncestorFrame){if(aBuilder->IsRetainingDisplayList()){mAncestorFrame->AddDisplayItem(this);}}~nsDisplayTableBackgroundColor()override{if(mAncestorFrame){mAncestorFrame->RemoveDisplayItem(this);}}NS_DISPLAY_DECL_NAME("TableBackgroundColor",TYPE_TABLE_BACKGROUND_COLOR)nsIFrame*FrameForInvalidation()constoverride{returnmAncestorFrame;}voidRemoveFrame(nsIFrame*aFrame)override{if(aFrame==mAncestorFrame){mAncestorFrame=nullptr;SetDeletedFrame();}nsDisplayBackgroundColor::RemoveFrame(aFrame);}boolCanUseAsyncAnimations(nsDisplayListBuilder*aBuilder)override{returnfalse;}protected:nsIFrame*mAncestorFrame;};/** * The standard display item to paint the outer CSS box-shadows of a frame. */classnsDisplayBoxShadowOuterfinal:publicnsPaintedDisplayItem{public:nsDisplayBoxShadowOuter(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame):nsPaintedDisplayItem(aBuilder,aFrame),mOpacity(1.0f){MOZ_COUNT_CTOR(nsDisplayBoxShadowOuter);mBounds=GetBoundsInternal();}MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBoxShadowOuter)NS_DISPLAY_DECL_NAME("BoxShadowOuter",TYPE_BOX_SHADOW_OUTER)boolRestoreState()override{if(!nsPaintedDisplayItem::RestoreState()&&mOpacity==1.0f){returnfalse;}mOpacity=1.0f;returntrue;}voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;nsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;boolIsInvisibleInRect(constnsRect&aRect)constoverride;voidComputeInvalidationRegion(nsDisplayListBuilder*aBuilder,constnsDisplayItemGeometry*aGeometry,nsRegion*aInvalidRegion)constoverride;voidApplyOpacity(nsDisplayListBuilder*aBuilder,floataOpacity,constDisplayItemClipChain*aClip)override{NS_ASSERTION(CanApplyOpacity(),"ApplyOpacity should be allowed");mOpacity=aOpacity;IntersectClip(aBuilder,aClip,false);}boolCanApplyOpacity()constoverride{returntrue;}nsDisplayItemGeometry*AllocateGeometry(nsDisplayListBuilder*aBuilder)override{returnnewnsDisplayBoxShadowOuterGeometry(this,aBuilder,mOpacity);}boolCanBuildWebRenderDisplayItems();boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;nsRectGetBoundsInternal();private:nsRectmBounds;floatmOpacity;};/** * The standard display item to paint the inner CSS box-shadows of a frame. */classnsDisplayBoxShadowInner:publicnsPaintedDisplayItem{public:nsDisplayBoxShadowInner(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame):nsPaintedDisplayItem(aBuilder,aFrame){MOZ_COUNT_CTOR(nsDisplayBoxShadowInner);}MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBoxShadowInner)NS_DISPLAY_DECL_NAME("BoxShadowInner",TYPE_BOX_SHADOW_INNER)voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;nsDisplayItemGeometry*AllocateGeometry(nsDisplayListBuilder*aBuilder)override{returnnewnsDisplayBoxShadowInnerGeometry(this,aBuilder);}voidComputeInvalidationRegion(nsDisplayListBuilder*aBuilder,constnsDisplayItemGeometry*aGeometry,nsRegion*aInvalidRegion)constoverride{constnsDisplayBoxShadowInnerGeometry*geometry=static_cast<constnsDisplayBoxShadowInnerGeometry*>(aGeometry);if(!geometry->mPaddingRect.IsEqualInterior(GetPaddingRect())){// nsDisplayBoxShadowInner is based around the padding rect, but it can// touch pixels outside of this. We should invalidate the entire bounds.boolsnap;aInvalidRegion->Or(geometry->mBounds,GetBounds(aBuilder,&snap));}}staticboolCanCreateWebRenderCommands(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constnsPoint&aReferenceOffset);staticvoidCreateInsetBoxShadowWebRenderCommands(wr::DisplayListBuilder&aBuilder,constStackingContextHelper&aSc,nsRect&aVisibleRect,nsIFrame*aFrame,constnsRect&aBorderRect);boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;};/** * The standard display item to paint the CSS outline of a frame. */classnsDisplayOutlinefinal:publicnsPaintedDisplayItem{public:nsDisplayOutline(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame):nsPaintedDisplayItem(aBuilder,aFrame){MOZ_COUNT_CTOR(nsDisplayOutline);}MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOutline)NS_DISPLAY_DECL_NAME("Outline",TYPE_OUTLINE)boolMustPaintOnContentSide()constoverride{MOZ_ASSERT(IsThemedOutline(),"The only fallback path we have is for themed outlines");returntrue;}boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;boolIsInvisibleInRect(constnsRect&aRect)constoverride;nsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;private:nsRectGetInnerRect()const;boolIsThemedOutline()const;boolHasRadius()const;};/** * A class that lets you receive events within the frame bounds but never * paints. */classnsDisplayEventReceiverfinal:publicnsDisplayItem{public:nsDisplayEventReceiver(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame):nsDisplayItem(aBuilder,aFrame){MOZ_COUNT_CTOR(nsDisplayEventReceiver);}MOZ_COUNTED_DTOR_FINAL(nsDisplayEventReceiver)NS_DISPLAY_DECL_NAME("EventReceiver",TYPE_EVENT_RECEIVER)voidHitTest(nsDisplayListBuilder*aBuilder,constnsRect&aRect,HitTestState*aState,nsTArray<nsIFrame*>*aOutFrames)final;};/** * Similar to nsDisplayEventReceiver in that it is used for hit-testing. However * this gets built when we're doing widget painting and we need to send the * compositor some hit-test info for a frame. This is effectively a dummy item * whose sole purpose is to carry the hit-test info to the compositor. */classnsDisplayCompositorHitTestInfofinal:publicnsDisplayItem{public:nsDisplayCompositorHitTestInfo(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame):nsDisplayItem(aBuilder,aFrame){MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo);mHitTestInfo.Initialize(aBuilder,aFrame);SetHasHitTestInfo();}nsDisplayCompositorHitTestInfo(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constnsRect&aArea,constgfx::CompositorHitTestInfo&aHitTestFlags):nsDisplayItem(aBuilder,aFrame){MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo);mHitTestInfo.SetAreaAndInfo(aArea,aHitTestFlags);mHitTestInfo.InitializeScrollTarget(aBuilder);SetHasHitTestInfo();}MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayCompositorHitTestInfo)NS_DISPLAY_DECL_NAME("CompositorHitTestInfo",TYPE_COMPOSITOR_HITTEST_INFO)boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;int32_tZIndex()constoverride;voidSetOverrideZIndex(int32_taZIndex);nsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride{*aSnap=false;returnnsRect();}constHitTestInfo&GetHitTestInfo()final{returnmHitTestInfo;}private:HitTestInfomHitTestInfo;Maybe<int32_t>mOverrideZIndex;};/** * A class that lets you wrap a display list as a display item. * * GetUnderlyingFrame() is troublesome for wrapped lists because if the wrapped * list has many items, it's not clear which one has the 'underlying frame'. * Thus we force the creator to specify what the underlying frame is. The * underlying frame should be the root of a stacking context, because sorting * a list containing this item will not get at the children. * * In some cases (e.g., clipping) we want to wrap a list but we don't have a * particular underlying frame that is a stacking context root. In that case * we allow the frame to be nullptr. Callers to GetUnderlyingFrame must * detect and handle this case. */classnsDisplayWrapList:publicnsPaintedDisplayItem{public:/** * Takes all the items from aList and puts them in our list. */nsDisplayWrapList(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList);nsDisplayWrapList(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayItem*aItem);nsDisplayWrapList(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,constActiveScrolledRoot*aActiveScrolledRoot,boolaClearClipChain=false);nsDisplayWrapList(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame):nsPaintedDisplayItem(aBuilder,aFrame),mFrameActiveScrolledRoot(aBuilder->CurrentActiveScrolledRoot()),mOverrideZIndex(0),mHasZIndexOverride(false){MOZ_COUNT_CTOR(nsDisplayWrapList);mBaseBuildingRect=GetBuildingRect();mListPtr=&mList;}nsDisplayWrapList()=delete;/** * A custom copy-constructor that does not copy mList, as this would mutate * the other item. */nsDisplayWrapList(constnsDisplayWrapList&aOther)=delete;nsDisplayWrapList(nsDisplayListBuilder*aBuilder,constnsDisplayWrapList&aOther):nsPaintedDisplayItem(aBuilder,aOther),mListPtr(&mList),mFrameActiveScrolledRoot(aOther.mFrameActiveScrolledRoot),mMergedFrames(aOther.mMergedFrames.Clone()),mBounds(aOther.mBounds),mBaseBuildingRect(aOther.mBaseBuildingRect),mOverrideZIndex(aOther.mOverrideZIndex),mHasZIndexOverride(aOther.mHasZIndexOverride),mClearingClipChain(aOther.mClearingClipChain){MOZ_COUNT_CTOR(nsDisplayWrapList);}~nsDisplayWrapList()override;constnsDisplayWrapList*AsDisplayWrapList()constfinal{returnthis;}nsDisplayWrapList*AsDisplayWrapList()final{returnthis;}voidDestroy(nsDisplayListBuilder*aBuilder)override{mList.DeleteAll(aBuilder);nsPaintedDisplayItem::Destroy(aBuilder);}/** * Creates a new nsDisplayWrapList that holds a pointer to the display list * owned by the given nsDisplayItem. The new nsDisplayWrapList will be added * to the bottom of this item's contents. */voidMergeDisplayListFromItem(nsDisplayListBuilder*aBuilder,constnsDisplayWrapList*aItem);/** * Call this if the wrapped list is changed. */voidUpdateBounds(nsDisplayListBuilder*aBuilder)override{// Clear the clip chain up to the asr, but don't store it, so that we'll// recover it when we reuse the item.if(mClearingClipChain){constDisplayItemClipChain*clip=mState.mClipChain;while(clip&&ActiveScrolledRoot::IsAncestor(GetActiveScrolledRoot(),clip->mASR)){clip=clip->mParent;}SetClipChain(clip,false);}nsRectbuildingRect;mBounds=mListPtr->GetClippedBoundsWithRespectToASR(aBuilder,mActiveScrolledRoot,&buildingRect);// The display list may contain content that's visible outside the visible// rect (i.e. the current dirty rect) passed in when the item was created.// This happens when the dirty rect has been restricted to the visual// overflow rect of a frame for some reason (e.g. when setting up dirty// rects in nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay), but that// frame contains placeholders for out-of-flows that aren't descendants of// the frame.buildingRect.UnionRect(mBaseBuildingRect,buildingRect);SetBuildingRect(buildingRect);}voidHitTest(nsDisplayListBuilder*aBuilder,constnsRect&aRect,HitTestState*aState,nsTArray<nsIFrame*>*aOutFrames)override;nsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;nsRegionGetOpaqueRegion(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;Maybe<nscolor>IsUniform(nsDisplayListBuilder*aBuilder)constoverride;/** * Checks if the given display item can be merged with this item. * @return true if the merging is possible, otherwise false. */virtualboolCanMerge(constnsDisplayItem*aItem)const{returnfalse;}/** * Try to merge with the other item (which is below us in the display * list). This gets used by nsDisplayClip to coalesce clipping operations * (optimization), by nsDisplayOpacity to merge rendering for the same * content element into a single opacity group (correctness), and will be * used by nsDisplayOutline to merge multiple outlines for the same element * (also for correctness). */virtualvoidMerge(constnsDisplayItem*aItem){MOZ_ASSERT(CanMerge(aItem));MOZ_ASSERT(Frame()!=aItem->Frame());MergeFromTrackingMergedFrames(static_cast<constnsDisplayWrapList*>(aItem));}/** * Returns the underlying frames of all display items that have been * merged into this one (excluding this item's own underlying frame) * to aFrames. */constnsTArray<nsIFrame*>&GetMergedFrames()const{returnmMergedFrames;}boolHasMergedFrames()const{return!mMergedFrames.IsEmpty();}boolShouldFlattenAway(nsDisplayListBuilder*aBuilder)override{returntrue;}boolIsInvalid(nsRect&aRect)constoverride{if(mFrame->IsInvalid(aRect)&&aRect.IsEmpty()){returntrue;}nsRecttemp;for(uint32_ti=0;i<mMergedFrames.Length();i++){if(mMergedFrames[i]->IsInvalid(temp)&&temp.IsEmpty()){aRect.SetEmpty();returntrue;}aRect=aRect.Union(temp);}aRect+=ToReferenceFrame();return!aRect.IsEmpty();}nsRectGetComponentAlphaBounds(nsDisplayListBuilder*aBuilder)constoverride;RetainedDisplayList*GetSameCoordinateSystemChildren()constoverride{NS_ASSERTION(mListPtr->IsEmpty()||!ReferenceFrame()||!mListPtr->GetBottom()->ReferenceFrame()||mListPtr->GetBottom()->ReferenceFrame()==ReferenceFrame(),"Children must have same reference frame");returnmListPtr;}RetainedDisplayList*GetChildren()constoverride{returnmListPtr;}int32_tZIndex()constoverride{return(mHasZIndexOverride)?mOverrideZIndex:nsPaintedDisplayItem::ZIndex();}voidSetOverrideZIndex(int32_taZIndex){mHasZIndexOverride=true;mOverrideZIndex=aZIndex;}/** * This creates a copy of this item, but wrapping aItem instead of * our existing list. Only gets called if this item returned nullptr * for GetUnderlyingFrame(). aItem is guaranteed to return non-null from * GetUnderlyingFrame(). */nsDisplayWrapList*WrapWithClone(nsDisplayListBuilder*aBuilder,nsDisplayItem*aItem){MOZ_ASSERT_UNREACHABLE("We never returned nullptr for GetUnderlyingFrame!");returnnullptr;}boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;constActiveScrolledRoot*GetFrameActiveScrolledRoot(){returnmFrameActiveScrolledRoot;}protected:voidMergeFromTrackingMergedFrames(constnsDisplayWrapList*aOther){mBounds.UnionRect(mBounds,aOther->mBounds);nsRectbuildingRect;buildingRect.UnionRect(GetBuildingRect(),aOther->GetBuildingRect());SetBuildingRect(buildingRect);mMergedFrames.AppendElement(aOther->mFrame);mMergedFrames.AppendElements(aOther->mMergedFrames.Clone());}RetainedDisplayListmList;RetainedDisplayList*mListPtr;// The active scrolled root for the frame that created this// wrap list.RefPtr<constActiveScrolledRoot>mFrameActiveScrolledRoot;// The frames from items that have been merged into this item, excluding// this item's own frame.nsTArray<nsIFrame*>mMergedFrames;nsRectmBounds;// Displaylist building rect contributed by this display item itself.// Our mBuildingRect may include the visible areas of children.nsRectmBaseBuildingRect;int32_tmOverrideZIndex;boolmHasZIndexOverride;boolmClearingClipChain=false;};classnsDisplayWrapper:publicnsDisplayWrapList{public:NS_DISPLAY_DECL_NAME("WrapList",TYPE_WRAP_LIST)nsDisplayWrapper(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,constActiveScrolledRoot*aActiveScrolledRoot,boolaClearClipChain=false):nsDisplayWrapList(aBuilder,aFrame,aList,aActiveScrolledRoot,aClearClipChain){}nsDisplayWrapper(constnsDisplayWrapper&aOther)=delete;nsDisplayWrapper(nsDisplayListBuilder*aBuilder,constnsDisplayWrapList&aOther):nsDisplayWrapList(aBuilder,aOther){}voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;private:NS_DISPLAY_ALLOW_CLONING()friendclassnsDisplayListBuilder;friendclassnsDisplayWrapList;};/** * We call WrapDisplayList on the in-flow lists: BorderBackground(), * BlockBorderBackgrounds() and Content(). * We call WrapDisplayItem on each item of Outlines(), PositionedDescendants(), * and Floats(). This is done to support special wrapping processing for frames * that may not be in-flow descendants of the current frame. */classnsDisplayItemWrapper{public:// This is never instantiated directly (it has pure virtual methods), so no// need to count constructors and destructors.boolWrapBorderBackground(){returntrue;}virtualnsDisplayItem*WrapList(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList)=0;virtualnsDisplayItem*WrapItem(nsDisplayListBuilder*aBuilder,nsDisplayItem*aItem)=0;nsresultWrapLists(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constnsDisplayListSet&aIn,constnsDisplayListSet&aOut);nsresultWrapListsInPlace(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constnsDisplayListSet&aLists);protected:nsDisplayItemWrapper()=default;};/** * The standard display item to paint a stacking context with translucency * set by the stacking context root frame's 'opacity' style. */classnsDisplayOpacity:publicnsDisplayWrapList{public:nsDisplayOpacity(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,constActiveScrolledRoot*aActiveScrolledRoot,boolaForEventsOnly,boolaNeedsActiveLayer);nsDisplayOpacity(nsDisplayListBuilder*aBuilder,constnsDisplayOpacity&aOther):nsDisplayWrapList(aBuilder,aOther),mOpacity(aOther.mOpacity),mForEventsOnly(aOther.mForEventsOnly),mNeedsActiveLayer(aOther.mNeedsActiveLayer),mChildOpacityState(ChildOpacityState::Unknown){MOZ_COUNT_CTOR(nsDisplayOpacity);// We should not try to merge flattened opacities.MOZ_ASSERT(aOther.mChildOpacityState!=ChildOpacityState::Applied);}voidHitTest(nsDisplayListBuilder*aBuilder,constnsRect&aRect,HitTestState*aState,nsTArray<nsIFrame*>*aOutFrames)override;MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOpacity)NS_DISPLAY_DECL_NAME("Opacity",TYPE_OPACITY)boolRestoreState()override{if(!nsDisplayWrapList::RestoreState()&&mOpacity==mState.mOpacity){returnfalse;}mOpacity=mState.mOpacity;returntrue;}voidInvalidateCachedChildInfo(nsDisplayListBuilder*aBuilder)override{mChildOpacityState=ChildOpacityState::Unknown;}nsRegionGetOpaqueRegion(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;boolCanMerge(constnsDisplayItem*aItem)constoverride{// items for the same content element should be merged into a single// compositing group// aItem->GetUnderlyingFrame() returns non-null because it's// nsDisplayOpacityreturnHasDifferentFrame(aItem)&&HasSameTypeAndClip(aItem)&&HasSameContent(aItem);}nsDisplayItemGeometry*AllocateGeometry(nsDisplayListBuilder*aBuilder)override{returnnewnsDisplayOpacityGeometry(this,aBuilder,mOpacity);}voidComputeInvalidationRegion(nsDisplayListBuilder*aBuilder,constnsDisplayItemGeometry*aGeometry,nsRegion*aInvalidRegion)constoverride;boolIsInvalid(nsRect&aRect)constoverride{if(mForEventsOnly){returnfalse;}returnnsDisplayWrapList::IsInvalid(aRect);}voidApplyOpacity(nsDisplayListBuilder*aBuilder,floataOpacity,constDisplayItemClipChain*aClip)override;boolCanApplyOpacity()constoverride;boolShouldFlattenAway(nsDisplayListBuilder*aBuilder)override;boolNeedsGeometryUpdates()constoverride{// For flattened nsDisplayOpacity items, ComputeInvalidationRegion() only// handles invalidation for changed |mOpacity|. In order to keep track of// the current bounds of the item for invalidation, nsDisplayOpacityGeometry// for the corresponding DisplayItemData needs to be updated, even if the// reported invalidation region is empty.returnmChildOpacityState==ChildOpacityState::Deferred;}/** * Returns true if ShouldFlattenAway() applied opacity to children. */boolOpacityAppliedToChildren()const{returnmChildOpacityState==ChildOpacityState::Applied;}staticboolNeedsActiveLayer(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,boolaEnforceMinimumSize=true);voidWriteDebugInfo(std::stringstream&aStream)override;boolCanUseAsyncAnimations(nsDisplayListBuilder*aBuilder)override;boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;floatGetOpacity()const{returnmOpacity;}boolCreatesStackingContextHelper()override{returntrue;}private:NS_DISPLAY_ALLOW_CLONING()boolApplyToChildren(nsDisplayListBuilder*aBuilder);boolApplyToFilterOrMask(constboolaUsingLayers);floatmOpacity;boolmForEventsOnly:1;enumclassChildOpacityState:uint8_t{// Our child list has changed since the last time ApplyToChildren was// called.Unknown,// Our children defer opacity handling to us.Deferred,// Opacity is applied to our children.Applied};boolmNeedsActiveLayer:1;#ifndef __GNUC__ChildOpacityStatemChildOpacityState:2;#elseChildOpacityStatemChildOpacityState;#endifstruct{floatmOpacity;}mState{};};classnsDisplayBlendMode:publicnsDisplayWrapList{public:nsDisplayBlendMode(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,StyleBlendaBlendMode,constActiveScrolledRoot*aActiveScrolledRoot,constboolaIsForBackground);nsDisplayBlendMode(nsDisplayListBuilder*aBuilder,constnsDisplayBlendMode&aOther):nsDisplayWrapList(aBuilder,aOther),mBlendMode(aOther.mBlendMode),mIsForBackground(aOther.mIsForBackground){MOZ_COUNT_CTOR(nsDisplayBlendMode);}MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBlendMode)NS_DISPLAY_DECL_NAME("BlendMode",TYPE_BLEND_MODE)nsRegionGetOpaqueRegion(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;voidComputeInvalidationRegion(nsDisplayListBuilder*aBuilder,constnsDisplayItemGeometry*aGeometry,nsRegion*aInvalidRegion)constoverride{// We don't need to compute an invalidation region since we have// LayerTreeInvalidation}boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;boolCanMerge(constnsDisplayItem*aItem)constoverride;boolShouldFlattenAway(nsDisplayListBuilder*aBuilder)override{returnfalse;}gfx::CompositionOpBlendMode();boolCreatesStackingContextHelper()override{returntrue;}protected:StyleBlendmBlendMode;boolmIsForBackground;private:NS_DISPLAY_ALLOW_CLONING()};classnsDisplayTableBlendMode:publicnsDisplayBlendMode{public:nsDisplayTableBlendMode(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,StyleBlendaBlendMode,constActiveScrolledRoot*aActiveScrolledRoot,nsIFrame*aAncestorFrame,constboolaIsForBackground):nsDisplayBlendMode(aBuilder,aFrame,aList,aBlendMode,aActiveScrolledRoot,aIsForBackground),mAncestorFrame(aAncestorFrame){if(aBuilder->IsRetainingDisplayList()){mAncestorFrame->AddDisplayItem(this);}}nsDisplayTableBlendMode(nsDisplayListBuilder*aBuilder,constnsDisplayTableBlendMode&aOther):nsDisplayBlendMode(aBuilder,aOther),mAncestorFrame(aOther.mAncestorFrame){if(aBuilder->IsRetainingDisplayList()){mAncestorFrame->AddDisplayItem(this);}}~nsDisplayTableBlendMode()override{if(mAncestorFrame){mAncestorFrame->RemoveDisplayItem(this);}}NS_DISPLAY_DECL_NAME("TableBlendMode",TYPE_TABLE_BLEND_MODE)nsIFrame*FrameForInvalidation()constoverride{returnmAncestorFrame;}voidRemoveFrame(nsIFrame*aFrame)override{if(aFrame==mAncestorFrame){mAncestorFrame=nullptr;SetDeletedFrame();}nsDisplayBlendMode::RemoveFrame(aFrame);}protected:nsIFrame*mAncestorFrame;private:NS_DISPLAY_ALLOW_CLONING()};classnsDisplayBlendContainer:publicnsDisplayWrapList{public:staticnsDisplayBlendContainer*CreateForMixBlendMode(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,constActiveScrolledRoot*aActiveScrolledRoot);staticnsDisplayBlendContainer*CreateForBackgroundBlendMode(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsIFrame*aSecondaryFrame,nsDisplayList*aList,constActiveScrolledRoot*aActiveScrolledRoot);MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBlendContainer)NS_DISPLAY_DECL_NAME("BlendContainer",TYPE_BLEND_CONTAINER)voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;boolCanMerge(constnsDisplayItem*aItem)constoverride{// Items for the same content element should be merged into a single// compositing group.returnHasDifferentFrame(aItem)&&HasSameTypeAndClip(aItem)&&HasSameContent(aItem)&&mIsForBackground==static_cast<constnsDisplayBlendContainer*>(aItem)->mIsForBackground;}boolShouldFlattenAway(nsDisplayListBuilder*aBuilder)override{returnfalse;}boolCreatesStackingContextHelper()override{returntrue;}protected:nsDisplayBlendContainer(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,constActiveScrolledRoot*aActiveScrolledRoot,boolaIsForBackground);nsDisplayBlendContainer(nsDisplayListBuilder*aBuilder,constnsDisplayBlendContainer&aOther):nsDisplayWrapList(aBuilder,aOther),mIsForBackground(aOther.mIsForBackground){MOZ_COUNT_CTOR(nsDisplayBlendContainer);}// Used to distinguish containers created at building stacking// context or appending background.boolmIsForBackground;private:NS_DISPLAY_ALLOW_CLONING()};classnsDisplayTableBlendContainer:publicnsDisplayBlendContainer{public:NS_DISPLAY_DECL_NAME("TableBlendContainer",TYPE_TABLE_BLEND_CONTAINER)nsIFrame*FrameForInvalidation()constoverride{returnmAncestorFrame;}voidRemoveFrame(nsIFrame*aFrame)override{if(aFrame==mAncestorFrame){mAncestorFrame=nullptr;SetDeletedFrame();}nsDisplayBlendContainer::RemoveFrame(aFrame);}protected:nsDisplayTableBlendContainer(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,constActiveScrolledRoot*aActiveScrolledRoot,boolaIsForBackground,nsIFrame*aAncestorFrame):nsDisplayBlendContainer(aBuilder,aFrame,aList,aActiveScrolledRoot,aIsForBackground),mAncestorFrame(aAncestorFrame){if(aBuilder->IsRetainingDisplayList()){mAncestorFrame->AddDisplayItem(this);}}nsDisplayTableBlendContainer(nsDisplayListBuilder*aBuilder,constnsDisplayTableBlendContainer&aOther):nsDisplayBlendContainer(aBuilder,aOther),mAncestorFrame(aOther.mAncestorFrame){}~nsDisplayTableBlendContainer()override{if(mAncestorFrame){mAncestorFrame->RemoveDisplayItem(this);}}nsIFrame*mAncestorFrame;private:NS_DISPLAY_ALLOW_CLONING()};/** * nsDisplayOwnLayer constructor flags. If we nest this class inside * nsDisplayOwnLayer then we can't forward-declare it up at the top of this * file and that makes it hard to use in all the places that we need to use it. */enumclassnsDisplayOwnLayerFlags{None=0,GenerateSubdocInvalidations=1<<0,GenerateScrollableLayer=1<<1,};MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsDisplayOwnLayerFlags)/** * A display item that has no purpose but to ensure its contents get * their own layer. */classnsDisplayOwnLayer:publicnsDisplayWrapList{public:enumOwnLayerType{OwnLayerForTransformWithRoundedClip,OwnLayerForStackingContext,OwnLayerForImageBoxFrame,OwnLayerForScrollbar,OwnLayerForScrollThumb,OwnLayerForSubdoc,OwnLayerForBoxFrame};/** * @param aFlags eGenerateSubdocInvalidations : * Add UserData to the created ContainerLayer, so that invalidations * for this layer are send to our nsPresContext. * eGenerateScrollableLayer : only valid on nsDisplaySubDocument (and * subclasses), indicates this layer is to be a scrollable layer, so call * ComputeFrameMetrics, etc. * @param aScrollTarget when eVerticalScrollbar or eHorizontalScrollbar * is set in the flags, this parameter should be the ViewID of the * scrollable content this scrollbar is for. */nsDisplayOwnLayer(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,constActiveScrolledRoot*aActiveScrolledRoot,nsDisplayOwnLayerFlagsaFlags=nsDisplayOwnLayerFlags::None,constlayers::ScrollbarData&aScrollbarData=layers::ScrollbarData{},boolaForceActive=true,boolaClearClipChain=false);nsDisplayOwnLayer(nsDisplayListBuilder*aBuilder,constnsDisplayOwnLayer&aOther):nsDisplayWrapList(aBuilder,aOther),mFlags(aOther.mFlags),mScrollbarData(aOther.mScrollbarData),mForceActive(aOther.mForceActive),mWrAnimationId(aOther.mWrAnimationId){MOZ_COUNT_CTOR(nsDisplayOwnLayer);}MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayOwnLayer)NS_DISPLAY_DECL_NAME("OwnLayer",TYPE_OWN_LAYER)boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;boolUpdateScrollData(layers::WebRenderScrollData*aData,layers::WebRenderLayerScrollData*aLayerData)override;voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override{GetChildren()->Paint(aBuilder,aCtx,mFrame->PresContext()->AppUnitsPerDevPixel());}boolCanMerge(constnsDisplayItem*aItem)constoverride{// Don't allow merging, each sublist must have its own layerreturnfalse;}boolShouldFlattenAway(nsDisplayListBuilder*aBuilder)override{returnfalse;}voidWriteDebugInfo(std::stringstream&aStream)override;nsDisplayOwnLayerFlagsGetFlags(){returnmFlags;}boolIsScrollThumbLayer()const;boolIsScrollbarContainer()const;boolIsRootScrollbarContainer()const;boolIsZoomingLayer()const;boolIsFixedPositionLayer()const;boolIsStickyPositionLayer()const;boolHasDynamicToolbar()const;boolCreatesStackingContextHelper()override{returntrue;}protected:nsDisplayOwnLayerFlagsmFlags;/** * If this nsDisplayOwnLayer represents a scroll thumb layer or a * scrollbar container layer, mScrollbarData stores information * about the scrollbar. Otherwise, mScrollbarData will be * default-constructed (in particular with mDirection == Nothing()) * and can be ignored. */layers::ScrollbarDatamScrollbarData;boolmForceActive;uint64_tmWrAnimationId;};/** * A display item for subdocuments. This is more or less the same as * nsDisplayOwnLayer, except that it always populates the FrameMetrics instance * on the ContainerLayer it builds. */classnsDisplaySubDocument:publicnsDisplayOwnLayer{public:nsDisplaySubDocument(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsSubDocumentFrame*aSubDocFrame,nsDisplayList*aList,nsDisplayOwnLayerFlagsaFlags);~nsDisplaySubDocument()override;NS_DISPLAY_DECL_NAME("SubDocument",TYPE_SUBDOCUMENT)nsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;virtualnsSubDocumentFrame*SubDocumentFrame(){returnmSubDocFrame;}boolShouldFlattenAway(nsDisplayListBuilder*aBuilder)override{returnmShouldFlatten;}voidSetShouldFlattenAway(boolaShouldFlatten){mShouldFlatten=aShouldFlatten;}nsRegionGetOpaqueRegion(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;nsIFrame*FrameForInvalidation()constoverride;voidRemoveFrame(nsIFrame*aFrame)override;voidDisown();protected:ViewIDmScrollParentId;boolmForceDispatchToContentRegion{};boolmShouldFlatten;nsSubDocumentFrame*mSubDocFrame;};/** * A display item used to represent sticky position elements. The contents * gets its own layer and creates a stacking context, and the layer will have * position-related metadata set on it. */classnsDisplayStickyPosition:publicnsDisplayOwnLayer{public:nsDisplayStickyPosition(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,constActiveScrolledRoot*aActiveScrolledRoot,constActiveScrolledRoot*aContainerASR,boolaClippedToDisplayPort);nsDisplayStickyPosition(nsDisplayListBuilder*aBuilder,constnsDisplayStickyPosition&aOther):nsDisplayOwnLayer(aBuilder,aOther),mContainerASR(aOther.mContainerASR),mClippedToDisplayPort(aOther.mClippedToDisplayPort){MOZ_COUNT_CTOR(nsDisplayStickyPosition);}MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayStickyPosition)voidSetClipChain(constDisplayItemClipChain*aClipChain,boolaStore)override;boolIsClippedToDisplayPort()const{returnmClippedToDisplayPort;}NS_DISPLAY_DECL_NAME("StickyPosition",TYPE_STICKY_POSITION)voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override{GetChildren()->Paint(aBuilder,aCtx,mFrame->PresContext()->AppUnitsPerDevPixel());}boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;boolUpdateScrollData(layers::WebRenderScrollData*aData,layers::WebRenderLayerScrollData*aLayerData)override;constActiveScrolledRoot*GetContainerASR()const{returnmContainerASR;}boolCreatesStackingContextHelper()override{returntrue;}private:NS_DISPLAY_ALLOW_CLONING()voidCalculateLayerScrollRanges(StickyScrollContainer*aStickyScrollContainer,floataAppUnitsPerDevPixel,floataScaleX,floataScaleY,LayerRectAbsolute&aStickyOuter,LayerRectAbsolute&aStickyInner);StickyScrollContainer*GetStickyScrollContainer();// This stores the ASR that this sticky container item would have assuming it// has no fixed descendants. This may be the same as the ASR returned by// GetActiveScrolledRoot(), or it may be a descendant of that.RefPtr<constActiveScrolledRoot>mContainerASR;// This flag tracks if this sticky item is just clipped to the enclosing// scrollframe's displayport, or if there are additional clips in play. In// the former case, we can skip setting the displayport clip as the scrolled-// clip of the corresponding layer. This allows sticky items to remain// unclipped when the enclosing scrollframe is scrolled past the displayport.// i.e. when the rest of the scrollframe checkerboards, the sticky item will// not. This makes sense to do because the sticky item has abnormal scrolling// behavior and may still be visible even if the rest of the scrollframe is// checkerboarded. Note that the sticky item will still be subject to the// scrollport clip.boolmClippedToDisplayPort;};classnsDisplayFixedPosition:publicnsDisplayOwnLayer{public:nsDisplayFixedPosition(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,constActiveScrolledRoot*aActiveScrolledRoot,constActiveScrolledRoot*aContainerASR);nsDisplayFixedPosition(nsDisplayListBuilder*aBuilder,constnsDisplayFixedPosition&aOther):nsDisplayOwnLayer(aBuilder,aOther),mAnimatedGeometryRootForScrollMetadata(aOther.mAnimatedGeometryRootForScrollMetadata),mContainerASR(aOther.mContainerASR),mIsFixedBackground(aOther.mIsFixedBackground){MOZ_COUNT_CTOR(nsDisplayFixedPosition);}staticnsDisplayFixedPosition*CreateForFixedBackground(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsIFrame*aSecondaryFrame,nsDisplayBackgroundImage*aImage,constuint16_taIndex);MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayFixedPosition)NS_DISPLAY_DECL_NAME("FixedPosition",TYPE_FIXED_POSITION)voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override{GetChildren()->Paint(aBuilder,aCtx,mFrame->PresContext()->AppUnitsPerDevPixel());}boolShouldFixToViewport(nsDisplayListBuilder*aBuilder)constoverride{returnmIsFixedBackground;}AnimatedGeometryRoot*AnimatedGeometryRootForScrollMetadata()constoverride{returnmAnimatedGeometryRootForScrollMetadata;}boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;boolUpdateScrollData(layers::WebRenderScrollData*aData,layers::WebRenderLayerScrollData*aLayerData)override;voidWriteDebugInfo(std::stringstream&aStream)override;protected:// For background-attachment:fixednsDisplayFixedPosition(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList);voidInit(nsDisplayListBuilder*aBuilder);ViewIDGetScrollTargetId();RefPtr<AnimatedGeometryRoot>mAnimatedGeometryRootForScrollMetadata;RefPtr<constActiveScrolledRoot>mContainerASR;boolmIsFixedBackground;private:NS_DISPLAY_ALLOW_CLONING()};classnsDisplayTableFixedPosition:publicnsDisplayFixedPosition{public:NS_DISPLAY_DECL_NAME("TableFixedPosition",TYPE_TABLE_FIXED_POSITION)nsIFrame*FrameForInvalidation()constoverride{returnmAncestorFrame;}voidRemoveFrame(nsIFrame*aFrame)override{if(aFrame==mAncestorFrame){mAncestorFrame=nullptr;SetDeletedFrame();}nsDisplayFixedPosition::RemoveFrame(aFrame);}protected:nsDisplayTableFixedPosition(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,nsIFrame*aAncestorFrame);nsDisplayTableFixedPosition(nsDisplayListBuilder*aBuilder,constnsDisplayTableFixedPosition&aOther):nsDisplayFixedPosition(aBuilder,aOther),mAncestorFrame(aOther.mAncestorFrame){}~nsDisplayTableFixedPosition()override{if(mAncestorFrame){mAncestorFrame->RemoveDisplayItem(this);}}nsIFrame*mAncestorFrame;private:NS_DISPLAY_ALLOW_CLONING()};/** * This creates an empty scrollable layer. It has no child layers. * It is used to record the existence of a scrollable frame in the layer * tree. */classnsDisplayScrollInfoLayer:publicnsDisplayWrapList{public:nsDisplayScrollInfoLayer(nsDisplayListBuilder*aBuilder,nsIFrame*aScrolledFrame,nsIFrame*aScrollFrame,constgfx::CompositorHitTestInfo&aHitInfo,constnsRect&aHitArea);MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayScrollInfoLayer)NS_DISPLAY_DECL_NAME("ScrollInfoLayer",TYPE_SCROLL_INFO_LAYER)nsRegionGetOpaqueRegion(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride{*aSnap=false;returnnsRegion();}voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override{return;}boolShouldFlattenAway(nsDisplayListBuilder*aBuilder)override{returnfalse;}voidWriteDebugInfo(std::stringstream&aStream)override;UniquePtr<layers::ScrollMetadata>ComputeScrollMetadata(nsDisplayListBuilder*aBuilder,layers::WebRenderLayerManager*aLayerManager);boolUpdateScrollData(layers::WebRenderScrollData*aData,layers::WebRenderLayerScrollData*aLayerData)override;boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;protected:nsIFrame*mScrollFrame;nsIFrame*mScrolledFrame;ViewIDmScrollParentId;gfx::CompositorHitTestInfomHitInfo;nsRectmHitArea;};/** * nsDisplayZoom is used for subdocuments that have a different full zoom than * their parent documents. This item creates a container layer. */classnsDisplayZoom:publicnsDisplaySubDocument{public:/** * @param aFrame is the root frame of the subdocument. * @param aList contains the display items for the subdocument. * @param aAPD is the app units per dev pixel ratio of the subdocument. * @param aParentAPD is the app units per dev pixel ratio of the parent * document. * @param aFlags eGenerateSubdocInvalidations : * Add UserData to the created ContainerLayer, so that invalidations * for this layer are send to our nsPresContext. */nsDisplayZoom(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsSubDocumentFrame*aSubDocFrame,nsDisplayList*aList,int32_taAPD,int32_taParentAPD,nsDisplayOwnLayerFlagsaFlags=nsDisplayOwnLayerFlags::None);MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayZoom)NS_DISPLAY_DECL_NAME("Zoom",TYPE_ZOOM)nsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;voidHitTest(nsDisplayListBuilder*aBuilder,constnsRect&aRect,HitTestState*aState,nsTArray<nsIFrame*>*aOutFrames)override;// Get the app units per dev pixel ratio of the child document.int32_tGetChildAppUnitsPerDevPixel(){returnmAPD;}// Get the app units per dev pixel ratio of the parent document.int32_tGetParentAppUnitsPerDevPixel(){returnmParentAPD;}private:int32_tmAPD,mParentAPD;};/** * nsDisplayAsyncZoom is used for APZ zooming. It wraps the contents of the * root content document's scroll frame, including fixed position content. It * does not contain the scroll frame's scrollbars. It is clipped to the scroll * frame's scroll port clip. It is not scrolled; only its non-fixed contents * are scrolled. This item creates a container layer. */classnsDisplayAsyncZoom:publicnsDisplayOwnLayer{public:nsDisplayAsyncZoom(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,constActiveScrolledRoot*aActiveScrolledRoot,layers::FrameMetrics::ViewIDaViewID);nsDisplayAsyncZoom(nsDisplayListBuilder*aBuilder,constnsDisplayAsyncZoom&aOther):nsDisplayOwnLayer(aBuilder,aOther),mViewID(aOther.mViewID){MOZ_COUNT_CTOR(nsDisplayAsyncZoom);}#ifdef NS_BUILD_REFCNT_LOGGINGvirtual~nsDisplayAsyncZoom();#endifNS_DISPLAY_DECL_NAME("AsyncZoom",TYPE_ASYNC_ZOOM)voidHitTest(nsDisplayListBuilder*aBuilder,constnsRect&aRect,HitTestState*aState,nsTArray<nsIFrame*>*aOutFrames)override;boolUpdateScrollData(layers::WebRenderScrollData*aData,layers::WebRenderLayerScrollData*aLayerData)override;protected:layers::FrameMetrics::ViewIDmViewID;};/** * A base class for different effects types. */classnsDisplayEffectsBase:publicnsDisplayWrapList{public:nsDisplayEffectsBase(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,constActiveScrolledRoot*aActiveScrolledRoot,boolaClearClipChain=false);nsDisplayEffectsBase(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList);nsDisplayEffectsBase(nsDisplayListBuilder*aBuilder,constnsDisplayEffectsBase&aOther):nsDisplayWrapList(aBuilder,aOther),mEffectsBounds(aOther.mEffectsBounds),mHandleOpacity(aOther.mHandleOpacity){MOZ_COUNT_CTOR(nsDisplayEffectsBase);}MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayEffectsBase)nsRegionGetOpaqueRegion(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;voidHitTest(nsDisplayListBuilder*aBuilder,constnsRect&aRect,HitTestState*aState,nsTArray<nsIFrame*>*aOutFrames)override;boolRestoreState()override{if(!nsDisplayWrapList::RestoreState()&&!mHandleOpacity){returnfalse;}mHandleOpacity=false;returntrue;}boolShouldFlattenAway(nsDisplayListBuilder*aBuilder)override{returnfalse;}virtualvoidSelectOpacityOptimization(constbool/* aUsingLayers */){SetHandleOpacity();}boolShouldHandleOpacity()const{returnmHandleOpacity;}gfxRectBBoxInUserSpace()const;gfxPointUserSpaceOffset()const;voidComputeInvalidationRegion(nsDisplayListBuilder*aBuilder,constnsDisplayItemGeometry*aGeometry,nsRegion*aInvalidRegion)constoverride;protected:voidSetHandleOpacity(){mHandleOpacity=true;}boolValidateSVGFrame();// relative to mFramensRectmEffectsBounds;// True if we need to handle css opacity in this display item.boolmHandleOpacity;};/** * A display item to paint a stacking context with 'mask' and 'clip-path' * effects set by the stacking context root frame's style. The 'mask' and * 'clip-path' properties may both contain multiple masks and clip paths, * respectively. * * Note that 'mask' and 'clip-path' may just contain CSS simple-images and CSS * basic shapes, respectively. That is, they don't necessarily reference * resources such as SVG 'mask' and 'clipPath' elements. */classnsDisplayMasksAndClipPaths:publicnsDisplayEffectsBase{public:nsDisplayMasksAndClipPaths(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,constActiveScrolledRoot*aActiveScrolledRoot);nsDisplayMasksAndClipPaths(nsDisplayListBuilder*aBuilder,constnsDisplayMasksAndClipPaths&aOther):nsDisplayEffectsBase(aBuilder,aOther),mDestRects(aOther.mDestRects.Clone()){MOZ_COUNT_CTOR(nsDisplayMasksAndClipPaths);}MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayMasksAndClipPaths)NS_DISPLAY_DECL_NAME("Mask",TYPE_MASK)boolCanMerge(constnsDisplayItem*aItem)constoverride;voidMerge(constnsDisplayItem*aItem)override{nsDisplayWrapList::Merge(aItem);constnsDisplayMasksAndClipPaths*other=static_cast<constnsDisplayMasksAndClipPaths*>(aItem);mEffectsBounds.UnionRect(mEffectsBounds,other->mEffectsBounds+other->mFrame->GetOffsetTo(mFrame));}voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;nsDisplayItemGeometry*AllocateGeometry(nsDisplayListBuilder*aBuilder)override{returnnewnsDisplayMasksAndClipPathsGeometry(this,aBuilder);}voidComputeInvalidationRegion(nsDisplayListBuilder*aBuilder,constnsDisplayItemGeometry*aGeometry,nsRegion*aInvalidRegion)constoverride;#ifdef MOZ_DUMP_PAINTINGvoidPrintEffects(nsACString&aTo);#endifboolIsValidMask();voidPaintWithContentsPaintCallback(nsDisplayListBuilder*aBuilder,gfxContext*aCtx,conststd::function<void()>&aPaintChildren);/* * Paint mask onto aMaskContext in mFrame's coordinate space and * return whether the mask layer was painted successfully. */boolPaintMask(nsDisplayListBuilder*aBuilder,gfxContext*aMaskContext,bool*aMaskPainted=nullptr);constnsTArray<nsRect>&GetDestRects(){returnmDestRects;}voidSelectOpacityOptimization(constboolaUsingLayers)override;boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;Maybe<nsRect>GetClipWithRespectToASR(nsDisplayListBuilder*aBuilder,constActiveScrolledRoot*aASR)constoverride;boolCreatesStackingContextHelper()override{returntrue;}private:NS_DISPLAY_ALLOW_CLONING()// According to mask property and the capability of aManager, determine// whether we can paint the mask onto a dedicate mask layer.boolCanPaintOnMaskLayer(LayerManager*aManager);nsTArray<nsRect>mDestRects;boolmApplyOpacityWithSimpleClipPath;};classnsDisplayBackdropRootContainer:publicnsDisplayWrapList{public:nsDisplayBackdropRootContainer(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,constActiveScrolledRoot*aActiveScrolledRoot):nsDisplayWrapList(aBuilder,aFrame,aList,aActiveScrolledRoot,true){MOZ_COUNT_CTOR(nsDisplayBackdropRootContainer);}MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBackdropRootContainer)NS_DISPLAY_DECL_NAME("BackdropRootContainer",TYPE_BACKDROP_ROOT_CONTAINER)voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;boolShouldFlattenAway(nsDisplayListBuilder*aBuilder)override{return!aBuilder->IsPaintingForWebRender();}boolCreatesStackingContextHelper()override{returntrue;}};classnsDisplayBackdropFilters:publicnsDisplayWrapList{public:nsDisplayBackdropFilters(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,constnsRect&aBackdropRect):nsDisplayWrapList(aBuilder,aFrame,aList),mBackdropRect(aBackdropRect){MOZ_COUNT_CTOR(nsDisplayBackdropFilters);}MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayBackdropFilters)NS_DISPLAY_DECL_NAME("BackdropFilter",TYPE_BACKDROP_FILTER)boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;staticboolCanCreateWebRenderCommands(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame);boolShouldFlattenAway(nsDisplayListBuilder*aBuilder)override{return!aBuilder->IsPaintingForWebRender();}boolCreatesStackingContextHelper()override{returntrue;}private:nsRectmBackdropRect;};/** * A display item to paint a stacking context with filter effects set by the * stacking context root frame's style. * * Note that the filters may just be simple CSS filter functions. That is, * they won't necessarily be references to SVG 'filter' elements. */classnsDisplayFilters:publicnsDisplayEffectsBase{public:nsDisplayFilters(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList);nsDisplayFilters(nsDisplayListBuilder*aBuilder,constnsDisplayFilters&aOther):nsDisplayEffectsBase(aBuilder,aOther),mEffectsBounds(aOther.mEffectsBounds){MOZ_COUNT_CTOR(nsDisplayFilters);}MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayFilters)NS_DISPLAY_DECL_NAME("Filter",TYPE_FILTER)boolCanMerge(constnsDisplayItem*aItem)constoverride{// Items for the same content element should be merged into a single// compositing group.returnHasDifferentFrame(aItem)&&HasSameTypeAndClip(aItem)&&HasSameContent(aItem);}voidMerge(constnsDisplayItem*aItem)override{nsDisplayWrapList::Merge(aItem);constnsDisplayFilters*other=static_cast<constnsDisplayFilters*>(aItem);mEffectsBounds.UnionRect(mEffectsBounds,other->mEffectsBounds+other->mFrame->GetOffsetTo(mFrame));}voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;nsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride{*aSnap=false;returnmEffectsBounds+ToReferenceFrame();}nsDisplayItemGeometry*AllocateGeometry(nsDisplayListBuilder*aBuilder)override{returnnewnsDisplayFiltersGeometry(this,aBuilder);}voidComputeInvalidationRegion(nsDisplayListBuilder*aBuilder,constnsDisplayItemGeometry*aGeometry,nsRegion*aInvalidRegion)constoverride;#ifdef MOZ_DUMP_PAINTINGvoidPrintEffects(nsACString&aTo);#endifvoidPaintWithContentsPaintCallback(nsDisplayListBuilder*aBuilder,gfxContext*aCtx,conststd::function<void(gfxContext*aContext)>&aPaintChildren);boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;boolCanCreateWebRenderCommands();boolCreatesStackingContextHelper()override{returntrue;}private:NS_DISPLAY_ALLOW_CLONING()// relative to mFramensRectmEffectsBounds;};/* A display item that applies a transformation to all of its descendant * elements. This wrapper should only be used if there is a transform applied * to the root element. * * The reason that a "bounds" rect is involved in transform calculations is * because CSS-transforms allow percentage values for the x and y components * of <translation-value>s, where percentages are percentages of the element's * border box. * * INVARIANT: The wrapped frame is transformed or we supplied a transform getter * function. * INVARIANT: The wrapped frame is non-null. */classnsDisplayTransform:publicnsPaintedDisplayItem{usingMatrix4x4=gfx::Matrix4x4;usingMatrix4x4Flagged=gfx::Matrix4x4Flagged;usingTransformReferenceBox=nsStyleTransformMatrix::TransformReferenceBox;public:enumclassPrerenderDecision:uint8_t{No,Full,Partial};enum{WithTransformGetter,};/* Constructor accepts a display list, empties it, and wraps it up. It also * ferries the underlying frame to the nsDisplayItem constructor. */nsDisplayTransform(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,constnsRect&aChildrenBuildingRect);nsDisplayTransform(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,constnsRect&aChildrenBuildingRect,PrerenderDecisionaPrerenderDecision);nsDisplayTransform(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList,constnsRect&aChildrenBuildingRect,decltype(WithTransformGetter));MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayTransform)NS_DISPLAY_DECL_NAME("nsDisplayTransform",TYPE_TRANSFORM)boolRestoreState()override{if(!nsPaintedDisplayItem::RestoreState()&&!mShouldFlatten){returnfalse;}mShouldFlatten=false;returntrue;}voidUpdateBounds(nsDisplayListBuilder*aBuilder)override;/** * This function updates bounds for items with a frame establishing * 3D rendering context. */voidUpdateBoundsFor3D(nsDisplayListBuilder*aBuilder);voidDoUpdateBoundsPreserves3D(nsDisplayListBuilder*aBuilder)override;voidDestroy(nsDisplayListBuilder*aBuilder)override{GetChildren()->DeleteAll(aBuilder);nsPaintedDisplayItem::Destroy(aBuilder);}nsRectGetComponentAlphaBounds(nsDisplayListBuilder*aBuilder)constoverride;RetainedDisplayList*GetChildren()constoverride{return&mChildren;}nsRectGetUntransformedBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride{*aSnap=false;returnmChildBounds;}constnsRect&GetUntransformedPaintRect()constoverride{returnmChildrenBuildingRect;}boolShouldFlattenAway(nsDisplayListBuilder*aBuilder)override;voidHitTest(nsDisplayListBuilder*aBuilder,constnsRect&aRect,HitTestState*aState,nsTArray<nsIFrame*>*aOutFrames)override;nsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;nsRegionGetOpaqueRegion(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx,constMaybe<gfx::Polygon>&aPolygon);boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;boolUpdateScrollData(layers::WebRenderScrollData*aData,layers::WebRenderLayerScrollData*aLayerData)override;nsDisplayItemGeometry*AllocateGeometry(nsDisplayListBuilder*aBuilder)override{returnnewnsDisplayTransformGeometry(this,aBuilder,GetTransformForRendering(),mFrame->PresContext()->AppUnitsPerDevPixel());}voidComputeInvalidationRegion(nsDisplayListBuilder*aBuilder,constnsDisplayItemGeometry*aGeometry,nsRegion*aInvalidRegion)constoverride{constnsDisplayTransformGeometry*geometry=static_cast<constnsDisplayTransformGeometry*>(aGeometry);// This code is only called for flattened, inactive transform items.// Only check if the transform has changed. The bounds invalidation should// be handled by the children themselves.if(!geometry->mTransform.FuzzyEqual(GetTransformForRendering())){boolsnap;aInvalidRegion->Or(GetBounds(aBuilder,&snap),geometry->mBounds);}}boolNeedsGeometryUpdates()constoverride{returnmShouldFlatten;}constnsIFrame*ReferenceFrameForChildren()constoverride{// If we were created using a transform-getter, then we don't// belong to a transformed frame, and aren't a reference frame// for our children.if(!mHasTransformGetter){returnmFrame;}returnnsPaintedDisplayItem::ReferenceFrameForChildren();}AnimatedGeometryRoot*AnimatedGeometryRootForScrollMetadata()constoverride{returnmAnimatedGeometryRootForScrollMetadata;}constnsRect&GetBuildingRectForChildren()constoverride{returnmChildrenBuildingRect;}enum{INDEX_MAX=UINT32_MAX>>TYPE_BITS};/** * We include the perspective matrix from our containing block for the * purposes of visibility calculations, but we exclude it from the transform * we set on the layer (for rendering), since there will be an * nsDisplayPerspective created for that. */constMatrix4x4Flagged&GetTransform()const;constMatrix4x4Flagged&GetInverseTransform()const;boolShouldSkipTransform(nsDisplayListBuilder*aBuilder)const;Matrix4x4GetTransformForRendering(LayoutDevicePoint*aOutOrigin=nullptr)const;/** * Return the transform that is aggregation of all transform on the * preserves3d chain. */constMatrix4x4&GetAccumulatedPreserved3DTransform(nsDisplayListBuilder*aBuilder);floatGetHitDepthAtPoint(nsDisplayListBuilder*aBuilder,constnsPoint&aPoint);/** * TransformRect takes in as parameters a rectangle (in aFrame's coordinate * space) and returns the smallest rectangle (in aFrame's coordinate space) * containing the transformed image of that rectangle. That is, it takes * the four corners of the rectangle, transforms them according to the * matrix associated with the specified frame, then returns the smallest * rectangle containing the four transformed points. * * @param untransformedBounds The rectangle (in app units) to transform. * @param aFrame The frame whose transformation should be applied. This * function raises an assertion if aFrame is null or doesn't have a * transform applied to it. * @param aRefBox the reference box to use, which would usually be just * TransformReferemceBox(aFrame), but callers may override it if * needed. */staticnsRectTransformRect(constnsRect&aUntransformedBounds,constnsIFrame*aFrame,TransformReferenceBox&aRefBox);/* UntransformRect is like TransformRect, except that it inverts the * transform. */staticboolUntransformRect(constnsRect&aTransformedBounds,constnsRect&aChildBounds,constnsIFrame*aFrame,nsRect*aOutRect);boolUntransformRect(nsDisplayListBuilder*aBuilder,constnsRect&aRect,nsRect*aOutRect)const;boolUntransformBuildingRect(nsDisplayListBuilder*aBuilder,nsRect*aOutRect)const{returnUntransformRect(aBuilder,GetBuildingRect(),aOutRect);}boolUntransformPaintRect(nsDisplayListBuilder*aBuilder,nsRect*aOutRect)const{returnUntransformRect(aBuilder,GetPaintRect(),aOutRect);}staticgfx::Point3DGetDeltaToTransformOrigin(constnsIFrame*aFrame,TransformReferenceBox&,floataAppUnitsPerPixel);/* * Returns true if aFrame has perspective applied from its containing * block. * Returns the matrix to append to apply the persective (taking * perspective-origin into account), relative to aFrames coordinate * space). * aOutMatrix is assumed to be the identity matrix, and isn't explicitly * cleared. */staticboolComputePerspectiveMatrix(constnsIFrame*aFrame,floataAppUnitsPerPixel,Matrix4x4&aOutMatrix);structMOZ_STACK_CLASSFrameTransformProperties{FrameTransformProperties(constnsIFrame*aFrame,TransformReferenceBox&aRefBox,floataAppUnitsPerPixel);FrameTransformProperties(constStyleTranslate&aTranslate,constStyleRotate&aRotate,constStyleScale&aScale,constStyleTransform&aTransform,constMaybe<ResolvedMotionPathData>&aMotion,constgfx::Point3D&aToTransformOrigin):mFrame(nullptr),mTranslate(aTranslate),mRotate(aRotate),mScale(aScale),mTransform(aTransform),mMotion(aMotion),mToTransformOrigin(aToTransformOrigin){}boolHasTransform()const{return!mTranslate.IsNone()||!mRotate.IsNone()||!mScale.IsNone()||!mTransform.IsNone()||mMotion.isSome();}constnsIFrame*mFrame;constStyleTranslate&mTranslate;constStyleRotate&mRotate;constStyleScale&mScale;constStyleTransform&mTransform;constMaybe<ResolvedMotionPathData>mMotion;constgfx::Point3DmToTransformOrigin;};/** * Given a frame with the transform property or an SVG transform, * returns the transformation matrix for that frame. * * @param aFrame The frame to get the matrix from. * @param aOrigin Relative to which point this transform should be applied. * @param aAppUnitsPerPixel The number of app units per graphics unit. * @param aBoundsOverride [optional] If this is nullptr (the default), the * computation will use the value of TransformReferenceBox(aFrame). * Otherwise, it will use the value of aBoundsOverride. This is * mostly for internal use and in most cases you will not need to * specify a value. * @param aFlags OFFSET_BY_ORIGIN The resulting matrix will be translated * by aOrigin. This translation is applied *before* the CSS transform. * @param aFlags INCLUDE_PRESERVE3D_ANCESTORS The computed transform will * include the transform of any ancestors participating in the same * 3d rendering context. * @param aFlags INCLUDE_PERSPECTIVE The resulting matrix will include the * perspective transform from the containing block if applicable. */enum{OFFSET_BY_ORIGIN=1<<0,INCLUDE_PRESERVE3D_ANCESTORS=1<<1,INCLUDE_PERSPECTIVE=1<<2,};staticMatrix4x4GetResultingTransformMatrix(constnsIFrame*aFrame,constnsPoint&aOrigin,floataAppUnitsPerPixel,uint32_taFlags);staticMatrix4x4GetResultingTransformMatrix(constFrameTransformProperties&aProperties,TransformReferenceBox&,floataAppUnitsPerPixel);structPrerenderInfo{boolCanUseAsyncAnimations()const{returnmDecision!=PrerenderDecision::No&&mHasAnimations;}PrerenderDecisionmDecision=PrerenderDecision::No;boolmHasAnimations=true;};/** * Decide whether we should prerender some or all of the contents of the * transformed frame even when it's not completely visible (yet). * Return PrerenderDecision::Full if the entire contents should be * prerendered, PrerenderDecision::Partial if some but not all of the * contents should be prerendered, or PrerenderDecision::No if only the * visible area should be rendered. * |mNoAffectDecisionInPreserve3D| is set if the prerender decision should not * affect the decision on other frames in the preserve 3d tree. * |aDirtyRect| is updated to the area that should be prerendered. */staticPrerenderInfoShouldPrerenderTransformedContent(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsRect*aDirtyRect);boolCanUseAsyncAnimations(nsDisplayListBuilder*aBuilder)override;boolMayBeAnimated(nsDisplayListBuilder*aBuilder,boolaEnforceMinimumSize=true)const;voidWriteDebugInfo(std::stringstream&aStream)override;/** * This item is an additional item as the boundary between parent * and child 3D rendering context. * \see nsIFrame::BuildDisplayListForStackingContext(). */boolIsTransformSeparator()const{returnmIsTransformSeparator;}/** * This item is the boundary between parent and child 3D rendering * context. */boolIsLeafOf3DContext()const{return(IsTransformSeparator()||(!mFrame->Extend3DContext()&&Combines3DTransformWithAncestors()));}/** * The backing frame of this item participates a 3D rendering * context. */boolIsParticipating3DContext()const{returnmFrame->Extend3DContext()||Combines3DTransformWithAncestors();}boolIsPartialPrerender()const{returnmPrerenderDecision==PrerenderDecision::Partial;}voidAddSizeOfExcludingThis(nsWindowSizes&)constoverride;boolCreatesStackingContextHelper()override{returntrue;}private:voidComputeBounds(nsDisplayListBuilder*aBuilder);nsRectTransformUntransformedBounds(nsDisplayListBuilder*aBuilder,constMatrix4x4Flagged&aMatrix)const;voidUpdateUntransformedBounds(nsDisplayListBuilder*aBuilder);voidSetReferenceFrameToAncestor(nsDisplayListBuilder*aBuilder);voidInit(nsDisplayListBuilder*aBuilder,nsDisplayList*aChildren);staticMatrix4x4GetResultingTransformMatrixInternal(constFrameTransformProperties&aProperties,TransformReferenceBox&aRefBox,constnsPoint&aOrigin,floataAppUnitsPerPixel,uint32_taFlags);voidCollect3DTransformLeaves(nsDisplayListBuilder*aBuilder,nsTArray<nsDisplayTransform*>&aLeaves);usingTransformPolygon=layers::BSPPolygon<nsDisplayTransform>;voidCollectSorted3DTransformLeaves(nsDisplayListBuilder*aBuilder,nsTArray<TransformPolygon>&aLeaves);mutableMaybe<Matrix4x4Flagged>mTransform;mutableMaybe<Matrix4x4Flagged>mInverseTransform;// Accumulated transform of ancestors on the preserves-3d chain.UniquePtr<Matrix4x4>mTransformPreserves3D;RefPtr<AnimatedGeometryRoot>mAnimatedGeometryRootForChildren;RefPtr<AnimatedGeometryRoot>mAnimatedGeometryRootForScrollMetadata;nsRectmChildrenBuildingRect;mutableRetainedDisplayListmChildren;// The untransformed bounds of |mChildren|.nsRectmChildBounds;// The transformed bounds of this display item.nsRectmBounds;PrerenderDecisionmPrerenderDecision:8;// This item is a separator between 3D rendering contexts, and// mTransform have been presetted by the constructor.// This also forces us not to extend the 3D context. Since we don't create a// transform item, a container layer, for every frame in a preserves3d// context, the transform items of a child preserves3d context may extend the// parent context unintendedly if the root of the child preserves3d context// doesn't create a transform item.boolmIsTransformSeparator:1;// True if this nsDisplayTransform should get flattenedboolmShouldFlatten:1;// True if we have a transform getter.boolmHasTransformGetter:1;};/* A display item that applies a perspective transformation to a single * nsDisplayTransform child item. We keep this as a separate item since the * perspective-origin is relative to an ancestor of the transformed frame, and * APZ can scroll the child separately. */classnsDisplayPerspective:publicnsPaintedDisplayItem{public:nsDisplayPerspective(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList);~nsDisplayPerspective()override=default;NS_DISPLAY_DECL_NAME("nsDisplayPerspective",TYPE_PERSPECTIVE)voidDestroy(nsDisplayListBuilder*aBuilder)override{mList.DeleteAll(aBuilder);nsPaintedDisplayItem::Destroy(aBuilder);}voidHitTest(nsDisplayListBuilder*aBuilder,constnsRect&aRect,HitTestState*aState,nsTArray<nsIFrame*>*aOutFrames)override{returnGetChildren()->HitTest(aBuilder,aRect,aState,aOutFrames);}nsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride{*aSnap=false;returnGetChildren()->GetClippedBoundsWithRespectToASR(aBuilder,mActiveScrolledRoot);}voidComputeInvalidationRegion(nsDisplayListBuilder*aBuilder,constnsDisplayItemGeometry*aGeometry,nsRegion*aInvalidRegion)constoverride{}nsRegionGetOpaqueRegion(nsDisplayListBuilder*aBuilder,bool*aSnap)constoverride;boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;RetainedDisplayList*GetSameCoordinateSystemChildren()constoverride{return&mList;}RetainedDisplayList*GetChildren()constoverride{return&mList;}nsRectGetComponentAlphaBounds(nsDisplayListBuilder*aBuilder)constoverride{returnGetChildren()->GetComponentAlphaBounds(aBuilder);}voidDoUpdateBoundsPreserves3D(nsDisplayListBuilder*aBuilder)override{if(GetChildren()->GetTop()){static_cast<nsDisplayTransform*>(GetChildren()->GetTop())->DoUpdateBoundsPreserves3D(aBuilder);}}boolCreatesStackingContextHelper()override{returntrue;}private:mutableRetainedDisplayListmList;};classnsDisplayTextGeometry;/** * This class adds basic support for limiting the rendering (in the inline axis * of the writing mode) to the part inside the specified edges. * The two members, mVisIStartEdge and mVisIEndEdge, are relative to the edges * of the frame's scrollable overflow rectangle and are the amount to suppress * on each side. * * Setting none, both or only one edge is allowed. * The values must be non-negative. * The default value for both edges is zero, which means everything is painted. */classnsDisplayTextfinal:publicnsPaintedDisplayItem{public:nsDisplayText(nsDisplayListBuilder*aBuilder,nsTextFrame*aFrame);MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayText)NS_DISPLAY_DECL_NAME("Text",TYPE_TEXT)boolRestoreState()final{if(!nsPaintedDisplayItem::RestoreState()&&mOpacity==1.0f){returnfalse;}mOpacity=1.0f;returntrue;}nsRectGetBounds(nsDisplayListBuilder*aBuilder,bool*aSnap)constfinal{*aSnap=false;returnmBounds;}voidHitTest(nsDisplayListBuilder*aBuilder,constnsRect&aRect,HitTestState*aState,nsTArray<nsIFrame*>*aOutFrames)final{if(nsRect(ToReferenceFrame(),mFrame->GetSize()).Intersects(aRect)){aOutFrames->AppendElement(mFrame);}}boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)final;voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)final;nsRectGetComponentAlphaBounds(nsDisplayListBuilder*aBuilder)constfinal{if(gfxPlatform::GetPlatform()->RespectsFontStyleSmoothing()){// On OS X, web authors can turn off subpixel text rendering using the// CSS property -moz-osx-font-smoothing. If they do that, we don't need// to use component alpha layers for the affected text.if(mFrame->StyleFont()->mFont.smoothing==NS_FONT_SMOOTHING_GRAYSCALE){returnnsRect();}}boolsnap;returnGetBounds(aBuilder,&snap);}nsDisplayItemGeometry*AllocateGeometry(nsDisplayListBuilder*aBuilder)final;voidComputeInvalidationRegion(nsDisplayListBuilder*aBuilder,constnsDisplayItemGeometry*aGeometry,nsRegion*aInvalidRegion)constfinal;voidRenderToContext(gfxContext*aCtx,nsDisplayListBuilder*aBuilder,boolaIsRecording=false);boolCanApplyOpacity()constfinal;voidApplyOpacity(nsDisplayListBuilder*aBuilder,floataOpacity,constDisplayItemClipChain*aClip)final{NS_ASSERTION(CanApplyOpacity(),"ApplyOpacity should be allowed");mOpacity=aOpacity;IntersectClip(aBuilder,aClip,false);}voidWriteDebugInfo(std::stringstream&aStream)final;staticnsDisplayText*CheckCast(nsDisplayItem*aItem){return(aItem->GetType()==DisplayItemType::TYPE_TEXT)?static_cast<nsDisplayText*>(aItem):nullptr;}structClipEdges{ClipEdges(constnsIFrame*aFrame,constnsPoint&aToReferenceFrame,nscoordaVisIStartEdge,nscoordaVisIEndEdge){nsRectr=aFrame->ScrollableOverflowRect()+aToReferenceFrame;if(aFrame->GetWritingMode().IsVertical()){mVisIStart=aVisIStartEdge>0?r.y+aVisIStartEdge:nscoord_MIN;mVisIEnd=aVisIEndEdge>0?std::max(r.YMost()-aVisIEndEdge,mVisIStart):nscoord_MAX;}else{mVisIStart=aVisIStartEdge>0?r.x+aVisIStartEdge:nscoord_MIN;mVisIEnd=aVisIEndEdge>0?std::max(r.XMost()-aVisIEndEdge,mVisIStart):nscoord_MAX;}}voidIntersect(nscoord*aVisIStart,nscoord*aVisISize)const{nscoordend=*aVisIStart+*aVisISize;*aVisIStart=std::max(*aVisIStart,mVisIStart);*aVisISize=std::max(std::min(end,mVisIEnd)-*aVisIStart,0);}nscoordmVisIStart;nscoordmVisIEnd;};nscoord&VisIStartEdge(){returnmVisIStartEdge;}nscoord&VisIEndEdge(){returnmVisIEndEdge;}floatOpacity()const{returnmOpacity;}private:nsRectmBounds;floatmOpacity;// Lengths measured from the visual inline start and end sides// (i.e. left and right respectively in horizontal writing modes,// regardless of bidi directionality; top and bottom in vertical modes).nscoordmVisIStartEdge;nscoordmVisIEndEdge;};/** * A display item that for webrender to handle SVG */classnsDisplaySVGWrapper:publicnsDisplayWrapList{public:nsDisplaySVGWrapper(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList);MOZ_COUNTED_DTOR_OVERRIDE(nsDisplaySVGWrapper)NS_DISPLAY_DECL_NAME("SVGWrapper",TYPE_SVG_WRAPPER)voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override{GetChildren()->Paint(aBuilder,aCtx,mFrame->PresContext()->AppUnitsPerDevPixel());}boolShouldFlattenAway(nsDisplayListBuilder*aBuilder)override;boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;};/** * A display item for webrender to handle SVG foreign object */classnsDisplayForeignObject:publicnsDisplayWrapList{public:nsDisplayForeignObject(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,nsDisplayList*aList);#ifdef NS_BUILD_REFCNT_LOGGINGvirtual~nsDisplayForeignObject();#endifNS_DISPLAY_DECL_NAME("ForeignObject",TYPE_FOREIGN_OBJECT)virtualboolShouldFlattenAway(nsDisplayListBuilder*aBuilder)override;voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override{GetChildren()->Paint(aBuilder,aCtx,mFrame->PresContext()->AppUnitsPerDevPixel());}boolCreateWebRenderCommands(wr::DisplayListBuilder&aBuilder,wr::IpcResourceUpdateQueue&aResources,constStackingContextHelper&aSc,layers::RenderRootStateManager*aManager,nsDisplayListBuilder*aDisplayListBuilder)override;};/** * A display item to represent a hyperlink. */classnsDisplayLink:publicnsPaintedDisplayItem{public:nsDisplayLink(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constchar*aLinkSpec,constnsRect&aRect):nsPaintedDisplayItem(aBuilder,aFrame),mLinkSpec(aLinkSpec),mRect(aRect){}NS_DISPLAY_DECL_NAME("Link",TYPE_LINK)voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;private:nsCStringmLinkSpec;nsRectmRect;};/** * A display item to represent a destination within the document. */classnsDisplayDestination:publicnsPaintedDisplayItem{public:nsDisplayDestination(nsDisplayListBuilder*aBuilder,nsIFrame*aFrame,constchar*aDestinationName,constnsPoint&aPosition):nsPaintedDisplayItem(aBuilder,aFrame),mDestinationName(aDestinationName),mPosition(aPosition){}NS_DISPLAY_DECL_NAME("Destination",TYPE_DESTINATION)voidPaint(nsDisplayListBuilder*aBuilder,gfxContext*aCtx)override;private:nsCStringmDestinationName;nsPointmPosition;};classFlattenedDisplayListIterator{public:FlattenedDisplayListIterator(nsDisplayListBuilder*aBuilder,nsDisplayList*aList):FlattenedDisplayListIterator(aBuilder,aList,true){}virtualboolHasNext()const{returnmNext||!mStack.IsEmpty();}nsDisplayItem*GetNextItem(){if(!mNext){returnnullptr;}nsDisplayItem*next=mNext;mNext=next->GetAbove();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);}ResolveFlattening();returnnext;}nsDisplayItem*PeekNext(){returnmNext;}protected:FlattenedDisplayListIterator(nsDisplayListBuilder*aBuilder,nsDisplayList*aList,constboolaResolveFlattening):mBuilder(aBuilder),mNext(aList->GetBottom()){if(aResolveFlattening){// This is done conditionally in case subclass overrides// ShouldFlattenNextItem().ResolveFlattening();}}virtualvoidEnterChildList(nsDisplayItem*aContainerItem){}virtualvoidExitChildList(){}boolAtEndOfNestedList()const{return!mNext&&mStack.Length()>0;}virtualboolShouldFlattenNextItem(){returnmNext&&mNext->ShouldFlattenAway(mBuilder);}voidResolveFlattening(){// Handle the case where we reach the end of a nested list, or the current// item should start a new nested list. Repeat this until we find an actual// 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();}else{EnterChildList(mNext);// 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();}}}/** * 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.returnaCurrent;}// 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&¤t->CanMerge(next));current=mBuilder->MergeItems(willMerge);}// Here |mNext| will be either the first item that could not be merged with// |current|, or nullptr.returncurrent;}private:nsDisplayListBuilder*mBuilder;nsDisplayItem*mNext;AutoTArray<nsDisplayItem*,16>mStack;};classPaintTelemetry{public:classAutoRecordPaint{public:AutoRecordPaint();~AutoRecordPaint();private:TimeStampmStart;};private:staticuint32_tsPaintLevel;};}// namespace mozilla#endif /*NSDISPLAYLIST_H_*/