Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/layout/painting/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 238 kB image not shown  

Quelle  nsDisplayList.h   Sprache: C

 
/* -*- 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 "RetainedDisplayListHelpers.h"
#include "Units.h"
#include "gfxContext.h"
#include "mozilla/ArenaAllocator.h"
#include "mozilla/Array.h"
#include "mozilla/ArrayIterator.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/EffectCompositor.h"
#include "mozilla/EnumSet.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/Logging.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/gfx/UserData.h"
#include "mozilla/layers/BSPTree.h"
#include "mozilla/layers/ScrollableLayerGuid.h"
#include "mozilla/layers/ScrollbarData.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 "nsCaret.h"

#include <algorithm>
#include <unordered_set>

// XXX Includes that could be avoided by moving function implementations to the
// cpp file.
#include "gfxPlatform.h"

class gfxContext;
class nsIContent;
class nsSubDocumentFrame;
struct WrFiltersHolder;

namespace nsStyleTransformMatrix {
class TransformReferenceBox;
}

namespace mozilla {

enum class nsDisplayOwnLayerFlags;
class nsDisplayCompositorHitTestInfo;
class nsDisplayScrollInfoLayer;
class PresShell;
class ScrollContainerFrame;
class StickyScrollContainer;

namespace layers {
struct FrameMetrics;
class RenderRootStateManager;
class Layer;
class ImageContainer;
class StackingContextHelper;
class WebRenderScrollData;
class WebRenderLayerScrollData;
class WebRenderLayerManager;
}  // namespace layers

namespace wr {
class DisplayListBuilder;
}  // namespace wr

namespace dom {
class RemoteBrowser;
class Selection;
}  // namespace dom

enum class DisplayListArenaObjectId {
#define DISPLAY_LIST_ARENA_OBJECT(name_) name_,
#include "nsDisplayListArenaTypes.h"
#undef DISPLAY_LIST_ARENA_OBJECT
  COUNT
};

extern LazyLogModule sContentDisplayListLog;
extern LazyLogModule sParentDisplayListLog;

LazyLogModule& GetLoggerByProcess();

#define DL_LOG(lvl, ...) MOZ_LOG(GetLoggerByProcess(), lvl, (__VA_ARGS__))
#define DL_LOGI(...) DL_LOG(LogLevel::Info, __VA_ARGS__)
#define DL_LOG_TEST(lvl) MOZ_LOG_TEST(GetLoggerByProcess(), lvl)

#ifdef DEBUG
#  define DL_LOGD(...) DL_LOG(LogLevel::Debug, __VA_ARGS__)
#  define DL_LOGV(...) DL_LOG(LogLevel::Verbose, __VA_ARGS__)
#else
// Disable Debug and Verbose logs for release builds.
#  define DL_LOGD(...)
#  define DL_LOGV(...)
#endif

/*
 * 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.
 */


/**
 * 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.
 */

struct ActiveScrolledRoot {
  static already_AddRefed<ActiveScrolledRoot> CreateASRForFrame(
      const ActiveScrolledRoot* aParent,
      ScrollContainerFrame* aScrollContainerFrame, bool aIsRetained);

  static const ActiveScrolledRoot* PickAncestor(
      const ActiveScrolledRoot* aOne, const ActiveScrolledRoot* aTwo) {
    MOZ_ASSERT(IsAncestor(aOne, aTwo) || IsAncestor(aTwo, aOne));
    return Depth(aOne) <= Depth(aTwo) ? aOne : aTwo;
  }

  static const ActiveScrolledRoot* PickDescendant(
      const ActiveScrolledRoot* aOne, const ActiveScrolledRoot* aTwo) {
    MOZ_ASSERT(IsAncestor(aOne, aTwo) || IsAncestor(aTwo, aOne));
    return Depth(aOne) >= Depth(aTwo) ? aOne : aTwo;
  }

  static bool IsAncestor(const ActiveScrolledRoot* aAncestor,
                         const ActiveScrolledRoot* aDescendant);
  static bool IsProperAncestor(const ActiveScrolledRoot* aAncestor,
                               const ActiveScrolledRoot* aDescendant);

  static nsCString ToString(const ActiveScrolledRoot* aActiveScrolledRoot);

  // Call this when inserting an ancestor.
  void IncrementDepth() { mDepth++; }

  /**
   * Find the view ID (or generate a new one) for the content element
   * corresponding to the ASR.
   */

  layers::ScrollableLayerGuid::ViewID GetViewId() const {
    if (!mViewId.isSome()) {
      mViewId = Some(ComputeViewId());
    }
    return *mViewId;
  }

  RefPtr<const ActiveScrolledRoot> mParent;
  ScrollContainerFrame* mScrollContainerFrame = nullptr;

  NS_INLINE_DECL_REFCOUNTING(ActiveScrolledRoot)

 private:
  ActiveScrolledRoot() : mDepth(0), mRetained(false) {}

  ~ActiveScrolledRoot();

  static void DetachASR(ActiveScrolledRoot* aASR) {
    aASR->mParent = nullptr;
    aASR->mScrollContainerFrame = nullptr;
    NS_RELEASE(aASR);
  }
  NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(ActiveScrolledRootCache,
                                      ActiveScrolledRoot, DetachASR)

  static uint32_t Depth(const ActiveScrolledRoot* aActiveScrolledRoot) {
    return aActiveScrolledRoot ? aActiveScrolledRoot->mDepth : 0;
  }

  layers::ScrollableLayerGuid::ViewID ComputeViewId() 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.
  mutable Maybe<layers::ScrollableLayerGuid::ViewID> mViewId;

  uint32_t mDepth;
  bool mRetained;
};

enum class nsDisplayListBuilderMode : uint8_t {
  Painting,
  PaintForPrinting,
  EventDelivery,
  FrameVisibility,
  GenerateGlyph,
};

using ListArenaAllocator = ArenaAllocator<4096, 8>;

class nsDisplayItem;
class nsPaintedDisplayItem;
class nsDisplayList;
class nsDisplayWrapList;
class nsDisplayTableBackgroundSet;
class nsDisplayTableItem;

class RetainedDisplayList;

/**
 * This manages a display list and is passed as a parameter to
 * nsIFrame::BuildDisplayList.
 * 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.
 */

class nsDisplayListBuilder {
  /**
   * 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.
   */

  class Preserves3DContext {
   public:
    Preserves3DContext()
        : mAccumulatedRectLevels(0), mAllowAsyncAnimation(true) {}

    Preserves3DContext(const Preserves3DContext& aOther)
        : mAccumulatedRectLevels(0),
          mVisibleRect(aOther.mVisibleRect),
          mAllowAsyncAnimation(aOther.mAllowAsyncAnimation) {}

    // Accmulate transforms of ancestors on the preserves-3d chain.
    gfx::Matrix4x4 mAccumulatedTransform;
    // Accmulate visible rect of descendants in the preserves-3d context.
    nsRect mAccumulatedRect;
    // How far this frame is from the root of the current 3d context.
    int mAccumulatedRectLevels;
    nsRect mVisibleRect;
    // Allow async animation for this 3D context.
    bool mAllowAsyncAnimation;
  };

 public:
  using ViewID = 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,
                       nsDisplayListBuilderMode aMode, bool aBuildCaret,
                       bool aRetainingDisplayList = false);
  ~nsDisplayListBuilder();

  void BeginFrame();
  void EndFrame();

  void AddTemporaryItem(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.
   */

  bool IsForEventDelivery() const {
    return mMode == 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.
   */

  bool IsForPainting() const {
    return mMode == nsDisplayListBuilderMode::Painting ||
           mMode == nsDisplayListBuilderMode::PaintForPrinting;
  }

  /**
   * @return true if the display list is being built specifically for printing.
   */

  bool IsForPrinting() const {
    return mMode == nsDisplayListBuilderMode::PaintForPrinting;
  }

  /**
   * @return true if the display list is being built for determining frame
   * visibility.
   */

  bool IsForFrameVisibility() const {
    return mMode == nsDisplayListBuilderMode::FrameVisibility;
  }

  /**
   * @return true if the display list is being built for creating the glyph
   * mask from text items.
   */

  bool IsForGenerateGlyphMask() const {
    return mMode == nsDisplayListBuilderMode::GenerateGlyph;
  }

  bool BuildCompositorHitTestInfo() const {
    return mAsyncPanZoomEnabled && mIsPaintingToWindow;
  }

  /**
   * @return true if "painting is suppressed" during page load and we
   * should paint only the background of the document.
   */

  bool IsBackgroundOnly() {
    NS_ASSERTION(mPresShellStates.Length() > 0,
                 "don't call this if we're not in a presshell");
    return CurrentPresShellState()->mIsBackgroundOnly;
  }

  /**
   * @return the root of given frame's (sub)tree, whose origin
   * establishes the coordinate system for the child display items.
   */

  const nsIFrame* FindReferenceFrameFor(const nsIFrame* aFrame,
                                        nsPoint* aOffset = nullptr) const;

  const Maybe<nsPoint>& AdditionalOffset() const { return mAdditionalOffset; }

  /**
   * @return the root of the display list's frame (sub)tree, whose origin
   * establishes the coordinate system for the display list
   */

  nsIFrame* RootReferenceFrame() const { return mReferenceFrame; }

  /**
   * @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.
   */

  const nsPoint ToReferenceFrame(const nsIFrame* aFrame) const {
    nsPoint result;
    FindReferenceFrameFor(aFrame, &result);
    return result;
  }
  /**
   * 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.
   */

  void SetIgnoreScrollFrame(nsIFrame* aFrame) { mIgnoreScrollFrame = aFrame; }
  /**
   * Get the scrollframe to ignore, if any.
   */

  nsIFrame* GetIgnoreScrollFrame() { return mIgnoreScrollFrame; }
  /**
   * Set for display lists built for hit-testing a point that is already
   * relative to the layout viewport. Display lists with this flag set
   * do not build an async zoom container (which would transform coordinates
   * relative to the visual viewport into coordinates relative to the
   * layout viewport during hit-testing).
   */

  void SetIsRelativeToLayoutViewport();
  bool IsRelativeToLayoutViewport() const {
    return mIsRelativeToLayoutViewport;
  }
  /**
   * Get the ViewID of the nearest scrolling ancestor frame.
   */

  ViewID GetCurrentScrollParentId() const { return mCurrentScrollParentId; }
  /**
   * 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.
   */

  void ForceLayerForScrollParent();
  uint32_t GetNumActiveScrollframesEncountered() const {
    return mNumActiveScrollframesEncountered;
  }
  /**
   * Set the flag that indicates there is a non-minimal display port in the
   * current subtree. This is used to determine display port expiry.
   */

  void SetContainsNonMinimalDisplayPort() {
    mContainsNonMinimalDisplayPort = true;
  }
  /**
   * Get the ViewID and the scrollbar flags corresponding to the scrollbar for
   * which we are building display items at the moment.
   */

  ViewID GetCurrentScrollbarTarget() const { return mCurrentScrollbarTarget; }
  Maybe<layers::ScrollDirection> GetCurrentScrollbarDirection() const {
    return mCurrentScrollbarDirection;
  }
  /**
   * Returns true if building a scrollbar, and the scrollbar will not be
   * layerized.
   */

  bool IsBuildingNonLayerizedScrollbar() const {
    return mIsBuildingScrollbar && !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).
   */

  void SetIncludeAllOutOfFlows() { mIncludeAllOutOfFlows = true; }
  bool GetIncludeAllOutOfFlows() const { return mIncludeAllOutOfFlows; }
  /**
   * Calling this setter makes us exclude all leaf frames that aren't
   * selected.
   */

  void SetSelectedFramesOnly() { mSelectedFramesOnly = true; }
  bool GetSelectedFramesOnly() { return mSelectedFramesOnly; }
  /**
   * @return Returns true if we should include the caret in any display lists
   * that we make.
   */

  bool IsBuildingCaret() const { return mBuildCaret; }

  bool IsRetainingDisplayList() const { return mRetainingDisplayList; }

  bool IsPartialUpdate() const { return mPartialUpdate; }
  void SetPartialUpdate(bool aPartial) { mPartialUpdate = aPartial; }

  bool IsBuilding() const { return mIsBuilding; }
  void SetIsBuilding(bool aIsBuilding) { mIsBuilding = aIsBuilding; }

  bool InInvalidSubtree() const { return mInInvalidSubtree; }

  /**
   * Allows callers to selectively override the regular paint suppression
   * checks, so that methods like GetFrameForPoint work when painting is
   * suppressed.
   */

  void IgnorePaintSuppression() { mIgnoreSuppression = true; }
  /**
   * @return Returns if this builder will ignore paint suppression.
   */

  bool IsIgnoringPaintSuppression() { return mIgnoreSuppression; }
  /**
   * Call this if we're doing normal painting to the window.
   */

  void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; }
  bool IsPaintingToWindow() const { return mIsPaintingToWindow; }
  /**
   * Call this if we're using high quality scaling for image decoding.
   * It is also implied by IsPaintingToWindow.
   */

  void SetUseHighQualityScaling(bool aUseHighQualityScaling) {
    mUseHighQualityScaling = aUseHighQualityScaling;
  }
  bool UseHighQualityScaling() const {
    return mIsPaintingToWindow || mUseHighQualityScaling;
  }
  /**
   * Call this if we're doing painting for WebRender
   */

  void SetPaintingForWebRender(bool aForWebRender) {
    mIsPaintingForWebRender = true;
  }
  bool IsPaintingForWebRender() const { return mIsPaintingForWebRender; }
  /**
   * Call this to prevent descending into subdocuments.
   */

  void SetDescendIntoSubdocuments(bool aDescend) {
    mDescendIntoSubdocuments = aDescend;
  }

  bool GetDescendIntoSubdocuments() { return mDescendIntoSubdocuments; }

  /**
   * Get dirty rect relative to current frame (the frame that we're calling
   * BuildDisplayList on right now).
   */

  const nsRect& GetVisibleRect() { return mVisibleRect; }
  const nsRect& GetDirtyRect() { return mDirtyRect; }

  void SetVisibleRect(const nsRect& aVisibleRect) {
    mVisibleRect = aVisibleRect;
  }

  void IntersectVisibleRect(const nsRect& aVisibleRect) {
    mVisibleRect.IntersectRect(mVisibleRect, aVisibleRect);
  }

  void SetDirtyRect(const nsRect& aDirtyRect) { mDirtyRect = aDirtyRect; }

  void IntersectDirtyRect(const nsRect& aDirtyRect) {
    mDirtyRect.IntersectRect(mDirtyRect, aDirtyRect);
  }

  const nsIFrame* GetCurrentFrame() { return mCurrentFrame; }
  const nsIFrame* GetCurrentReferenceFrame() { return mCurrentReferenceFrame; }

  const nsPoint& GetCurrentFrameOffsetToReferenceFrame() const {
    return mCurrentOffsetToReferenceFrame;
  }

  void Check() { mPool.Check(); }

  /*
   * Get the paint sequence number of the current paint.
   */

  static uint32_t GetPaintSequenceNumber() { return sPaintSequenceNumber; }

  /*
   * Increment the paint sequence number.
   */

  static void IncrementPaintSequenceNumber() { ++sPaintSequenceNumber; }

  /**
   * Returns true if merging and flattening of display lists should be
   * performed while computing visibility.
   */

  bool AllowMergingAndFlattening() { return mAllowMergingAndFlattening; }
  void SetAllowMergingAndFlattening(bool aAllow) {
    mAllowMergingAndFlattening = aAllow;
  }

  void SetCompositorHitTestInfo(const gfx::CompositorHitTestInfo& aInfo) {
    mCompositorHitTestInfo = aInfo;
  }

  const gfx::CompositorHitTestInfo& GetCompositorHitTestInfo() const {
    return mCompositorHitTestInfo;
  }

  /**
   * Builds a new nsDisplayCompositorHitTestInfo for the frame |aFrame| if
   * needed, and adds it to the top of |aList|.
   */

  void BuildCompositorHitTestInfoIfNeeded(nsIFrame* aFrame,
                                          nsDisplayList* aList);

  bool IsInsidePointerEventsNoneDoc() {
    return CurrentPresShellState()->mInsidePointerEventsNoneDoc;
  }

  bool IsTouchEventPrefEnabledDoc() {
    return CurrentPresShellState()->mTouchEventPrefEnabledDoc;
  }

  bool GetAncestorHasApzAwareEventHandler() const {
    return mAncestorHasApzAwareEventHandler;
  }

  void SetAncestorHasApzAwareEventHandler(bool aValue) {
    mAncestorHasApzAwareEventHandler = aValue;
  }

  bool HaveScrollableDisplayPort() const { return mHaveScrollableDisplayPort; }
  void SetHaveScrollableDisplayPort() { mHaveScrollableDisplayPort = true; }
  void ClearHaveScrollableDisplayPort() { mHaveScrollableDisplayPort = false; }

  /**
   * Display the caret if needed.
   */

  bool DisplayCaret(nsIFrame* aFrame, nsDisplayList* aList) {
    nsIFrame* frame = GetCaretFrame();
    if (aFrame == frame && !IsBackgroundOnly()) {
      frame->DisplayCaret(this, aList);
      return true;
    }
    return false;
  }
  /**
   * Get the frame that the caret is supposed to draw in.
   * If the caret is currently invisible, this will be null.
   */

  nsIFrame* GetCaretFrame() { return CurrentPresShellState()->mCaretFrame; }
  /**
   * Get the rectangle we're supposed to draw the caret into.
   */

  const nsRect& GetCaretRect() { return mCaretRect; }
  /**
   * 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() {
    return CurrentPresShellState()->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.
   */

  void EnterPresShell(const nsIFrame* aReferenceFrame,
                      bool aPointerEventsNoneDoc = 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.
   */

  void ResetMarkedFramesForDisplayList(const nsIFrame* aReferenceFrame);
  /**
   * Notify the display list builder that we're leaving a presshell.
   */

  void LeavePresShell(const nsIFrame* aReferenceFrame,
                      nsDisplayList* aPaintedContents);

  void IncrementPresShellPaintCount(PresShell* aPresShell);

  /**
   * Returns true if we're currently building a display list that's
   * directly or indirectly under an nsDisplayTransform.
   */

  bool IsInTransform() const { return mInTransform; }

  bool InEventsOnly() const { return mInEventsOnly; }
  /**
   * Indicate whether or not we're directly or indirectly under and
   * nsDisplayTransform or SVG foreignObject.
   */

  void SetInTransform(bool aInTransform) { mInTransform = aInTransform; }

  /**
   * Returns true if we're currently building a display list that's
   * under an nsDisplayFilters.
   */

  bool IsInFilter() const { return mInFilter; }

  /**
   * Return true if we're currently building a display list for a
   * nested presshell.
   */

  bool IsInSubdocument() const { return mPresShellStates.Length() > 1; }

  void SetDisablePartialUpdates(bool aDisable) {
    mDisablePartialUpdates = aDisable;
  }
  bool DisablePartialUpdates() const { return mDisablePartialUpdates; }

  void SetPartialBuildFailed(bool aFailed) { mPartialBuildFailed = aFailed; }
  bool PartialBuildFailed() const { return mPartialBuildFailed; }

  bool IsInActiveDocShell() const { return mIsInActiveDocShell; }
  void SetInActiveDocShell(bool aActive) { 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.
   */

  bool IsInChromeDocumentOrPopup() const {
    return mIsInChromePresContext || mIsBuildingForPopup;
  }

  /**
   * @return true if images have been set to decode synchronously.
   */

  bool ShouldSyncDecodeImages() const { return mSyncDecodeImages; }

  /**
   * 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.
   */

  void SetSyncDecodeImages(bool aSyncDecodeImages) {
    mSyncDecodeImages = aSyncDecodeImages;
  }

  nsDisplayTableBackgroundSet* SetTableBackgroundSet(
      nsDisplayTableBackgroundSet* aTableSet) {
    nsDisplayTableBackgroundSet* old = mTableBackgroundSet;
    mTableBackgroundSet = aTableSet;
    return old;
  }
  nsDisplayTableBackgroundSet* GetTableBackgroundSet() const {
    return mTableBackgroundSet;
  }

  void FreeClipChains();

  /*
   * Frees the temporary display items created during merging.
   */

  void FreeTemporaryItems();

  /**
   * Helper method to generate background painting flags based on the
   * information available in the display list builder.
   */

  uint32_t GetBackgroundPaintFlags();

  /**
   * Helper method to generate nsImageRenderer flags based on the information
   * available in the display list builder.
   */

  uint32_t GetImageRendererFlags() const;

  /**
   * Helper method to generate image decoding flags based on the
   * information available in the display list builder.
   */

  uint32_t GetImageDecodeFlags() const;

  /**
   * 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.
   */

  void MarkFramesForDisplayList(nsIFrame* aDirtyFrame,
                                const nsFrameList& aFrames);
  void MarkFrameForDisplay(nsIFrame* aFrame, const nsIFrame* aStopAtFrame);
  void MarkFrameForDisplayIfVisible(nsIFrame* aFrame,
                                    const nsIFrame* aStopAtFrame);
  void AddFrameMarkedForDisplayIfVisible(nsIFrame* aFrame);

  void ClearFixedBackgroundDisplayData();
  /**
   * 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.
   */

  void MarkPreserve3DFramesForDisplayList(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.
   */

  bool ShouldDescendIntoFrame(nsIFrame* aFrame, bool aVisible) const {
    return aFrame->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 (const auto& data : mThemeGeometries.Values()) {
      geometries.AppendElements(*data);
    }

    return geometries;
  }

  /**
   * 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::MozWindowTitlebar) 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
   */

  void RegisterThemeGeometry(uint8_t aWidgetType, nsDisplayItem* aItem,
                             const LayoutDeviceIntRect& 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|.
   */

  void UnregisterThemeGeometry(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.
   */

  void AdjustWindowDraggingRegion(nsIFrame* aFrame);

  LayoutDeviceIntRegion GetWindowDraggingRegion() const;

  void RemoveModifiedWindowRegions();
  void ClearRetainedWindowRegions();

  /**
   * Invalidates the caret frames from previous paints, if they have changed.
   */

  void InvalidateCaretFramesIfNeeded();

  /**
   * 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_t aSize, DisplayListArenaObjectId aId) {
    return mPool.Allocate(aId, aSize);
  }
  void* Allocate(size_t aSize, DisplayItemType aType) {
#define DECLARE_DISPLAY_ITEM_TYPE(name_, ...)                \
  static_assert(size_t(DisplayItemType::TYPE_##name_) ==     \
                    size_t(DisplayListArenaObjectId::name_), \
                "");
#include "nsDisplayItemTypesList.h"
    static_assert(size_t(DisplayItemType::TYPE_MAX) ==
                      size_t(DisplayListArenaObjectId::CLIPCHAIN),
                  "");
    static_assert(size_t(DisplayItemType::TYPE_MAX) + 1 ==
                      size_t(DisplayListArenaObjectId::LISTNODE),
                  "");
#undef DECLARE_DISPLAY_ITEM_TYPE
    return Allocate(aSize, DisplayListArenaObjectId(size_t(aType)));
  }

  void Destroy(DisplayListArenaObjectId aId, void* aPtr) {
    if (!mIsDestroying) {
      mPool.Free(aId, aPtr);
    }
  }
  void Destroy(DisplayItemType aType, void* aPtr) {
    Destroy(DisplayListArenaObjectId(size_t(aType)), aPtr);
  }

  /**
   * Allocate a new ActiveScrolledRoot in the arena. Will be cleaned up
   * automatically when the arena goes away.
   */

  ActiveScrolledRoot* AllocateActiveScrolledRoot(
      const ActiveScrolledRoot* aParent,
      ScrollContainerFrame* aScrollContainerFrame);

  /**
   * Allocate a new DisplayItemClipChain object in the arena. Will be cleaned
   * up automatically when the arena goes away.
   */

  const DisplayItemClipChain* AllocateDisplayItemClipChain(
      const DisplayItemClip& aClip, const ActiveScrolledRoot* aASR,
      const DisplayItemClipChain* 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.
   */

  const DisplayItemClipChain* CreateClipChainIntersection(
      const DisplayItemClipChain* aAncestor,
      const DisplayItemClipChain* aLeafClip1,
      const DisplayItemClipChain* aLeafClip2);

  /**
   * Same as above, except aAncestor is computed as the nearest common
   * ancestor of the two provided clips.
   */

  const DisplayItemClipChain* CreateClipChainIntersection(
      const DisplayItemClipChain* aLeafClip1,
      const DisplayItemClipChain* aLeafClip2);

  /**
   * Clone the supplied clip chain's chain items into this builder's arena.
   */

  const DisplayItemClipChain* CopyWholeChain(
      const DisplayItemClipChain* aClipChain);

  const ActiveScrolledRoot* GetFilterASR() const { return mFilterASR; }

  /**
   * 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<nsDisplayItem*>& aItems);

  /**
   * A helper class used to temporarily set nsDisplayListBuilder properties for
   * building display items.
   * aVisibleRect and aDirtyRect are relative to aForChild.
   */

  class AutoBuildingDisplayList {
   public:
    AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aForChild,
                            const nsRect& aVisibleRect,
                            const nsRect& aDirtyRect)
        : AutoBuildingDisplayList(aBuilder, aForChild, aVisibleRect, aDirtyRect,
                                  aForChild->IsTransformed()) {}

    AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aForChild,
                            const nsRect& aVisibleRect,
                            const nsRect& aDirtyRect,
                            const bool aIsTransformed);

    void SetReferenceFrameAndCurrentOffset(const nsIFrame* aFrame,
                                           const nsPoint& aOffset) {
      mBuilder->mCurrentReferenceFrame = aFrame;
      mBuilder->mCurrentOffsetToReferenceFrame = aOffset;
    }

    void SetAdditionalOffset(const nsPoint& aOffset) {
      MOZ_ASSERT(!mBuilder->mAdditionalOffset);
      mBuilder->mAdditionalOffset = Some(aOffset);

      mBuilder->mCurrentOffsetToReferenceFrame += aOffset;
    }

    void RestoreBuildingInvisibleItemsValue() {
      mBuilder->mBuildingInvisibleItems = mPrevBuildingInvisibleItems;
    }

    ~AutoBuildingDisplayList() {
      mBuilder->mCurrentFrame = mPrevFrame;
      mBuilder->mCurrentReferenceFrame = mPrevReferenceFrame;
      mBuilder->mCurrentOffsetToReferenceFrame = mPrevOffset;
      mBuilder->mVisibleRect = mPrevVisibleRect;
      mBuilder->mDirtyRect = mPrevDirtyRect;
      mBuilder->mAncestorHasApzAwareEventHandler =
          mPrevAncestorHasApzAwareEventHandler;
      mBuilder->mBuildingInvisibleItems = mPrevBuildingInvisibleItems;
      mBuilder->mInInvalidSubtree = mPrevInInvalidSubtree;
      mBuilder->mAdditionalOffset = mPrevAdditionalOffset;
      mBuilder->mCompositorHitTestInfo = mPrevCompositorHitTestInfo;
    }

   private:
    nsDisplayListBuilder* mBuilder;
    const nsIFrame* mPrevFrame;
    const nsIFrame* mPrevReferenceFrame;
    nsPoint mPrevOffset;
    Maybe<nsPoint> mPrevAdditionalOffset;
    nsRect mPrevVisibleRect;
    nsRect mPrevDirtyRect;
    gfx::CompositorHitTestInfo mPrevCompositorHitTestInfo;
    bool mPrevAncestorHasApzAwareEventHandler;
    bool mPrevBuildingInvisibleItems;
    bool mPrevInInvalidSubtree;
  };

  /**
   * A helper class to temporarily set the value of mInTransform.
   */

  class AutoInTransformSetter {
   public:
    AutoInTransformSetter(nsDisplayListBuilder* aBuilder, bool aInTransform)
        : mBuilder(aBuilder), mOldValue(aBuilder->mInTransform) {
      aBuilder->mInTransform = aInTransform;
    }

    ~AutoInTransformSetter() { mBuilder->mInTransform = mOldValue; }

   private:
    nsDisplayListBuilder* mBuilder;
    bool mOldValue;
  };

  class AutoInEventsOnly {
   public:
    AutoInEventsOnly(nsDisplayListBuilder* aBuilder, bool aInEventsOnly)
        : mBuilder(aBuilder), mOldValue(aBuilder->mInEventsOnly) {
      aBuilder->mInEventsOnly |= aInEventsOnly;
    }

    ~AutoInEventsOnly() { mBuilder->mInEventsOnly = mOldValue; }

   private:
    nsDisplayListBuilder* mBuilder;
    bool mOldValue;
  };

  /**
   * A helper class to temporarily set the value of mFilterASR and
   * mInFilter.
   */

  class AutoEnterFilter {
   public:
    AutoEnterFilter(nsDisplayListBuilder* aBuilder, bool aUsingFilter)
        : 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;
    const ActiveScrolledRoot* mOldValue;
    bool mOldInFilter;
  };

  /**
   * Used to update the current active scrolled root on the display list
   * builder, and to create new active scrolled roots.
   */

  class AutoCurrentActiveScrolledRootSetter {
   public:
    explicit AutoCurrentActiveScrolledRootSetter(nsDisplayListBuilder* aBuilder)
        : mBuilder(aBuilder),
          mSavedActiveScrolledRoot(aBuilder->mCurrentActiveScrolledRoot),
          mContentClipASR(aBuilder->ClipState().GetContentClipASR()),
          mDescendantsStartIndex(aBuilder->mActiveScrolledRoots.Length()),
          mUsed(false),
          mOldScrollParentId(aBuilder->mCurrentScrollParentId),
          mOldForceLayer(aBuilder->mForceLayerForScrollParent),
          mOldContainsNonMinimalDisplayPort(
              mBuilder->mContainsNonMinimalDisplayPort),
          mCanBeScrollParent(false) {}

    void SetCurrentScrollParentId(ViewID aScrollId) {
      // Update the old scroll parent id.
      mOldScrollParentId = mBuilder->mCurrentScrollParentId;
      // If this AutoCurrentActiveScrolledRootSetter has the same aScrollId 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 = (mOldScrollParentId != aScrollId);
      mBuilder->mCurrentScrollParentId = aScrollId;
      mBuilder->mForceLayerForScrollParent = false;
      mBuilder->mContainsNonMinimalDisplayPort = false;
    }

    bool ShouldForceLayerForScrollParent() const {
      // Only scrollframes participating in scroll handoff can be forced to
      // layerize
      return mCanBeScrollParent && mBuilder->mForceLayerForScrollParent;
    }

    bool GetContainsNonMinimalDisplayPort() const {
      // Only for scrollframes participating in scroll handoff can we return
      // true.
      return mCanBeScrollParent && mBuilder->mContainsNonMinimalDisplayPort;
    }

    ~AutoCurrentActiveScrolledRootSetter() {
      mBuilder->mCurrentActiveScrolledRoot = mSavedActiveScrolledRoot;
      mBuilder->mCurrentScrollParentId = mOldScrollParentId;
      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;
    }

    void SetCurrentActiveScrolledRoot(
        const ActiveScrolledRoot* aActiveScrolledRoot);

    void EnterScrollFrame(ScrollContainerFrame* aScrollContainerFrame) {
      MOZ_ASSERT(!mUsed);
      ActiveScrolledRoot* asr = mBuilder->AllocateActiveScrolledRoot(
          mBuilder->mCurrentActiveScrolledRoot, aScrollContainerFrame);
      mBuilder->mCurrentActiveScrolledRoot = asr;
      mUsed = true;
    }

    void InsertScrollFrame(ScrollContainerFrame* aScrollContainerFrame);

   private:
    nsDisplayListBuilder* mBuilder;
    /**
     * The builder's mCurrentActiveScrolledRoot at construction time which
     * needs to be restored at destruction time.
     */

    const ActiveScrolledRoot* 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.
     */

    const ActiveScrolledRoot* 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_t mDescendantsStartIndex;
    /**
     * Flag to make sure that only one of SetCurrentActiveScrolledRoot /
     * EnterScrollFrame / InsertScrollFrame is called per instance of this
     * class.
     */

    bool mUsed;
    ViewID mOldScrollParentId;
    bool mOldForceLayer;
    bool mOldContainsNonMinimalDisplayPort;
    bool mCanBeScrollParent;
  };

  /**
   * 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.
   */

  class AutoContainerASRTracker {
   public:
    explicit AutoContainerASRTracker(nsDisplayListBuilder* aBuilder);

    const ActiveScrolledRoot* GetContainerASR() {
      return mBuilder->mCurrentContainerASR;
    }

    ~AutoContainerASRTracker() {
      mBuilder->mCurrentContainerASR = ActiveScrolledRoot::PickAncestor(
          mBuilder->mCurrentContainerASR, mSavedContainerASR);
    }

   private:
    nsDisplayListBuilder* mBuilder;
    const ActiveScrolledRoot* mSavedContainerASR;
  };

  /**
   * A helper class to temporarily set the value of mCurrentScrollbarTarget
   * and mCurrentScrollbarFlags.
   */

  class AutoCurrentScrollbarInfoSetter {
   public:
    AutoCurrentScrollbarInfoSetter(
        nsDisplayListBuilder* aBuilder, ViewID aScrollTargetID,
        const Maybe<layers::ScrollDirection>& aScrollbarDirection,
        bool aWillHaveLayer)
        : 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.
   */

  class MOZ_RAII AutoPageNumberSetter {
   public:
    AutoPageNumberSetter(nsDisplayListBuilder* aBuilder, const uint8_t aPageNum)
        : mBuilder(aBuilder),
          mOldPageNum(aBuilder->GetBuildingExtraPagesForPageNum()) {
      mBuilder->SetBuildingExtraPagesForPageNum(aPageNum);
    }
    ~AutoPageNumberSetter() {
      mBuilder->SetBuildingExtraPagesForPageNum(mOldPageNum);
    }

   private:
    nsDisplayListBuilder* mBuilder;
    uint8_t mOldPageNum;
  };

  /**
   * 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.
   */

  class AutoAccumulateTransform {
   public:
    explicit AutoAccumulateTransform(nsDisplayListBuilder* aBuilder)
        : mBuilder(aBuilder),
          mSavedTransform(aBuilder->mPreserves3DCtx.mAccumulatedTransform) {}

    ~AutoAccumulateTransform() {
      mBuilder->mPreserves3DCtx.mAccumulatedTransform = mSavedTransform;
    }

    void Accumulate(const gfx::Matrix4x4& aTransform) {
      mBuilder->mPreserves3DCtx.mAccumulatedTransform =
          aTransform * mBuilder->mPreserves3DCtx.mAccumulatedTransform;
    }

    const gfx::Matrix4x4& GetCurrentTransform() {
      return mBuilder->mPreserves3DCtx.mAccumulatedTransform;
    }

    void StartRoot() {
      mBuilder->mPreserves3DCtx.mAccumulatedTransform = gfx::Matrix4x4();
    }

   private:
    nsDisplayListBuilder* mBuilder;
    gfx::Matrix4x4 mSavedTransform;
  };

  /**
   * 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.
   */

  class AutoAccumulateRect {
   public:
    explicit AutoAccumulateRect(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;
    nsRect mSavedRect;
  };

  void AccumulateRect(const nsRect& aRect) {
    mPreserves3DCtx.mAccumulatedRect.UnionRect(mPreserves3DCtx.mAccumulatedRect,
                                               aRect);
  }

  const nsRect& GetAccumulatedRect() {
    return mPreserves3DCtx.mAccumulatedRect;
  }

  /**
   * The level is increased by one for items establishing 3D rendering
   * context and starting a new accumulation.
   */

  int GetAccumulatedRectLevels() {
    return mPreserves3DCtx.mAccumulatedRectLevels;
  }

  struct OutOfFlowDisplayData {
    OutOfFlowDisplayData(
        const DisplayItemClipChain* aContainingBlockClipChain,
        const DisplayItemClipChain* aCombinedClipChain,
        const ActiveScrolledRoot* aContainingBlockActiveScrolledRoot,
        const ViewID& aScrollParentId, const nsRect& aVisibleRect,
        const nsRect& aDirtyRect)
        : mContainingBlockClipChain(aContainingBlockClipChain),
          mCombinedClipChain(aCombinedClipChain),
          mContainingBlockActiveScrolledRoot(
              aContainingBlockActiveScrolledRoot),
          mVisibleRect(aVisibleRect),
          mDirtyRect(aDirtyRect),
          mScrollParentId(aScrollParentId) {}
    const DisplayItemClipChain* mContainingBlockClipChain;
    const DisplayItemClipChain*
        mCombinedClipChain;  // only necessary for the special case of top layer
    const ActiveScrolledRoot* 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.
    nsRect mVisibleRect;
    nsRect mDirtyRect;
    ViewID mScrollParentId;

    static nsRect ComputeVisibleRectForFrame(nsDisplayListBuilder* aBuilder,
                                             nsIFrame* aFrame,
                                             const nsRect& aVisibleRect,
                                             const nsRect& aDirtyRect,
                                             nsRect* aOutDirtyRect);

    nsRect GetVisibleRectForFrame(nsDisplayListBuilder* aBuilder,
                                  nsIFrame* aFrame, nsRect* aDirtyRect) {
      return ComputeVisibleRectForFrame(aBuilder, aFrame, mVisibleRect,
                                        mDirtyRect, aDirtyRect);
    }
  };

  NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutOfFlowDisplayDataProperty,
                                      OutOfFlowDisplayData)

  struct DisplayListBuildingData {
    nsIFrame* mModifiedAGR = nullptr;
    nsRect mDirtyRect;
  };
  NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingRect,
                                      DisplayListBuildingData)

  NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingDisplayPortRect,
                                      nsRect)

  static OutOfFlowDisplayData* GetOutOfFlowData(nsIFrame* aFrame) {
    if (!aFrame->GetParent()) {
      return nullptr;
    }
    return aFrame->GetParent()->GetProperty(OutOfFlowDisplayDataProperty());
  }

  nsPresContext* CurrentPresContext();

  OutOfFlowDisplayData* GetCurrentFixedBackgroundDisplayData() {
    auto& displayData = CurrentPresShellState()->mFixedBackgroundDisplayData;
    return displayData ? displayData.ptr() : nullptr;
  }

  /**
   * Accumulates opaque stuff into the window opaque region.
   */

  void AddWindowOpaqueRegion(nsIFrame* aFrame, const nsRect& 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.
   */

  const nsRegion GetWindowOpaqueRegion() {
    return IsRetainingDisplayList() ? mRetainedWindowOpaqueRegion.ToRegion()
                                    : mWindowOpaqueRegion;
  }

  /**
   * 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.
   */

  void SetContainsBlendMode(bool aContainsBlendMode) {
    mContainsBlendMode = aContainsBlendMode;
  }
  bool ContainsBlendMode() const { return mContainsBlendMode; }

  DisplayListClipState& ClipState() { return mClipState; }
  const ActiveScrolledRoot* CurrentActiveScrolledRoot() {
    return mCurrentActiveScrolledRoot;
  }
  const ActiveScrolledRoot* CurrentAncestorASRStackingContextContents() {
    return mCurrentContainerASR;
  }

  /**
   * 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.
   */

  bool AddToWillChangeBudget(nsIFrame* aFrame, const nsSize& 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.
   */

  bool IsInWillChangeBudget(nsIFrame* aFrame, const nsSize& aSize);

  /**
   * Clears the will-change budget status for the given |aFrame|.
   * This will also remove the frame from will-change budgets.
   */

  void ClearWillChangeBudgetStatus(nsIFrame* aFrame);

  /**
   * Removes the given |aFrame| from will-change budgets.
   */

  void RemoveFromWillChangeBudgets(const nsIFrame* aFrame);

  /**
   * Clears the will-change budgets.
   */

  void ClearWillChangeBudgets();

  void EnterSVGEffectsContents(nsIFrame* aEffectsFrame,
                               nsDisplayList* aHoistedItemsStorage);
  void ExitSVGEffectsContents();

  bool ShouldBuildScrollInfoItemsForHoisting() const;

  void AppendNewScrollInfoItemForHoisting(
      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.
   */

  class AutoPreserves3DContext {
   public:
    explicit AutoPreserves3DContext(nsDisplayListBuilder* aBuilder)
        : mBuilder(aBuilder), mSavedCtx(aBuilder->mPreserves3DCtx) {}

    ~AutoPreserves3DContext() { mBuilder->mPreserves3DCtx = mSavedCtx; }

   private:
    nsDisplayListBuilder* mBuilder;
    Preserves3DContext mSavedCtx;
  };

  const nsRect GetPreserves3DRect() const {
    return mPreserves3DCtx.mVisibleRect;
  }

  void SavePreserves3DRect() { mPreserves3DCtx.mVisibleRect = mVisibleRect; }

  void SavePreserves3DAllowAsyncAnimation(bool aValue) {
    mPreserves3DCtx.mAllowAsyncAnimation = aValue;
  }

  bool GetPreserves3DAllowAsyncAnimation() const {
    return mPreserves3DCtx.mAllowAsyncAnimation;
  }

  bool IsBuildingInvisibleItems() const { return mBuildingInvisibleItems; }

  void SetBuildingInvisibleItems(bool aBuildingInvisibleItems) {
    mBuildingInvisibleItems = aBuildingInvisibleItems;
  }

  void SetBuildingExtraPagesForPageNum(uint8_t aPageNum) {
    mBuildingExtraPagesForPageNum = aPageNum;
  }
  uint8_t GetBuildingExtraPagesForPageNum() const {
    return mBuildingExtraPagesForPageNum;
  }

  bool HitTestIsForVisibility() const { return mVisibleThreshold.isSome(); }

  float VisibilityThreshold() const {
    MOZ_DIAGNOSTIC_ASSERT(HitTestIsForVisibility());
    return mVisibleThreshold.valueOr(1.0f);
  }

  void SetHitTestIsForVisibility(float aVisibleThreshold) {
    mVisibleThreshold = Some(aVisibleThreshold);
  }

  bool ShouldBuildAsyncZoomContainer() const {
    return mBuildAsyncZoomContainer;
  }
  void UpdateShouldBuildAsyncZoomContainer();

  void UpdateShouldBuildBackdropRootContainer();

  bool ShouldRebuildDisplayListDueToPrefChange();

  /**
   * 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.
   */

  struct WeakFrameRegion {
    /**
     * 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.
     */

    struct WeakFrameWrapper {
      explicit WeakFrameWrapper(nsIFrame* aFrame)
          : mWeakFrame(new WeakFrame(aFrame)), mFrame(aFrame) {}

      UniquePtr<WeakFrame> mWeakFrame;
      void* mFrame;
    };

    nsTHashSet<void*> mFrameSet;
    nsTArray<WeakFrameWrapper> mFrames;
    nsTArray<pixman_box32_t> mRects;

    template <typename RectType>
    void Add(nsIFrame* aFrame, const RectType& aRect) {
      if (mFrameSet.Contains(aFrame)) {
        return;
      }

      mFrameSet.Insert(aFrame);
      mFrames.AppendElement(WeakFrameWrapper(aFrame));
      mRects.AppendElement(nsRegion::RectToBox(aRect));
    }

    void Clear() {
      mFrameSet.Clear();
      mFrames.Clear();
      mRects.Clear();
    }

    void RemoveModifiedFramesAndRects();

    size_t SizeOfExcludingThis(MallocSizeOf) const;

    typedef gfx::ArrayView<pixman_box32_t> BoxArrayView;

    nsRegion ToRegion() const { return nsRegion(BoxArrayView(mRects)); }

    LayoutDeviceIntRegion ToLayoutDeviceIntRegion() const {
      return LayoutDeviceIntRegion(BoxArrayView(mRects));
    }
  };

  void AddScrollContainerFrameToNotify(
      ScrollContainerFrame* aScrollContainerFrame);
  void NotifyAndClearScrollContainerFrames();

  // 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.
  class Linkifier {
   public:
    Linkifier(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
              nsDisplayList* aList);

    ~Linkifier() {
      if (mBuilderToReset) {
        mBuilderToReset->mLinkURI.Truncate(0);
        mBuilderToReset->mLinkDest.Truncate(0);
      }
    }

    void MaybeAppendLink(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);

   private:
    nsDisplayListBuilder* mBuilderToReset = nullptr;
    nsDisplayList* mList;
  };

  /**
   * 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);

  /**
   * Returns true if this is a retained builder and reuse stacking contexts
   * mode is enabled by pref.
   */

  bool IsReusingStackingContextItems() const {
    return mIsReusingStackingContextItems;
  }

  /**
   * Adds display item |aItem| to the reuseable display items set.
   */

  void AddReusableDisplayItem(nsDisplayItem* aItem);

  /**
   * Removes display item |aItem| from the reuseable display items set.
   * This is needed because display items are sometimes deleted during
   * display list building.
   * Called by |nsDisplayItem::Destroy()| when the item has been reused.
   */

  void RemoveReusedDisplayItem(nsDisplayItem* aItem);

  /**
   * Clears the reuseable display items set.
   */

  void ClearReuseableDisplayItems();

  /**
   * Marks the given display item |aItem| as reused, and updates the necessary
   * display list builder state.
   */

  void ReuseDisplayItem(nsDisplayItem* aItem);

  void SetIsDestroying() { mIsDestroying = true; }
  bool IsDestroying() const { return mIsDestroying; }

 private:
  bool MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame,
                                    const nsRect& aVisibleRect,
                                    const nsRect& aDirtyRect);

  friend class nsDisplayBackgroundImage;
  friend class RetainedDisplayListBuilder;

  /**
   * Returns whether a frame acts as an animated geometry root, optionally
   * returning the next ancestor to check.
   */

  bool IsAnimatedGeometryRoot(nsIFrame* aFrame, nsIFrame** aParent = nullptr);

  struct PresShellState {
    PresShell* mPresShell;
#ifdef DEBUG
    Maybe<nsAutoLayoutPhase> mAutoLayoutPhase;
#endif
    Maybe<OutOfFlowDisplayData> mFixedBackgroundDisplayData;
    uint32_t mFirstFrameMarkedForDisplay;
    uint32_t mFirstFrameWithOOFData;
    bool mIsBackgroundOnly;
    // 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.
    bool mInsidePointerEventsNoneDoc;
    bool mTouchEventPrefEnabledDoc;
    nsIFrame* mPresShellIgnoreScrollFrame;
    nsIFrame* mCaretFrame = nullptr;
  };

  PresShellState* CurrentPresShellState() {
    NS_ASSERTION(mPresShellStates.Length() > 0,
                 "Someone forgot to enter a presshell");
    return &mPresShellStates[mPresShellStates.Length() - 1];
  }

  void AddSizeOfExcludingThis(nsWindowSizes&) const;

  struct FrameWillChangeBudget {
    FrameWillChangeBudget() : mPresContext(nullptr), mUsage(0) {}

    FrameWillChangeBudget(const nsPresContext* aPresContext, uint32_t aUsage)
        : mPresContext(aPresContext), mUsage(aUsage) {}

    const nsPresContext* mPresContext;
    uint32_t mUsage;
  };

  // will-change budget tracker
  typedef uint32_t DocumentWillChangeBudget;

  nsIFrame* const mReferenceFrame;
  nsIFrame* mIgnoreScrollFrame;

  const ActiveScrolledRoot* mCurrentActiveScrolledRoot;
  const ActiveScrolledRoot* mCurrentContainerASR;
  // mCurrentFrame is the frame that we're currently calling (or about to call)
  // BuildDisplayList on.
  const nsIFrame* mCurrentFrame;
  // The reference frame for mCurrentFrame.
  const nsIFrame* mCurrentReferenceFrame;

  // 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;
  DisplayItemClipChain* mFirstClipChainToDestroy;
  nsTArray<nsDisplayItem*> mTemporaryItems;
  nsDisplayTableBackgroundSet* mTableBackgroundSet;
  ViewID mCurrentScrollParentId;
  ViewID mCurrentScrollbarTarget;

  nsTArray<nsIFrame*> mSVGEffectsFrames;
  // When we are inside a filter, the current ASR at the time we entered the
  // filter. Otherwise nullptr.
  const ActiveScrolledRoot* mFilterASR;
  nsCString mLinkURI;   // URI of link currently being emitted, if any.
  nsCString mLinkDest;  // Local destination name of link, if any.

  // Optimized versions for non-retained display list.
  LayoutDeviceIntRegion mWindowDraggingRegion;
  LayoutDeviceIntRegion mWindowNoDraggingRegion;
  nsRegion mWindowOpaqueRegion;

  nsClassHashtable<nsPtrHashKey<nsDisplayItem>,
                   nsTArray<nsIWidget::ThemeGeometry>>
      mThemeGeometries;
  DisplayListClipState mClipState;
  nsTHashMap<nsPtrHashKey<const nsPresContext>, DocumentWillChangeBudget>
      mDocumentWillChangeBudgets;

  // Any frame listed in this set is already counted in the budget
  // and thus is in-budget.
  nsTHashMap<nsPtrHashKey<const nsIFrame>, FrameWillChangeBudget>
      mFrameWillChangeBudgets;

  nsTHashSet<nsCString> mDestinations;  // Destination names emitted.

  // Stores reusable items collected during display list preprocessing.
  nsTHashSet<nsDisplayItem*> mReuseableItems;

  // Tracked carets used for retained display list.
  AutoTArray<RefPtr<nsCaret>, 1> mPaintedCarets;

  // Tracked regions used for retained display list.
  WeakFrameRegion mRetainedWindowDraggingRegion;
  WeakFrameRegion mRetainedWindowNoDraggingRegion;

  // Window opaque region is calculated during layer building.
  WeakFrameRegion mRetainedWindowOpaqueRegion;

  std::unordered_set<const DisplayItemClipChain*, DisplayItemClipChainHasher,
                     DisplayItemClipChainEqualer>
      mClipDeduplicator;
  std::unordered_set<ScrollContainerFrame*> mScrollContainerFramesToNotify;

  AutoTArray<nsIFrame*, 20> mFramesWithOOFData;
  AutoTArray<nsIFrame*, 40> mFramesMarkedForDisplayIfVisible;
  AutoTArray<PresShellState, 8> mPresShellStates;

  using Arena = nsPresArena<32768, DisplayListArenaObjectId,
                            size_t(DisplayListArenaObjectId::COUNT)>;
  Arena mPool;

  AutoTArray<nsIFrame*, 400> mFramesMarkedForDisplay;

  gfx::CompositorHitTestInfo mCompositorHitTestInfo;

  // The offset from mCurrentFrame to mCurrentReferenceFrame.
  nsPoint mCurrentOffsetToReferenceFrame;

  Maybe<float> mVisibleThreshold;

  Maybe<nsPoint> mAdditionalOffset;

  // Relative to mCurrentFrame.
  nsRect mVisibleRect;
  nsRect mDirtyRect;
  nsRect mCaretRect;

  Preserves3DContext mPreserves3DCtx;

  uint8_t mBuildingExtraPagesForPageNum;

  nsDisplayListBuilderMode mMode;
  static uint32_t sPaintSequenceNumber;

  uint32_t mNumActiveScrollframesEncountered = 0;

  bool mContainsBlendMode;
  bool mIsBuildingScrollbar;
  bool mCurrentScrollbarWillHaveLayer;
  bool mBuildCaret;
  bool mRetainingDisplayList;
  bool mPartialUpdate;
  bool mIgnoreSuppression;
  bool mIncludeAllOutOfFlows;
  bool mDescendIntoSubdocuments;
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=91 H=95 G=92

¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.75Angebot  Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können  ¤

*Eine klare Vorstellung vom Zielzustand






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.