tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsIFrame.h (231071B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 /* interface for all rendering objects */
      8 
      9 #ifndef nsIFrame_h___
     10 #define nsIFrame_h___
     11 
     12 #ifndef MOZILLA_INTERNAL_API
     13 #error This header/class should only be used within Mozilla code. It should not be used by extensions.
     14 #endif
     15 
     16 #if (defined(XP_WIN) && !defined(HAVE_64BIT_BUILD)) || defined(ANDROID)
     17 // Blink's magic depth limit from its HTML parser (513) plus as much as fits in
     18 // the default run-time stack on armv7 Android on Dalvik when using display:
     19 // block minus a bit just to be sure. The Dalvik default stack crashes at 588.
     20 // ART can do a few frames more. Using the same number for 32-bit Windows for
     21 // consistency. Over there, Blink's magic depth of 513 doesn't fit in the
     22 // default stack of 1 MB, but this magic depth fits when the default is grown by
     23 // mere 192 KB (tested in 64 KB increments).
     24 //
     25 // 32-bit Windows has a different limit compared to 64-bit desktop, because the
     26 // default stack size affects all threads and consumes address space. Fixing
     27 // that is bug 1257522.
     28 //
     29 // 32-bit Android on ARM already happens to have defaults that are close enough
     30 // to what makes sense as a temporary measure on Windows, so adjusting the
     31 // Android stack can be a follow-up. The stack on 64-bit ARM needs adjusting in
     32 // any case before 64-bit ARM can become tier-1. See bug 1400811.
     33 //
     34 // Ideally, we'd get rid of this smaller limit and make 32-bit Windows and
     35 // Android capable of working with the Linux/Mac/Win64 number below.
     36 #  define MAX_REFLOW_DEPTH 585
     37 #else
     38 // Blink's magic depth limit from its HTML parser times two. Also just about
     39 // fits within the system default runtime stack limit of 8 MB on 64-bit Mac and
     40 // Linux with display: table-cell.
     41 #  define MAX_REFLOW_DEPTH 1026
     42 #endif
     43 
     44 /* nsIFrame is in the process of being deCOMtaminated, i.e., this file is
     45   eventually going to be eliminated, and all callers will use nsFrame instead.
     46   At the moment we're midway through this process, so you will see inlined
     47   functions and member variables in this file.  -dwh */
     48 
     49 #include <stdio.h>
     50 
     51 #include <algorithm>
     52 
     53 #include "FrameProperties.h"
     54 #include "LayoutConstants.h"
     55 #include "Visibility.h"
     56 #include "mozilla/AspectRatio.h"
     57 #include "mozilla/Attributes.h"
     58 #include "mozilla/Baseline.h"
     59 #include "mozilla/ComputedStyle.h"
     60 #include "mozilla/EnumSet.h"
     61 #include "mozilla/EventForwards.h"
     62 #include "mozilla/Maybe.h"
     63 #include "mozilla/ReflowInput.h"
     64 #include "mozilla/RelativeTo.h"
     65 #include "mozilla/Result.h"
     66 #include "mozilla/SmallPointerArray.h"
     67 #include "mozilla/ToString.h"
     68 #include "mozilla/WritingModes.h"
     69 #include "mozilla/gfx/2D.h"
     70 #include "mozilla/gfx/CompositorHitTestInfo.h"
     71 #include "mozilla/gfx/MatrixFwd.h"
     72 #include "mozilla/intl/BidiEmbeddingLevel.h"
     73 #include "mozilla/intl/UnicodeProperties.h"
     74 #include "nsChangeHint.h"
     75 #include "nsDirection.h"
     76 #include "nsDisplayItemTypes.h"
     77 #include "nsFrameList.h"
     78 #include "nsFrameState.h"
     79 #include "nsIContent.h"
     80 #include "nsITheme.h"
     81 #include "nsPresContext.h"
     82 #include "nsQueryFrame.h"
     83 #include "nsStyleStruct.h"
     84 #include "nsStyleStructList.h"
     85 #include "nsTHashSet.h"
     86 
     87 #ifdef ACCESSIBILITY
     88 #  include "mozilla/a11y/AccTypes.h"
     89 #endif
     90 
     91 /**
     92 * New rules of reflow:
     93 * 1. you get a WillReflow() followed by a Reflow() followed by a DidReflow() in
     94 *    order (no separate pass over the tree)
     95 * 2. it's the parent frame's responsibility to size/position the child's view
     96 *    (not the child frame's responsibility as it is today) during reflow (and
     97 *    before sending the DidReflow() notification)
     98 * 3. positioning of child frames (and their views) is done on the way down the
     99 *    tree, and sizing of child frames (and their views) on the way back up
    100 * 4. if you move a frame (outside of the reflow process, or after reflowing
    101 *    it), then you must make sure that its view (or its child frame's views)
    102 *    are re-positioned as well. It's reasonable to not position the view until
    103 *    after all reflowing the entire line, for example, but the frame should
    104 *    still be positioned and sized (and the view sized) during the reflow
    105 *    (i.e., before sending the DidReflow() notification)
    106 * 5. the view system handles moving of widgets, i.e., it's not our problem
    107 */
    108 
    109 class nsAtom;
    110 class nsView;
    111 class nsFrameSelection;
    112 class nsIWidget;
    113 class nsISelectionController;
    114 class nsILineIterator;
    115 class nsTextControlFrame;
    116 class gfxSkipChars;
    117 class gfxSkipCharsIterator;
    118 class gfxContext;
    119 class nsLineLink;
    120 template <typename Link, bool>
    121 class GenericLineListIterator;
    122 using LineListIterator = GenericLineListIterator<nsLineLink, false>;
    123 class nsContainerFrame;
    124 class nsPlaceholderFrame;
    125 class nsStyleChangeList;
    126 class nsViewManager;
    127 class nsWindowSizes;
    128 
    129 enum class AttrModType : uint8_t;  // Defined by nsIMutationObserver.h
    130 
    131 struct CharacterDataChangeInfo;
    132 
    133 namespace mozilla {
    134 
    135 enum class CaretAssociationHint;
    136 enum class IsFocusableFlags : uint8_t;
    137 enum class PeekOffsetOption : uint16_t;
    138 enum class PseudoStyleType : uint8_t;
    139 enum class TableSelectionMode : uint32_t;
    140 
    141 class AbsoluteContainingBlock;
    142 class AnchorPosReferenceData;
    143 struct LastSuccessfulPositionData;
    144 class EffectSet;
    145 class LazyLogModule;
    146 class nsDisplayItem;
    147 class nsDisplayList;
    148 class nsDisplayListBuilder;
    149 class nsDisplayListSet;
    150 class PresShell;
    151 class ScrollContainerFrame;
    152 class ServoRestyleState;
    153 class WidgetGUIEvent;
    154 class WidgetMouseEvent;
    155 
    156 void DeleteAnchorPosReferenceData(AnchorPosReferenceData*);
    157 void DeleteLastSuccessfulPositionData(LastSuccessfulPositionData*);
    158 
    159 struct PeekOffsetStruct;
    160 
    161 namespace layers {
    162 class Layer;
    163 class LayerManager;
    164 }  // namespace layers
    165 
    166 namespace layout {
    167 class ScrollAnchorContainer;
    168 }  // namespace layout
    169 
    170 }  // namespace mozilla
    171 
    172 //----------------------------------------------------------------------
    173 
    174 // 1 million CSS pixels less than our max app unit measure.
    175 // For reflowing with an "infinite" available inline space per [css-sizing].
    176 // (reflowing with an NS_UNCONSTRAINEDSIZE available inline size isn't allowed
    177 //  and leads to assertions)
    178 #define INFINITE_ISIZE_COORD nscoord(NS_MAXSIZE - (1000000 * 60))
    179 
    180 //----------------------------------------------------------------------
    181 
    182 namespace mozilla {
    183 
    184 enum class LayoutFrameType : uint8_t {
    185 #define FRAME_TYPE(ty_, ...) ty_,
    186 #include "mozilla/FrameTypeList.h"
    187 #undef FRAME_TYPE
    188 };
    189 
    190 // Stores ascent and descent metrics to be used for Ruby annotation positioning
    191 // (potentially different from line-box or font ascent and descent).
    192 struct RubyMetrics {
    193  nscoord mAscent = 0;
    194  nscoord mDescent = 0;
    195 
    196  void CombineWith(const RubyMetrics& aOther) {
    197    mAscent = std::max(mAscent, aOther.mAscent);
    198    mDescent = std::max(mDescent, aOther.mDescent);
    199  }
    200 };
    201 
    202 }  // namespace mozilla
    203 
    204 enum nsSelectionAmount {
    205  eSelectCharacter = 0,  // a single Unicode character;
    206                         // do not use this (prefer Cluster) unless you
    207                         // are really sure it's what you want
    208  eSelectCluster = 1,    // a grapheme cluster: this is usually the right
    209                         // choice for movement or selection by "character"
    210                         // as perceived by the user
    211  eSelectWord = 2,
    212  eSelectWordNoSpace = 3,  // select a "word" without selecting the following
    213                           // space, no matter what the default platform
    214                           // behavior is
    215  eSelectLine = 4,         // previous drawn line in flow.
    216  // NOTE that selection code depends on the ordering of the above values,
    217  // allowing simple <= tests to check categories of caret movement.
    218  // Don't rearrange without checking the usage in nsSelection.cpp!
    219 
    220  eSelectBeginLine = 5,
    221  eSelectEndLine = 6,
    222  eSelectNoAmount = 7,  // just bounce back current offset.
    223  eSelectParagraph = 8  // select a "paragraph"
    224 };
    225 
    226 //----------------------------------------------------------------------
    227 // Reflow status returned by the Reflow() methods.
    228 class nsReflowStatus final {
    229 public:
    230  nsReflowStatus()
    231      : mFloatClearType(mozilla::UsedClear::None),
    232        mInlineBreak(InlineBreak::None),
    233        mCompletion(Completion::FullyComplete),
    234        mNextInFlowNeedsReflow(false),
    235        mFirstLetterComplete(false) {}
    236 
    237  // Reset all the member variables.
    238  void Reset() {
    239    mFloatClearType = mozilla::UsedClear::None;
    240    mInlineBreak = InlineBreak::None;
    241    mCompletion = Completion::FullyComplete;
    242    mNextInFlowNeedsReflow = false;
    243    mFirstLetterComplete = false;
    244  }
    245 
    246  // Return true if all member variables have their default values.
    247  bool IsEmpty() const {
    248    return (IsFullyComplete() && !IsInlineBreak() && !mNextInFlowNeedsReflow &&
    249            !mFirstLetterComplete);
    250  }
    251 
    252  // There are three possible completion statuses, represented by
    253  // mCompletion.
    254  //
    255  // Incomplete means the frame does *not* map all its content, and the
    256  // parent frame should create a continuing frame.
    257  //
    258  // OverflowIncomplete means that the frame has an overflow that is not
    259  // complete, but its own box is complete. (This happens when the content
    260  // overflows a fixed-height box.) The reflower should place and size the
    261  // frame and continue its reflow, but it needs to create an overflow
    262  // container as a continuation for this frame. See "Overflow containers"
    263  // documentation in nsContainerFrame.h for more information.
    264  //
    265  // FullyComplete means the frame is neither Incomplete nor
    266  // OverflowIncomplete. This is the default state for a nsReflowStatus.
    267  //
    268  enum class Completion : uint8_t {
    269    // The order of the enum values is important, which represents the
    270    // precedence when merging.
    271    FullyComplete,
    272    OverflowIncomplete,
    273    Incomplete,
    274  };
    275 
    276  bool IsIncomplete() const { return mCompletion == Completion::Incomplete; }
    277  bool IsOverflowIncomplete() const {
    278    return mCompletion == Completion::OverflowIncomplete;
    279  }
    280  bool IsFullyComplete() const {
    281    return mCompletion == Completion::FullyComplete;
    282  }
    283  // Just for convenience; not a distinct state.
    284  bool IsComplete() const { return !IsIncomplete(); }
    285 
    286  void SetIncomplete() { mCompletion = Completion::Incomplete; }
    287  void SetOverflowIncomplete() { mCompletion = Completion::OverflowIncomplete; }
    288 
    289  // mNextInFlowNeedsReflow bit flag means that the next-in-flow is dirty,
    290  // and also needs to be reflowed. This status only makes sense for a frame
    291  // that is not complete, i.e. you wouldn't set mNextInFlowNeedsReflow when
    292  // IsComplete() is true.
    293  bool NextInFlowNeedsReflow() const { return mNextInFlowNeedsReflow; }
    294  void SetNextInFlowNeedsReflow() { mNextInFlowNeedsReflow = true; }
    295 
    296  // Merge the frame completion status bits from aStatus into this.
    297  void MergeCompletionStatusFrom(const nsReflowStatus& aStatus) {
    298    if (mCompletion < aStatus.mCompletion) {
    299      mCompletion = aStatus.mCompletion;
    300    }
    301 
    302    // These asserts ensure that the mCompletion merging works as we expect.
    303    // (Incomplete beats OverflowIncomplete, which beats FullyComplete.)
    304    static_assert(
    305        Completion::Incomplete > Completion::OverflowIncomplete &&
    306            Completion::OverflowIncomplete > Completion::FullyComplete,
    307        "mCompletion merging won't work without this!");
    308 
    309    mNextInFlowNeedsReflow |= aStatus.mNextInFlowNeedsReflow;
    310  }
    311 
    312  // There are three possible inline-break statuses, represented by
    313  // mInlineBreak.
    314  //
    315  // "None" means no break is requested.
    316  // "Before" means the break should occur before the frame.
    317  // "After" means the break should occur after the frame.
    318  // (Here, "the frame" is the frame whose reflow results are being reported by
    319  // this nsReflowStatus.)
    320  //
    321  enum class InlineBreak : uint8_t {
    322    None,
    323    Before,
    324    After,
    325  };
    326 
    327  bool IsInlineBreak() const { return mInlineBreak != InlineBreak::None; }
    328  bool IsInlineBreakBefore() const {
    329    return mInlineBreak == InlineBreak::Before;
    330  }
    331  bool IsInlineBreakAfter() const { return mInlineBreak == InlineBreak::After; }
    332  mozilla::UsedClear FloatClearType() const { return mFloatClearType; }
    333 
    334  // Set the inline line-break-before status, and reset other bit flags. Note
    335  // that other frame completion status isn't expected to matter after calling
    336  // this method.
    337  //
    338  // Here's one scenario where a child frame would report this status. Suppose
    339  // the child has "break-inside:avoid" in its style, and the child (and its
    340  // content) won't fit in the available block-size. This child would want to
    341  // report this status so that it gets pushed (in its entirety) to the next
    342  // column/page where it will hopefully fit.
    343  void SetInlineLineBreakBeforeAndReset() {
    344    Reset();
    345    mFloatClearType = mozilla::UsedClear::None;
    346    mInlineBreak = InlineBreak::Before;
    347  }
    348 
    349  // Set the inline line-break-after status. The clear type can be changed
    350  // via the optional aClearType param.
    351  void SetInlineLineBreakAfter(
    352      mozilla::UsedClear aClearType = mozilla::UsedClear::None) {
    353    mFloatClearType = aClearType;
    354    mInlineBreak = InlineBreak::After;
    355  }
    356 
    357  // mFirstLetterComplete bit flag means the break was induced by
    358  // completion of a first-letter.
    359  bool FirstLetterComplete() const { return mFirstLetterComplete; }
    360  void SetFirstLetterComplete() { mFirstLetterComplete = true; }
    361 
    362 private:
    363  mozilla::UsedClear mFloatClearType;
    364  InlineBreak mInlineBreak;
    365  Completion mCompletion;
    366  bool mNextInFlowNeedsReflow : 1;
    367  bool mFirstLetterComplete : 1;
    368 };
    369 
    370 // Convert nsReflowStatus to a human-readable string.
    371 std::ostream& operator<<(std::ostream& aStream, const nsReflowStatus& aStatus);
    372 
    373 namespace mozilla {
    374 
    375 // Loosely: https://drafts.csswg.org/css-align-3/#shared-alignment-context
    376 enum class AlignmentContext {
    377  Inline,
    378  Table,
    379  Flexbox,
    380  Grid,
    381 };
    382 
    383 /*
    384 * For replaced elements only. Gets the intrinsic dimensions of this element,
    385 * which can be specified on a per-axis basis.
    386 */
    387 struct IntrinsicSize {
    388  Maybe<nscoord> width;
    389  Maybe<nscoord> height;
    390 
    391  IntrinsicSize() = default;
    392 
    393  IntrinsicSize(nscoord aWidth, nscoord aHeight)
    394      : width(Some(aWidth)), height(Some(aHeight)) {}
    395 
    396  explicit IntrinsicSize(const nsSize& aSize)
    397      : IntrinsicSize(aSize.Width(), aSize.Height()) {}
    398 
    399  Maybe<nsSize> ToSize() const {
    400    return width && height ? Some(nsSize(*width, *height)) : Nothing();
    401  }
    402 
    403  Maybe<nscoord>& ISize(WritingMode aWM) {
    404    return aWM.IsVertical() ? height : width;
    405  }
    406  const Maybe<nscoord>& ISize(WritingMode aWM) const {
    407    return aWM.IsVertical() ? height : width;
    408  }
    409 
    410  Maybe<nscoord>& BSize(WritingMode aWM) {
    411    return aWM.IsVertical() ? width : height;
    412  }
    413  const Maybe<nscoord>& BSize(WritingMode aWM) const {
    414    return aWM.IsVertical() ? width : height;
    415  }
    416 
    417  void Zoom(const StyleZoom& aZoom) {
    418    if (width) {
    419      *width = aZoom.ZoomCoord(*width);
    420    }
    421    if (height) {
    422      *height = aZoom.ZoomCoord(*height);
    423    }
    424  }
    425 
    426  bool operator==(const IntrinsicSize&) const = default;
    427  bool operator!=(const IntrinsicSize&) const = default;
    428 };
    429 
    430 // Pseudo bidi embedding level indicating nonexistence.
    431 constexpr mozilla::intl::BidiEmbeddingLevel kBidiLevelNone(0xff);
    432 
    433 struct FrameBidiData {
    434  mozilla::intl::BidiEmbeddingLevel baseLevel;
    435  mozilla::intl::BidiEmbeddingLevel embeddingLevel;
    436  // The embedding level of virtual bidi formatting character before
    437  // this frame if any. kBidiLevelNone is used to indicate nonexistence
    438  // or unnecessity of such virtual character.
    439  mozilla::intl::BidiEmbeddingLevel precedingControl;
    440 };
    441 
    442 // A struct aggregates necessary data to compute the intrinsic sizes for a
    443 // frame, typically the frame whose intrinsic size contribution is being
    444 // requested. This struct is used as an input for GetMinISize(), GetPrefISize(),
    445 // IntrinsicISize(), and others.
    446 struct MOZ_STACK_CLASS IntrinsicSizeInput final {
    447  gfxContext* const mContext;
    448 
    449  // The content-box size of a frame's containing block (in the frame's own
    450  // writing mode), used as a percentage basis for percentage-based sizes on the
    451  // frame itself that contribute to its intrinsic size. For example, in grid
    452  // layout, a percentage value of min-height be can transferred through the
    453  // aspect-ratio to determine auto repeat columns specified in
    454  // grid-template-columns.
    455  //
    456  // Note: it is acceptable for mContainingBlockSize to be Nothing() as long as
    457  // the frame doesn't have percentage-based value for properties that need to
    458  // be resolved in order to compute its intrinsic size.
    459  Maybe<LogicalSize> mContainingBlockSize;
    460 
    461  // The content-box size of a frame (in the frame's own writing mode), served
    462  // as a percentage basis when computing the children's intrinsic
    463  // contributions. If the basis is indefinite in a given axis, use
    464  // NS_UNCONSTRAINEDSIZE for that component. If the value is Nothing, it is
    465  // semantically equivalent to NS_UNCONSTRAINEDSIZE in both axes.
    466  //
    467  // In most scenarios, this struct is used when computing the inline size
    468  // contribution, so the inline component of the percentage basis should be set
    469  // to NS_UNCONSTRAINEDSIZE.
    470  Maybe<LogicalSize> mPercentageBasisForChildren;
    471 
    472  bool HasSomePercentageBasisForChildren() const {
    473    return mPercentageBasisForChildren &&
    474           !mPercentageBasisForChildren->IsAllValues(NS_UNCONSTRAINEDSIZE);
    475  }
    476 
    477  IntrinsicSizeInput(gfxContext* aContext,
    478                     const Maybe<LogicalSize>& aContainingBlockSize,
    479                     const Maybe<LogicalSize>& aPercentageBasisForChildren)
    480      : mContext(aContext),
    481        mContainingBlockSize(aContainingBlockSize),
    482        mPercentageBasisForChildren(aPercentageBasisForChildren) {
    483    MOZ_ASSERT(mContext);
    484  }
    485 
    486  // Construct a new IntrinsicSizeInput for children by copying from
    487  // aParentInput.
    488  //
    489  // Note: since this constructor creates an IntrinsicSizeInput for the
    490  // children, it does not copy mContainingBlockSize from aParentInput.
    491  //
    492  // This constructor converts mPercentageBasisForChildren's writing mode, if it
    493  // exists. The original mPercentageBasis in aSource is expected to be in the
    494  // writing mode aFromWM, and it will be converted to the writing mode aToWM.
    495  IntrinsicSizeInput(const IntrinsicSizeInput& aParentInput,
    496                     mozilla::WritingMode aToWM, mozilla::WritingMode aFromWM)
    497      : IntrinsicSizeInput(
    498            aParentInput.mContext, Nothing(),
    499            aParentInput.mPercentageBasisForChildren.map([&](const auto& aPB) {
    500              return aPB.ConvertTo(aToWM, aFromWM);
    501            })) {}
    502 };
    503 
    504 }  // namespace mozilla
    505 
    506 /// Generic destructor for frame properties. Calls delete.
    507 template <typename T>
    508 static void DeleteValue(T* aPropertyValue) {
    509  delete aPropertyValue;
    510 }
    511 
    512 /// Generic destructor for frame properties. Calls Release().
    513 template <typename T>
    514 static void ReleaseValue(T* aPropertyValue) {
    515  aPropertyValue->Release();
    516 }
    517 
    518 //----------------------------------------------------------------------
    519 
    520 /**
    521 * nsIFrame logging constants. We redefine the nspr
    522 * PRLogModuleInfo.level field to be a bitfield.  Each bit controls a
    523 * specific type of logging. Each logging operation has associated
    524 * inline methods defined below.
    525 *
    526 * Due to the redefinition of the level field we cannot use MOZ_LOG directly
    527 * as that will cause assertions due to invalid log levels.
    528 */
    529 #define NS_FRAME_TRACE_CALLS 0x1
    530 #define NS_FRAME_TRACE_PUSH_PULL 0x2
    531 #define NS_FRAME_TRACE_CHILD_REFLOW 0x4
    532 #define NS_FRAME_TRACE_NEW_FRAMES 0x8
    533 
    534 #define NS_FRAME_LOG_TEST(_lm, _bit) \
    535  (int(((mozilla::LogModule*)(_lm))->Level()) & (_bit))
    536 
    537 #ifdef DEBUG
    538 #  define NS_FRAME_LOG(_bit, _args)                           \
    539    PR_BEGIN_MACRO                                            \
    540    if (NS_FRAME_LOG_TEST(nsIFrame::sFrameLogModule, _bit)) { \
    541      printf_stderr _args;                                    \
    542    }                                                         \
    543    PR_END_MACRO
    544 #else
    545 #  define NS_FRAME_LOG(_bit, _args)
    546 #endif
    547 
    548 // XXX Need to rework this so that logging is free when it's off
    549 #ifdef DEBUG
    550 #  define NS_FRAME_TRACE_IN(_method) Trace(_method, true)
    551 
    552 #  define NS_FRAME_TRACE_OUT(_method) Trace(_method, false)
    553 
    554 #  define NS_FRAME_TRACE(_bit, _args)                         \
    555    PR_BEGIN_MACRO                                            \
    556    if (NS_FRAME_LOG_TEST(nsIFrame::sFrameLogModule, _bit)) { \
    557      TraceMsg _args;                                         \
    558    }                                                         \
    559    PR_END_MACRO
    560 
    561 #  define NS_FRAME_TRACE_REFLOW_IN(_method) Trace(_method, true)
    562 
    563 #  define NS_FRAME_TRACE_REFLOW_OUT(_method, _status) \
    564    Trace(_method, false, _status)
    565 
    566 #else
    567 #  define NS_FRAME_TRACE(_bits, _args)
    568 #  define NS_FRAME_TRACE_IN(_method)
    569 #  define NS_FRAME_TRACE_OUT(_method)
    570 #  define NS_FRAME_TRACE_REFLOW_IN(_method)
    571 #  define NS_FRAME_TRACE_REFLOW_OUT(_method, _status)
    572 #endif
    573 
    574 //----------------------------------------------------------------------
    575 
    576 // Frame allocation boilerplate macros. Every subclass of nsFrame must
    577 // either use NS_{DECL,IMPL}_FRAMEARENA_HELPERS pair for allocating
    578 // memory correctly, or use NS_DECL_ABSTRACT_FRAME to declare a frame
    579 // class abstract and stop it from being instantiated. If a frame class
    580 // without its own operator new and GetFrameId gets instantiated, the
    581 // per-frame recycler lists in nsPresArena will not work correctly,
    582 // with potentially catastrophic consequences (not enough memory is
    583 // allocated for a frame object).
    584 
    585 #define NS_DECL_FRAMEARENA_HELPERS(class)                                      \
    586  NS_DECL_QUERYFRAME_TARGET(class)                                             \
    587  static constexpr nsIFrame::ClassID kClassID = nsIFrame::ClassID::class##_id; \
    588  void* operator new(size_t, mozilla::PresShell*) MOZ_MUST_OVERRIDE;           \
    589  nsQueryFrame::FrameIID GetFrameId() const override MOZ_MUST_OVERRIDE {       \
    590    return nsQueryFrame::class##_id;                                           \
    591  }
    592 
    593 #define NS_IMPL_FRAMEARENA_HELPERS(class)                             \
    594  void* class ::operator new(size_t sz, mozilla::PresShell* aShell) { \
    595    return aShell->AllocateFrame(nsQueryFrame::class##_id, sz);       \
    596  }
    597 
    598 #define NS_DECL_ABSTRACT_FRAME(class)                                         \
    599  void* operator new(size_t, mozilla::PresShell*) MOZ_MUST_OVERRIDE = delete; \
    600  nsQueryFrame::FrameIID GetFrameId() const override MOZ_MUST_OVERRIDE = 0;
    601 
    602 //----------------------------------------------------------------------
    603 
    604 namespace mozilla {
    605 
    606 // A simple class to group stuff that we need to keep around when tearing down
    607 // a frame tree.
    608 //
    609 // Native anonymous content created by the frames need to get unbound _after_
    610 // the frame has been destroyed, see bug 1400618.
    611 //
    612 // We destroy the anonymous content bottom-up (so, in reverse order), because
    613 // it's a bit simpler, though we generally don't have that much nested anonymous
    614 // content (except for scrollbars).
    615 struct MOZ_RAII FrameDestroyContext {
    616  explicit FrameDestroyContext(PresShell* aPs) : mPresShell(aPs) {}
    617 
    618  void AddAnonymousContent(already_AddRefed<nsIContent>&& aContent) {
    619    if (RefPtr<nsIContent> content = aContent) {
    620      mAnonymousContent.AppendElement(std::move(content));
    621    }
    622  }
    623 
    624  ~FrameDestroyContext();
    625 
    626 private:
    627  PresShell* const mPresShell;
    628  AutoTArray<RefPtr<nsIContent>, 100> mAnonymousContent;
    629 };
    630 
    631 /**
    632 * Bit-flags specific to a given layout class id.
    633 */
    634 enum class LayoutFrameClassFlags : uint32_t {
    635  None = 0,
    636  Leaf = 1 << 0,
    637  LeafDynamic = 1 << 1,
    638  MathML = 1 << 2,
    639  SVG = 1 << 3,
    640  SVGContainer = 1 << 4,
    641  BidiInlineContainer = 1 << 5,
    642  // The frame is for a replaced element, such as an image. Note that HTML
    643  // <button> elements don't have this flag but still behave as replaced, see
    644  // nsIFrame::IsReplaced().
    645  Replaced = 1 << 6,
    646  // A replaced element that has replaced-element sizing characteristics (i.e.,
    647  // like images or iframes), as opposed to inline-block sizing characteristics
    648  // (like form controls).
    649  ReplacedSizing = 1 << 7,
    650  // A frame that participates in inline reflow, i.e., one that requires
    651  // ReflowInput::mLineLayout.
    652  LineParticipant = 1 << 8,
    653  // Whether this frame is a table part (but not a table or table wrapper).
    654  TablePart = 1 << 9,
    655  CanContainOverflowContainers = 1 << 10,
    656  // Whether the frame supports CSS transforms.
    657  SupportsCSSTransforms = 1 << 11,
    658  // Whether this frame class supports 'contain: layout' and 'contain: paint'
    659  // (supporting one is equivalent to supporting the other).
    660  SupportsContainLayoutAndPaint = 1 << 12,
    661  // Whether this frame class supports the `aspect-ratio` property.
    662  SupportsAspectRatio = 1 << 13,
    663  // Whether this frame class is always a BFC.
    664  BlockFormattingContext = 1 << 14,
    665  // Whether we're a SVG rendering observer container.
    666  SVGRenderingObserverContainer = 1 << 15,
    667 };
    668 
    669 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(LayoutFrameClassFlags)
    670 
    671 }  // namespace mozilla
    672 
    673 /**
    674 * A frame in the layout model. This interface is supported by all frame
    675 * objects.
    676 *
    677 * Frames can have multiple child lists: the default child list
    678 * (referred to as the <i>principal</i> child list, and additional named
    679 * child lists. There is an ordering of frames within a child list, but
    680 * there is no order defined between frames in different child lists of
    681 * the same parent frame.
    682 *
    683 * Frames are NOT reference counted. Use the Destroy() member function
    684 * to destroy a frame. The lifetime of the frame hierarchy is bounded by the
    685 * lifetime of the presentation shell which owns the frames.
    686 *
    687 * nsIFrame is a private Gecko interface. If you are not Gecko then you
    688 * should not use it. If you're not in layout, then you won't be able to
    689 * link to many of the functions defined here. Too bad.
    690 *
    691 * If you're not in layout but you must call functions in here, at least
    692 * restrict yourself to calling virtual methods, which won't hurt you as badly.
    693 */
    694 class nsIFrame : public nsQueryFrame {
    695 public:
    696  using AlignmentContext = mozilla::AlignmentContext;
    697  using BaselineSharingGroup = mozilla::BaselineSharingGroup;
    698  using BaselineExportContext = mozilla::BaselineExportContext;
    699  template <typename T>
    700  using Maybe = mozilla::Maybe<T>;
    701  template <typename T, typename E>
    702  using Result = mozilla::Result<T, E>;
    703  using Nothing = mozilla::Nothing;
    704  using OnNonvisible = mozilla::OnNonvisible;
    705  using ReflowInput = mozilla::ReflowInput;
    706  using SizeComputationInput = mozilla::SizeComputationInput;
    707  using ReflowOutput = mozilla::ReflowOutput;
    708  using Visibility = mozilla::Visibility;
    709  using ContentRelevancy = mozilla::ContentRelevancy;
    710 
    711  using nsDisplayItem = mozilla::nsDisplayItem;
    712  using nsDisplayList = mozilla::nsDisplayList;
    713  using nsDisplayListSet = mozilla::nsDisplayListSet;
    714  using nsDisplayListBuilder = mozilla::nsDisplayListBuilder;
    715 
    716  typedef mozilla::ComputedStyle ComputedStyle;
    717  typedef mozilla::FrameProperties FrameProperties;
    718  typedef mozilla::layers::LayerManager LayerManager;
    719  typedef mozilla::gfx::DrawTarget DrawTarget;
    720  typedef mozilla::gfx::Matrix Matrix;
    721  typedef mozilla::gfx::Matrix4x4 Matrix4x4;
    722  typedef mozilla::gfx::Matrix4x4Flagged Matrix4x4Flagged;
    723  typedef mozilla::Sides Sides;
    724  typedef mozilla::LogicalSides LogicalSides;
    725  typedef mozilla::SmallPointerArray<nsDisplayItem> DisplayItemArray;
    726 
    727  typedef nsQueryFrame::ClassID ClassID;
    728 
    729  using ClassFlags = mozilla::LayoutFrameClassFlags;
    730 
    731 protected:
    732  using ChildList = mozilla::FrameChildList;
    733  using ChildListID = mozilla::FrameChildListID;
    734  using ChildListIDs = mozilla::FrameChildListIDs;
    735 
    736 public:
    737  // nsQueryFrame
    738  NS_DECL_QUERYFRAME
    739  NS_DECL_QUERYFRAME_TARGET(nsIFrame)
    740 
    741  nsIFrame(ComputedStyle* aStyle, nsPresContext* aPresContext, ClassID aID)
    742      : mContent(nullptr),
    743        mComputedStyle(aStyle),
    744        mPresContext(aPresContext),
    745        mParent(nullptr),
    746        mNextSibling(nullptr),
    747        mPrevSibling(nullptr),
    748        mState(NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY),
    749        mWritingMode(aStyle),
    750        mClass(aID),
    751        mMayHaveRoundedCorners(false),
    752        mHasImageRequest(false),
    753        mHasFirstLetterChild(false),
    754        mParentIsWrapperAnonBox(false),
    755        mIsWrapperBoxNeedingRestyle(false),
    756        mReflowRequestedForCharDataChange(false),
    757        mForceDescendIntoIfVisible(false),
    758        mBuiltDisplayList(false),
    759        mFrameIsModified(false),
    760        mHasModifiedDescendants(false),
    761        mHasOverrideDirtyRegion(false),
    762        mMayHaveWillChangeBudget(false),
    763 #ifdef DEBUG
    764        mWasVisitedByAutoFrameConstructionPageName(false),
    765 #endif
    766        mIsPrimaryFrame(false),
    767        mMayHaveTransformAnimation(false),
    768        mMayHaveOpacityAnimation(false),
    769        mAllDescendantsAreInvisible(false),
    770        mHasBSizeChange(false),
    771        mHasPaddingChange(false),
    772        mInScrollAnchorChain(false),
    773        mHasColumnSpanSiblings(false),
    774        mDescendantMayDependOnItsStaticPosition(false) {
    775    MOZ_ASSERT(mComputedStyle);
    776    MOZ_ASSERT(mPresContext);
    777    mozilla::PodZero(&mOverflow);
    778    MOZ_COUNT_CTOR(nsIFrame);
    779  }
    780  explicit nsIFrame(ComputedStyle* aStyle, nsPresContext* aPresContext)
    781      : nsIFrame(aStyle, aPresContext, ClassID::nsIFrame_id) {}
    782 
    783  nsPresContext* PresContext() const { return mPresContext; }
    784 
    785  mozilla::PresShell* PresShell() const { return PresContext()->PresShell(); }
    786 
    787  virtual nsQueryFrame::FrameIID GetFrameId() const MOZ_MUST_OVERRIDE {
    788    return kFrameIID;
    789  }
    790 
    791  /**
    792   * Called to initialize the frame. This is called immediately after creating
    793   * the frame.
    794   *
    795   * If the frame is a continuing frame, then aPrevInFlow indicates the previous
    796   * frame (the frame that was split).
    797   *
    798   * @param   aContent the content object associated with the frame
    799   * @param   aParent the parent frame
    800   * @param   aPrevInFlow the prev-in-flow frame
    801   */
    802  virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
    803                    nsIFrame* aPrevInFlow);
    804 
    805  void* operator new(size_t, mozilla::PresShell*) MOZ_MUST_OVERRIDE;
    806 
    807  using DestroyContext = mozilla::FrameDestroyContext;
    808 
    809  /**
    810   * Flags for PeekOffsetCharacter, PeekOffsetNoAmount, PeekOffsetWord return
    811   * values.
    812   */
    813  enum FrameSearchResult {
    814    // Peek found a appropriate offset within frame.
    815    FOUND = 0x00,
    816    // try next frame for offset.
    817    CONTINUE = 0x1,
    818    // offset not found because the frame was empty of text.
    819    CONTINUE_EMPTY = 0x2 | CONTINUE,
    820    // offset not found because the frame didn't contain any text that could be
    821    // selected.
    822    CONTINUE_UNSELECTABLE = 0x4 | CONTINUE,
    823  };
    824 
    825  /**
    826   * Options for PeekOffsetCharacter().
    827   */
    828  struct MOZ_STACK_CLASS PeekOffsetCharacterOptions {
    829    // Whether to restrict result to valid cursor locations (between grapheme
    830    // clusters) - if this is included, maintains "normal" behavior, otherwise,
    831    // used for selection by "code unit" (instead of "character")
    832    bool mRespectClusters;
    833    // Whether to check user-select style value - if this is included, checks
    834    // if user-select is all, then, it may return CONTINUE_UNSELECTABLE.
    835    bool mIgnoreUserStyleAll;
    836 
    837    PeekOffsetCharacterOptions()
    838        : mRespectClusters(true), mIgnoreUserStyleAll(false) {}
    839  };
    840 
    841  virtual void Destroy(DestroyContext&);
    842 
    843 protected:
    844  /**
    845   * Return true if the frame is part of a Selection.
    846   * Helper method to implement the public IsSelected() API.
    847   */
    848  virtual bool IsFrameSelected() const;
    849 
    850  template <class Source>
    851  friend class do_QueryFrameHelper;  // to read mClass
    852  friend class nsBlockFrame;         // for GetCaretBaseline
    853 
    854  virtual ~nsIFrame();
    855 
    856  // Overridden to prevent the global delete from being called, since
    857  // the memory came out of an arena instead of the heap.
    858  //
    859  // Ideally this would be private and undefined, like the normal
    860  // operator new.  Unfortunately, the C++ standard requires an
    861  // overridden operator delete to be accessible to any subclass that
    862  // defines a virtual destructor, so we can only make it protected;
    863  // worse, some C++ compilers will synthesize calls to this function
    864  // from the "deleting destructors" that they emit in case of
    865  // delete-expressions, so it can't even be undefined.
    866  void operator delete(void* aPtr, size_t sz);
    867 
    868 private:
    869  // Left undefined; nsFrame objects are never allocated from the heap.
    870  void* operator new(size_t sz) noexcept(true);
    871 
    872  // Returns true if this frame has any kind of CSS animations.
    873  bool HasCSSAnimations();
    874 
    875  // Returns true if this frame has any kind of CSS transitions.
    876  bool HasCSSTransitions();
    877 
    878 public:
    879  /**
    880   * Get the content object associated with this frame. Does not add a
    881   * reference.
    882   */
    883  [[nodiscard]] nsIContent* GetContent() const { return mContent; }
    884 
    885  [[nodiscard]] bool ContentIsRootOfNativeAnonymousSubtree() const {
    886    return mContent && mContent->IsRootOfNativeAnonymousSubtree();
    887  }
    888 
    889  [[nodiscard]] inline bool ContentIsEditable() const;
    890 
    891  /**
    892   * @brief Get the closest native anonymous subtree root if the content is in a
    893   * native anonymous subtree.
    894   *
    895   * @return The root of native anonymous subtree which the content belongs to.
    896   * Otherwise, nullptr.
    897   */
    898  nsIContent* GetClosestNativeAnonymousSubtreeRoot() const {
    899    return mContent ? mContent->GetClosestNativeAnonymousSubtreeRoot()
    900                    : nullptr;
    901  }
    902 
    903  /**
    904   * Get the frame that should be the parent for the frames of child elements
    905   * May return nullptr during reflow
    906   */
    907  virtual nsContainerFrame* GetContentInsertionFrame() { return nullptr; }
    908 
    909  /**
    910   * Move any frames on our overflow list to the end of our principal list.
    911   * @return true if there were any overflow frames
    912   */
    913  virtual bool DrainSelfOverflowList() { return false; }
    914 
    915  /**
    916   * Get the frame that should be scrolled if the content associated with this
    917   * frame is targeted for scrolling. For a scroll container frame, this will
    918   * just return the frame itself. For frames like nsTextControlFrame that
    919   * contain a scroll container frame, will return that scroll container frame.
    920   */
    921  virtual mozilla::ScrollContainerFrame* GetScrollTargetFrame() const {
    922    return nullptr;
    923  }
    924 
    925  /**
    926   * Get the offsets of the frame. most will be 0,0
    927   *
    928   */
    929  virtual std::pair<int32_t, int32_t> GetOffsets() const;
    930 
    931  /**
    932   * Reset the offsets when splitting frames during Bidi reordering
    933   *
    934   */
    935  virtual void AdjustOffsetsForBidi(int32_t aStart, int32_t aEnd) {}
    936 
    937  /**
    938   * Get the style associated with this frame.
    939   */
    940  ComputedStyle* Style() const { return mComputedStyle; }
    941 
    942  void AssertNewStyleIsSane(ComputedStyle&)
    943 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
    944      ;
    945 #else
    946  {
    947  }
    948 #endif
    949 
    950  void SetComputedStyle(ComputedStyle* aStyle) {
    951    if (aStyle != mComputedStyle) {
    952      AssertNewStyleIsSane(*aStyle);
    953      RefPtr<ComputedStyle> oldComputedStyle = std::move(mComputedStyle);
    954      mComputedStyle = aStyle;
    955      DidSetComputedStyle(oldComputedStyle);
    956    }
    957  }
    958 
    959  /**
    960   * SetComputedStyleWithoutNotification is for changes to the style that should
    961   * suppress style change processing, in other words, those that aren't really
    962   * changes. This generally means only changes that happen during frame
    963   * construction, or those that get handled out of band, like @position-try
    964   * fallback.
    965   * @return the old style.
    966   */
    967  RefPtr<ComputedStyle> SetComputedStyleWithoutNotification(
    968      RefPtr<ComputedStyle> aStyle) {
    969    return std::exchange(mComputedStyle, std::move(aStyle));
    970  }
    971 
    972 protected:
    973  // Style post processing hook
    974  // Attention: the old style is the one we're forgetting,
    975  // and hence possibly completely bogus for GetStyle* purposes.
    976  // Use PeekStyleData instead.
    977  virtual void DidSetComputedStyle(ComputedStyle* aOldComputedStyle);
    978 
    979 public:
    980 /**
    981 * Define typesafe getter functions for each style struct by
    982 * preprocessing the list of style structs.  These functions are the
    983 * preferred way to get style data.  The macro creates functions like:
    984 *   const nsStyleBorder* StyleBorder();
    985 *   const nsStyleColor* StyleColor();
    986 *
    987 * Callers outside of libxul should use nsIDOMWindow::GetComputedStyle()
    988 * instead of these accessors.
    989 *
    990 * Callers can use Style*WithOptionalParam if they're in a function that
    991 * accepts an *optional* pointer the style struct.
    992 */
    993 #define FRAME_STYLE_ACCESSORS(name_)                                 \
    994  const nsStyle##name_* Style##name_() const MOZ_NONNULL_RETURN {    \
    995    NS_ASSERTION(mComputedStyle, "No style found!");                 \
    996    return mComputedStyle->Style##name_();                           \
    997  }                                                                  \
    998  const nsStyle##name_* Style##name_##WithOptionalParam(             \
    999      const nsStyle##name_* aStyleStruct) const MOZ_NONNULL_RETURN { \
   1000    if (aStyleStruct) {                                              \
   1001      MOZ_ASSERT(aStyleStruct == Style##name_());                    \
   1002      return aStyleStruct;                                           \
   1003    }                                                                \
   1004    return Style##name_();                                           \
   1005  }
   1006  FOR_EACH_STYLE_STRUCT(FRAME_STYLE_ACCESSORS, FRAME_STYLE_ACCESSORS)
   1007 #undef FRAME_STYLE_ACCESSORS
   1008 
   1009  /** Also forward GetVisitedDependentColor to the style */
   1010  template <typename T, typename S>
   1011  nscolor GetVisitedDependentColor(T S::* aField) {
   1012    return mComputedStyle->GetVisitedDependentColor(aField);
   1013  }
   1014 
   1015  /**
   1016   * These methods are to access any additional ComputedStyles that
   1017   * the frame may be holding.
   1018   *
   1019   * These are styles that are children of the frame's primary style and are NOT
   1020   * used as styles for any child frames.
   1021   *
   1022   * These contexts also MUST NOT have any child styles whatsoever. If you need
   1023   * to insert styles into the style tree, then you should create pseudo element
   1024   * frames to own them.
   1025   *
   1026   * The indicies must be consecutive and implementations MUST return null if
   1027   * asked for an index that is out of range.
   1028   */
   1029  virtual ComputedStyle* GetAdditionalComputedStyle(int32_t aIndex) const;
   1030 
   1031  virtual void SetAdditionalComputedStyle(int32_t aIndex,
   1032                                          ComputedStyle* aComputedStyle);
   1033 
   1034  /**
   1035   * @param aSelectionStatus nsISelectionController::getDisplaySelection.
   1036   */
   1037  already_AddRefed<ComputedStyle> ComputeSelectionStyle(
   1038      int16_t aSelectionStatus) const;
   1039 
   1040  already_AddRefed<ComputedStyle> ComputeHighlightSelectionStyle(
   1041      nsAtom* aHighlightName);
   1042 
   1043  already_AddRefed<ComputedStyle> ComputeTargetTextStyle() const;
   1044 
   1045  /**
   1046   * Accessor functions for geometric parent.
   1047   */
   1048  nsContainerFrame* GetParent() const { return mParent; }
   1049 
   1050  bool CanBeDynamicReflowRoot() const;
   1051 
   1052  // Whether we're inside an nsTextControlFrame. This is needed because that
   1053  // frame manages its own selection.
   1054  nsTextControlFrame* GetContainingTextControlFrame() const;
   1055  bool IsInsideTextControl() const { return !!GetContainingTextControlFrame(); }
   1056 
   1057  /**
   1058   * Gets the parent of a frame, using the parent of the placeholder for
   1059   * out-of-flow frames.
   1060   */
   1061  inline nsContainerFrame* GetInFlowParent() const;
   1062 
   1063  /**
   1064   * Gets the primary frame of the closest flattened tree ancestor that has a
   1065   * frame (flattened tree ancestors may not have frames in presence of display:
   1066   * contents).
   1067   */
   1068  inline nsIFrame* GetClosestFlattenedTreeAncestorPrimaryFrame() const;
   1069 
   1070  /**
   1071   * Return the placeholder for this frame (which must be out-of-flow).
   1072   * @note this will only return non-null if |this| is the first-in-flow
   1073   * although we don't assert that here for legacy reasons.
   1074   */
   1075  inline nsPlaceholderFrame* GetPlaceholderFrame() const {
   1076    MOZ_ASSERT(HasAnyStateBits(NS_FRAME_OUT_OF_FLOW));
   1077    return GetProperty(PlaceholderFrameProperty());
   1078  }
   1079 
   1080  /**
   1081   * Set this frame's parent to aParent.
   1082   */
   1083  void SetParent(nsContainerFrame* aParent);
   1084 
   1085  /**
   1086   * The frame's writing-mode, used for logical layout computations.
   1087   * It's usually the 'writing-mode' computed value, but there are exceptions:
   1088   *   * inner table frames copy the value from the table frame
   1089   *     (@see nsTableRowGroupFrame::Init, nsTableRowFrame::Init etc)
   1090   *   * the root element frame propagates its value to its ancestors.
   1091   *     The value may obtain from the principal <body> element.
   1092   *     (@see nsCSSFrameConstructor::ConstructDocElementFrame)
   1093   *   * the internal anonymous frames of the root element copy their value
   1094   *     from the parent.
   1095   *     (@see nsIFrame::Init)
   1096   *   * a scrolled frame propagates its value to its ancestor scroll frame
   1097   *     (@see ScrollContainerFrame::ReloadChildFrames)
   1098   */
   1099  mozilla::WritingMode GetWritingMode() const { return mWritingMode; }
   1100 
   1101  /**
   1102   * Construct a writing mode for line layout in this frame.  This is
   1103   * the writing mode of this frame, except that if this frame is styled with
   1104   * unicode-bidi:plaintext, we reset the direction to the resolved paragraph
   1105   * level of the given subframe (typically the first frame on the line),
   1106   * because the container frame could be split by hard line breaks into
   1107   * multiple paragraphs with different base direction.
   1108   * @param aSelfWM the WM of 'this'
   1109   */
   1110  mozilla::WritingMode WritingModeForLine(mozilla::WritingMode aSelfWM,
   1111                                          nsIFrame* aSubFrame) const;
   1112 
   1113  /**
   1114   * Bounding rect of the frame.
   1115   *
   1116   * For frames that are laid out according to CSS box model rules the values
   1117   * are in app units, and the origin is relative to the upper-left of the
   1118   * geometric parent.  The size includes the content area, borders, and
   1119   * padding.
   1120   *
   1121   * Frames that are laid out according to SVG's coordinate space based rules
   1122   * (frames with the NS_FRAME_SVG_LAYOUT bit set, which *excludes*
   1123   * SVGOuterSVGFrame) are different.  Many frames of this type do not set or
   1124   * use mRect, in which case the frame rect is undefined.  The exceptions are:
   1125   *
   1126   *   - SVGInnerSVGFrame
   1127   *   - SVGGeometryFrame (used for <path>, <circle>, etc.)
   1128   *   - SVGImageFrame
   1129   *   - SVGForeignObjectFrame
   1130   *
   1131   * For these frames the frame rect contains the frame's element's userspace
   1132   * bounds including fill, stroke and markers, but converted to app units
   1133   * rather than being in user units (CSS px).  In the SVG code "userspace" is
   1134   * defined to be the coordinate system for the attributes that define an
   1135   * element's geometry (such as the 'cx' attribute for <circle>).  For more
   1136   * precise details see these frames' implementations of the ReflowSVG method
   1137   * where mRect is set.
   1138   *
   1139   * Note: moving or sizing the frame does not affect the view's size or
   1140   * position.
   1141   */
   1142  nsRect GetRect() const { return mRect; }
   1143  nsPoint GetPosition() const { return mRect.TopLeft(); }
   1144  nsSize GetSize() const { return mRect.Size(); }
   1145  nsRect GetRectRelativeToSelf() const {
   1146    return nsRect(nsPoint(0, 0), mRect.Size());
   1147  }
   1148 
   1149  /**
   1150   * Like the frame's rect (see |GetRect|), which is the border rect,
   1151   * other rectangles of the frame, in app units, relative to the parent.
   1152   */
   1153  nsRect GetPaddingRect() const;
   1154  nsRect GetPaddingRectRelativeToSelf() const;
   1155  nsRect GetContentRect() const;
   1156  nsRect GetContentRectRelativeToSelf() const;
   1157  nsRect GetMarginRect() const;
   1158  nsRect GetMarginRectRelativeToSelf() const;
   1159 
   1160  /**
   1161   * Dimensions and position in logical coordinates in the frame's writing mode
   1162   *  or another writing mode
   1163   */
   1164  mozilla::LogicalRect GetLogicalRect(const nsSize& aContainerSize) const {
   1165    return GetLogicalRect(GetWritingMode(), aContainerSize);
   1166  }
   1167  mozilla::LogicalPoint GetLogicalPosition(const nsSize& aContainerSize) const {
   1168    return GetLogicalPosition(GetWritingMode(), aContainerSize);
   1169  }
   1170  mozilla::LogicalSize GetLogicalSize() const {
   1171    return GetLogicalSize(GetWritingMode());
   1172  }
   1173  mozilla::LogicalRect GetLogicalRect(mozilla::WritingMode aWritingMode,
   1174                                      const nsSize& aContainerSize) const {
   1175    return mozilla::LogicalRect(aWritingMode, GetRect(), aContainerSize);
   1176  }
   1177  mozilla::LogicalPoint GetLogicalPosition(mozilla::WritingMode aWritingMode,
   1178                                           const nsSize& aContainerSize) const {
   1179    return GetLogicalRect(aWritingMode, aContainerSize).Origin(aWritingMode);
   1180  }
   1181  mozilla::LogicalSize GetLogicalSize(mozilla::WritingMode aWritingMode) const {
   1182    return mozilla::LogicalSize(aWritingMode, GetSize());
   1183  }
   1184  nscoord IStart(const nsSize& aContainerSize) const {
   1185    return IStart(GetWritingMode(), aContainerSize);
   1186  }
   1187  nscoord IStart(mozilla::WritingMode aWritingMode,
   1188                 const nsSize& aContainerSize) const {
   1189    return GetLogicalPosition(aWritingMode, aContainerSize).I(aWritingMode);
   1190  }
   1191  nscoord BStart(const nsSize& aContainerSize) const {
   1192    return BStart(GetWritingMode(), aContainerSize);
   1193  }
   1194  nscoord BStart(mozilla::WritingMode aWritingMode,
   1195                 const nsSize& aContainerSize) const {
   1196    return GetLogicalPosition(aWritingMode, aContainerSize).B(aWritingMode);
   1197  }
   1198  nscoord ISize() const { return ISize(GetWritingMode()); }
   1199  nscoord ISize(mozilla::WritingMode aWritingMode) const {
   1200    return GetLogicalSize(aWritingMode).ISize(aWritingMode);
   1201  }
   1202  nscoord BSize() const { return BSize(GetWritingMode()); }
   1203  nscoord BSize(mozilla::WritingMode aWritingMode) const {
   1204    return GetLogicalSize(aWritingMode).BSize(aWritingMode);
   1205  }
   1206  mozilla::LogicalSize ContentSize() const {
   1207    return ContentSize(GetWritingMode());
   1208  }
   1209 
   1210  mozilla::LogicalSize ContentSize(mozilla::WritingMode aWritingMode) const {
   1211    return SizeReducedBy(aWritingMode,
   1212                         GetLogicalUsedBorderAndPadding(GetWritingMode()));
   1213  }
   1214 
   1215  mozilla::LogicalSize PaddingSize(mozilla::WritingMode aWritingMode) const {
   1216    return SizeReducedBy(aWritingMode, GetLogicalUsedBorder(GetWritingMode()));
   1217  }
   1218  nscoord ContentISize(mozilla::WritingMode aWritingMode) const {
   1219    return ContentSize(aWritingMode).ISize(aWritingMode);
   1220  }
   1221  nscoord ContentBSize(mozilla::WritingMode aWritingMode) const {
   1222    return ContentSize(aWritingMode).BSize(aWritingMode);
   1223  }
   1224 
   1225  /**
   1226   * When we change the size of the frame's border-box rect, we may need to
   1227   * reset the overflow rect if it was previously stored as deltas.
   1228   * (If it is currently a "large" overflow and could be re-packed as deltas,
   1229   * we don't bother as the cost of the allocation has already been paid.)
   1230   * @param aRebuildDisplayItems If true, then adds this frame to the
   1231   * list of modified frames for display list building if the rect has changed.
   1232   * Only pass false if you're sure that the relevant display items will be
   1233   * rebuilt already (possibly by an ancestor being in the modified list), or if
   1234   * this is a temporary change.
   1235   */
   1236  void SetRect(const nsRect& aRect, bool aRebuildDisplayItems = true) {
   1237    if (aRect == mRect) {
   1238      return;
   1239    }
   1240    if (mOverflow.mType != OverflowStorageType::Large &&
   1241        mOverflow.mType != OverflowStorageType::None) {
   1242      mozilla::OverflowAreas overflow = GetOverflowAreas();
   1243      mRect = aRect;
   1244      SetOverflowAreas(overflow);
   1245    } else {
   1246      mRect = aRect;
   1247    }
   1248    if (aRebuildDisplayItems) {
   1249      MarkNeedsDisplayItemRebuild();
   1250    }
   1251  }
   1252  /**
   1253   * Set this frame's rect from a logical rect in its own writing direction
   1254   */
   1255  void SetRect(const mozilla::LogicalRect& aRect,
   1256               const nsSize& aContainerSize) {
   1257    SetRect(GetWritingMode(), aRect, aContainerSize);
   1258  }
   1259  /**
   1260   * Set this frame's rect from a logical rect in a different writing direction
   1261   * (GetPhysicalRect will assert if the writing mode doesn't match)
   1262   */
   1263  void SetRect(mozilla::WritingMode aWritingMode,
   1264               const mozilla::LogicalRect& aRect,
   1265               const nsSize& aContainerSize) {
   1266    SetRect(aRect.GetPhysicalRect(aWritingMode, aContainerSize));
   1267  }
   1268 
   1269  /**
   1270   * Set this frame's size from a logical size in its own writing direction.
   1271   * This leaves the frame's logical position unchanged, which means its
   1272   * physical position may change (for right-to-left modes).
   1273   */
   1274  void SetSize(const mozilla::LogicalSize& aSize) {
   1275    SetSize(GetWritingMode(), aSize);
   1276  }
   1277  /*
   1278   * Set this frame's size from a logical size in a different writing direction.
   1279   * This leaves the frame's logical position in the given mode unchanged,
   1280   * which means its physical position may change (for right-to-left modes).
   1281   */
   1282  void SetSize(mozilla::WritingMode aWritingMode,
   1283               const mozilla::LogicalSize& aSize) {
   1284    if (aWritingMode.IsPhysicalRTL()) {
   1285      nscoord oldWidth = mRect.Width();
   1286      SetSize(aSize.GetPhysicalSize(aWritingMode));
   1287      mRect.x -= mRect.Width() - oldWidth;
   1288    } else {
   1289      SetSize(aSize.GetPhysicalSize(aWritingMode));
   1290    }
   1291  }
   1292 
   1293  /**
   1294   * Set this frame's physical size. This leaves the frame's physical position
   1295   * (topLeft) unchanged.
   1296   * @param aRebuildDisplayItems If true, then adds this frame to the
   1297   * list of modified frames for display list building if the size has changed.
   1298   * Only pass false if you're sure that the relevant display items will be
   1299   * rebuilt already (possibly by an ancestor being in the modified list), or if
   1300   * this is a temporary change.
   1301   */
   1302  void SetSize(const nsSize& aSize, bool aRebuildDisplayItems = true) {
   1303    SetRect(nsRect(mRect.TopLeft(), aSize), aRebuildDisplayItems);
   1304  }
   1305 
   1306  void SetPosition(const nsPoint& aPt);
   1307  void SetPosition(mozilla::WritingMode aWritingMode,
   1308                   const mozilla::LogicalPoint& aPt,
   1309                   const nsSize& aContainerSize) {
   1310    // We subtract mRect.Size() from the container size to account for
   1311    // the fact that logical origins in RTL coordinate systems are at
   1312    // the top right of the frame instead of the top left.
   1313    SetPosition(
   1314        aPt.GetPhysicalPoint(aWritingMode, aContainerSize - mRect.Size()));
   1315  }
   1316 
   1317  /**
   1318   * Move the frame, accounting for relative positioning. Use this when
   1319   * adjusting the frame's position by a known amount, to properly update its
   1320   * saved normal position (see GetNormalPosition below).
   1321   *
   1322   * This must be used only when moving a frame *after*
   1323   * ReflowInput::ApplyRelativePositioning is called.  When moving
   1324   * a frame during the reflow process prior to calling
   1325   * ReflowInput::ApplyRelativePositioning, the position should
   1326   * simply be adjusted directly (e.g., using SetPosition()).
   1327   */
   1328  void MovePositionBy(const nsPoint& aTranslation);
   1329 
   1330  /**
   1331   * As above, using a logical-point delta in a given writing mode.
   1332   */
   1333  void MovePositionBy(mozilla::WritingMode aWritingMode,
   1334                      const mozilla::LogicalPoint& aTranslation) {
   1335    // The LogicalPoint represents a vector rather than a point within a
   1336    // rectangular coordinate space, so we use a null containerSize when
   1337    // converting logical to physical.
   1338    const nsSize nullContainerSize;
   1339    MovePositionBy(
   1340        aTranslation.GetPhysicalPoint(aWritingMode, nullContainerSize));
   1341  }
   1342 
   1343  /**
   1344   * Return frame's rect without relative positioning
   1345   */
   1346  nsRect GetNormalRect() const;
   1347  mozilla::LogicalRect GetLogicalNormalRect(
   1348      mozilla::WritingMode aWritingMode, const nsSize& aContainerSize) const {
   1349    return mozilla::LogicalRect(aWritingMode, GetNormalRect(), aContainerSize);
   1350  }
   1351 
   1352  /**
   1353   * Returns frame's rect as required by the GetBoundingClientRect() DOM API.
   1354   */
   1355  nsRect GetBoundingClientRect();
   1356 
   1357  /**
   1358   * Return frame's position without relative positioning.
   1359   * If aHasProperty is provided, returns whether the normal position
   1360   * was stored in a frame property.
   1361   */
   1362  inline nsPoint GetNormalPosition(bool* aHasProperty = nullptr) const;
   1363  inline mozilla::LogicalPoint GetLogicalNormalPosition(
   1364      mozilla::WritingMode aWritingMode, const nsSize& aContainerSize) const;
   1365 
   1366  virtual nsPoint GetPositionOfChildIgnoringScrolling(const nsIFrame* aChild) {
   1367    return aChild->GetPosition();
   1368  }
   1369 
   1370  nsPoint GetPositionIgnoringScrolling() const;
   1371 
   1372 #define NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, dtor)              \
   1373  static const mozilla::FramePropertyDescriptor<type>* prop() {            \
   1374    /* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */     \
   1375    static const auto descriptor =                                         \
   1376        mozilla::FramePropertyDescriptor<type>::NewWithDestructor<dtor>(); \
   1377    return &descriptor;                                                    \
   1378  }
   1379 
   1380 // Don't use this unless you really know what you're doing!
   1381 #define NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(prop, type, dtor) \
   1382  static const mozilla::FramePropertyDescriptor<type>* prop() {        \
   1383    /* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */ \
   1384    static const auto descriptor = mozilla::FramePropertyDescriptor<   \
   1385        type>::NewWithDestructorWithFrame<dtor>();                     \
   1386    return &descriptor;                                                \
   1387  }
   1388 
   1389 #define NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(prop, type)              \
   1390  static const mozilla::FramePropertyDescriptor<type>* prop() {         \
   1391    /* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */  \
   1392    static const auto descriptor =                                      \
   1393        mozilla::FramePropertyDescriptor<type>::NewWithoutDestructor(); \
   1394    return &descriptor;                                                 \
   1395  }
   1396 
   1397 #define NS_DECLARE_FRAME_PROPERTY_DELETABLE(prop, type) \
   1398  NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, DeleteValue)
   1399 
   1400 #define NS_DECLARE_FRAME_PROPERTY_RELEASABLE(prop, type) \
   1401  NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, ReleaseValue)
   1402 
   1403 #define NS_DECLARE_FRAME_PROPERTY_WITH_DTOR_NEVER_CALLED(prop, type) \
   1404  static void AssertOnDestroyingProperty##prop(type*) {              \
   1405    MOZ_ASSERT_UNREACHABLE(                                          \
   1406        "Frame property " #prop                                      \
   1407        " should never be destroyed by the FrameProperties class");  \
   1408  }                                                                  \
   1409  NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type,                    \
   1410                                      AssertOnDestroyingProperty##prop)
   1411 
   1412 #define NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(prop, type) \
   1413  NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(prop, mozilla::SmallValueHolder<type>)
   1414 
   1415  NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(IBSplitSibling, nsContainerFrame)
   1416  NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(IBSplitPrevSibling, nsContainerFrame)
   1417 
   1418  NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(NormalPositionProperty, nsPoint)
   1419  NS_DECLARE_FRAME_PROPERTY_DELETABLE(ComputedOffsetProperty, nsMargin)
   1420 
   1421  NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutlineInnerRectProperty, nsRect)
   1422  NS_DECLARE_FRAME_PROPERTY_DELETABLE(PreEffectsBBoxProperty, nsRect)
   1423  NS_DECLARE_FRAME_PROPERTY_DELETABLE(PreTransformOverflowAreasProperty,
   1424                                      mozilla::OverflowAreas)
   1425 
   1426  NS_DECLARE_FRAME_PROPERTY_DELETABLE(OverflowAreasProperty,
   1427                                      mozilla::OverflowAreas)
   1428 
   1429  // The initial overflow area passed to FinishAndStoreOverflow. This is only
   1430  // set on frames that Preserve3D() or HasPerspective() or IsTransformed(), and
   1431  // when at least one of the overflow areas differs from the frame bound rect.
   1432  NS_DECLARE_FRAME_PROPERTY_DELETABLE(InitialOverflowProperty,
   1433                                      mozilla::OverflowAreas)
   1434 
   1435 #ifdef DEBUG
   1436  // InitialOverflowPropertyDebug is added to the frame to indicate that either
   1437  // the InitialOverflowProperty has been stored or the InitialOverflowProperty
   1438  // has been suppressed due to being set to the default value (frame bounds)
   1439  NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(DebugInitialOverflowPropertyApplied,
   1440                                        bool)
   1441 #endif
   1442 
   1443  NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedMarginProperty, nsMargin)
   1444  NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedPaddingProperty, nsMargin)
   1445  NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(AnchorPosReferences,
   1446                                      mozilla::AnchorPosReferenceData,
   1447                                      mozilla::DeleteAnchorPosReferenceData);
   1448 
   1449  // The last successful position-try-fallbacks index, if present.
   1450  NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(
   1451      LastSuccessfulPositionFallback, mozilla::LastSuccessfulPositionData,
   1452      mozilla::DeleteLastSuccessfulPositionData);
   1453 
   1454  mozilla::PhysicalAxes GetAnchorPosCompensatingForScroll() const;
   1455 
   1456  // This tracks the start and end page value for a frame.
   1457  //
   1458  // https://www.w3.org/TR/css-page-3/#using-named-pages
   1459  //
   1460  // This is only tracked during paginated frame construction.
   1461  // This is used to implement fragmentation based on CSS page names. During
   1462  // frame construction, we insert page breaks when we begin a new page box and
   1463  // the previous page box had a different name.
   1464  struct PageValues {
   1465    // A value of null indicates that the value is equal to what auto resolves
   1466    // to for this frame.
   1467    RefPtr<const nsAtom> mStartPageValue = nullptr;
   1468    RefPtr<const nsAtom> mEndPageValue = nullptr;
   1469  };
   1470  NS_DECLARE_FRAME_PROPERTY_DELETABLE(PageValuesProperty, PageValues)
   1471 
   1472  const nsAtom* GetStartPageValue() const {
   1473    if (const PageValues* const values =
   1474            FirstInFlow()->GetProperty(PageValuesProperty())) {
   1475      return values->mStartPageValue;
   1476    }
   1477    return nullptr;
   1478  }
   1479 
   1480  const nsAtom* GetEndPageValue() const {
   1481    if (const PageValues* const values =
   1482            FirstInFlow()->GetProperty(PageValuesProperty())) {
   1483      return values->mEndPageValue;
   1484    }
   1485    return nullptr;
   1486  }
   1487 
   1488  // Returns the page name based on style information for this frame, or null
   1489  // if the value is auto.
   1490  const nsAtom* GetStylePageName() const {
   1491    const mozilla::StylePageName& pageName = StylePage()->mPage;
   1492    if (pageName.IsPageName()) {
   1493      return pageName.AsPageName().AsAtom();
   1494    }
   1495    MOZ_ASSERT(pageName.IsAuto(), "Impossible page name");
   1496    return nullptr;
   1497  }
   1498 
   1499  bool HasUnreflowedContainerQueryAncestor() const;
   1500 
   1501  // Return True if this frame has a forced break value before it.
   1502  //
   1503  // Note: this method only checks 'break-before' property on *this* frame, and
   1504  // it doesn't handle forced break value propagation from its first child.
   1505  // Callers should handle the propagation in reflow.
   1506  bool ShouldBreakBefore(const ReflowInput::BreakType aBreakType) const;
   1507 
   1508  // Return True if this frame has a forced break value after it.
   1509  //
   1510  // Note: this method only checks 'break-after' property on *this* frame, and
   1511  // it doesn't handle forced break value propagation from its last child.
   1512  // Callers should handle the propagation in reflow.
   1513  bool ShouldBreakAfter(const ReflowInput::BreakType aBreakType) const;
   1514 
   1515 private:
   1516  bool ShouldBreakBetween(const nsStyleDisplay* aDisplay,
   1517                          const mozilla::StyleBreakBetween aBreakBetween,
   1518                          const ReflowInput::BreakType aBreakType) const;
   1519 
   1520  mozilla::LogicalSize SizeReducedBy(mozilla::WritingMode aWritingMode,
   1521                                     mozilla::LogicalMargin aMargin) const {
   1522    mozilla::WritingMode wm = GetWritingMode();
   1523    // aMargin assumed to be in `wm`.
   1524    const auto m = aMargin.ApplySkipSides(GetLogicalSkipSides())
   1525                       .ConvertTo(aWritingMode, wm);
   1526    const auto size = GetLogicalSize(aWritingMode);
   1527    return mozilla::LogicalSize(
   1528        aWritingMode,
   1529        std::max(0, size.ISize(aWritingMode) - m.IStartEnd(aWritingMode)),
   1530        std::max(0, size.BSize(aWritingMode) - m.BStartEnd(aWritingMode)));
   1531  }
   1532 
   1533  // The value that the CSS page-name "auto" keyword resolves to for children
   1534  // of this frame.
   1535  //
   1536  // A missing value for this property indicates that the auto value is the
   1537  // empty string, which is the default if no ancestors of a frame specify a
   1538  // page name. This avoids ever storing this property if the document doesn't
   1539  // use named pages.
   1540  //
   1541  // https://www.w3.org/TR/css-page-3/#using-named-pages
   1542  //
   1543  // Ideally this would be a const atom, but that isn't possible with the
   1544  // Release() call. This isn't too bad, since it's hidden behind constness-
   1545  // preserving getter/setter.
   1546  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(AutoPageValueProperty, nsAtom)
   1547 
   1548 public:
   1549  // Get the value that the CSS page-name "auto" keyword resolves to for
   1550  // children of this frame.
   1551  // This is needed when propagating page-name values up the frame tree.
   1552  const nsAtom* GetAutoPageValue() const {
   1553    if (const nsAtom* const atom = GetProperty(AutoPageValueProperty())) {
   1554      return atom;
   1555    }
   1556    return nsGkAtoms::_empty;
   1557  }
   1558  void SetAutoPageValue(const nsAtom* aAtom) {
   1559    MOZ_ASSERT(aAtom, "Atom must not be null");
   1560    nsAtom* const atom = const_cast<nsAtom*>(aAtom);
   1561    if (atom != nsGkAtoms::_empty) {
   1562      SetProperty(AutoPageValueProperty(), do_AddRef(atom).take());
   1563    }
   1564  }
   1565 
   1566  NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(LineBaselineOffset, nscoord)
   1567 
   1568  NS_DECLARE_FRAME_PROPERTY_DELETABLE(InvalidationRect, nsRect)
   1569 
   1570  NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(RefusedAsyncAnimationProperty, bool)
   1571 
   1572  NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(FragStretchBSizeProperty, nscoord)
   1573 
   1574  // The block-axis margin-box size associated with eBClampMarginBoxMinSize.
   1575  NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BClampMarginBoxMinSizeProperty, nscoord)
   1576 
   1577  NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(IBaselinePadProperty, nscoord)
   1578  NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BBaselinePadProperty, nscoord)
   1579 
   1580  NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BidiDataProperty,
   1581                                        mozilla::FrameBidiData)
   1582 
   1583  NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(PlaceholderFrameProperty,
   1584                                         nsPlaceholderFrame)
   1585 
   1586  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(OffsetPathCache, mozilla::gfx::Path)
   1587 
   1588  mozilla::FrameBidiData GetBidiData() const {
   1589    bool exists;
   1590    mozilla::FrameBidiData bidiData = GetProperty(BidiDataProperty(), &exists);
   1591    if (!exists) {
   1592      bidiData.precedingControl = mozilla::kBidiLevelNone;
   1593    }
   1594    return bidiData;
   1595  }
   1596 
   1597  mozilla::intl::BidiEmbeddingLevel GetBaseLevel() const {
   1598    return GetBidiData().baseLevel;
   1599  }
   1600 
   1601  mozilla::intl::BidiEmbeddingLevel GetEmbeddingLevel() const {
   1602    return GetBidiData().embeddingLevel;
   1603  }
   1604 
   1605  /**
   1606   * Return the distance between the border edge of the frame and the
   1607   * margin edge of the frame.  Like GetRect(), returns the dimensions
   1608   * as of the most recent reflow.
   1609   *
   1610   * This doesn't include any margin collapsing that may have occurred.
   1611   * It also doesn't consider GetSkipSides()/GetLogicalSkipSides(), so
   1612   * may report nonzero values on sides that are actually skipped for
   1613   * this fragment.
   1614   *
   1615   * It also treats 'auto' margins as zero, and treats any margins that
   1616   * should have been turned into 'auto' because of overconstraint as
   1617   * having their original values.
   1618   */
   1619  virtual nsMargin GetUsedMargin() const;
   1620  virtual mozilla::LogicalMargin GetLogicalUsedMargin(
   1621      mozilla::WritingMode aWritingMode) const {
   1622    return mozilla::LogicalMargin(aWritingMode, GetUsedMargin());
   1623  }
   1624 
   1625  /**
   1626   * Return the distance between the border edge of the frame (which is
   1627   * its rect) and the padding edge of the frame. Like GetRect(), returns
   1628   * the dimensions as of the most recent reflow.
   1629   *
   1630   * This doesn't consider GetSkipSides()/GetLogicalSkipSides(), so
   1631   * may report nonzero values on sides that are actually skipped for
   1632   * this fragment.
   1633   *
   1634   * Note that this differs from StyleBorder()->GetComputedBorder() in
   1635   * that this describes a region of the frame's box, and
   1636   * StyleBorder()->GetComputedBorder() describes a border.  They differ
   1637   * for tables (particularly border-collapse tables) and themed
   1638   * elements.
   1639   */
   1640  virtual nsMargin GetUsedBorder() const;
   1641  virtual mozilla::LogicalMargin GetLogicalUsedBorder(
   1642      mozilla::WritingMode aWritingMode) const {
   1643    return mozilla::LogicalMargin(aWritingMode, GetUsedBorder());
   1644  }
   1645 
   1646  /**
   1647   * Return the distance between the padding edge of the frame and the
   1648   * content edge of the frame.  Like GetRect(), returns the dimensions
   1649   * as of the most recent reflow.
   1650   *
   1651   * This doesn't consider GetSkipSides()/GetLogicalSkipSides(), so
   1652   * may report nonzero values on sides that are actually skipped for
   1653   * this fragment.
   1654   */
   1655  virtual nsMargin GetUsedPadding() const;
   1656  virtual mozilla::LogicalMargin GetLogicalUsedPadding(
   1657      mozilla::WritingMode aWritingMode) const {
   1658    return mozilla::LogicalMargin(aWritingMode, GetUsedPadding());
   1659  }
   1660 
   1661  nsMargin GetUsedBorderAndPadding() const {
   1662    return GetUsedBorder() + GetUsedPadding();
   1663  }
   1664  mozilla::LogicalMargin GetLogicalUsedBorderAndPadding(
   1665      mozilla::WritingMode aWritingMode) const {
   1666    return mozilla::LogicalMargin(aWritingMode, GetUsedBorderAndPadding());
   1667  }
   1668 
   1669  /**
   1670   * The area to paint box-shadows around.  The default is the border rect.
   1671   * (nsFieldSetFrame overrides this).
   1672   */
   1673  virtual nsRect VisualBorderRectRelativeToSelf() const {
   1674    return nsRect(0, 0, mRect.Width(), mRect.Height());
   1675  }
   1676 
   1677  /**
   1678   * Get the size, in app units, of the border radii. It returns FALSE iff all
   1679   * returned radii == 0 (so no border radii), TRUE otherwise.
   1680   * For the aRadii indexes, use the enum HalfCorner constants in gfx/2d/Types.h
   1681   * If a side is skipped via aSkipSides, its corners are forced to 0.
   1682   *
   1683   * All corner radii are then adjusted so they do not require more
   1684   * space than aBorderArea, according to the algorithm in css3-background.
   1685   *
   1686   * aFrameSize is used as the basis for percentage widths and heights.
   1687   * aBorderArea is used for the adjustment of radii that might be too
   1688   * large.
   1689   *
   1690   * Return whether any radii are nonzero.
   1691   */
   1692  static bool ComputeBorderRadii(const mozilla::BorderRadius&,
   1693                                 const nsSize& aFrameSize,
   1694                                 const nsSize& aBorderArea, Sides aSkipSides,
   1695                                 nsRectCornerRadii&);
   1696 
   1697  /**
   1698   * Fill in border radii for this frame.  Return whether any are nonzero.
   1699   * Indices into aRadii are the enum HalfCorner constants in gfx/2d/Types.h
   1700   * aSkipSides is a union of SideBits::eLeft/Right/Top/Bottom bits that says
   1701   * which side(s) to skip.
   1702   *
   1703   * Note: GetMarginBoxBorderRadii() and GetShapeBoxBorderRadii() work only
   1704   * on frames that establish block formatting contexts since they don't
   1705   * participate in margin-collapsing.
   1706   */
   1707  virtual bool GetBorderRadii(const nsSize& aFrameSize,
   1708                              const nsSize& aBorderArea, Sides aSkipSides,
   1709                              nsRectCornerRadii&) const;
   1710  bool GetBorderRadii(nsRectCornerRadii&) const;
   1711  bool GetMarginBoxBorderRadii(nsRectCornerRadii&) const;
   1712  bool GetPaddingBoxBorderRadii(nsRectCornerRadii&) const;
   1713  bool GetContentBoxBorderRadii(nsRectCornerRadii&) const;
   1714  bool GetShapeBoxBorderRadii(nsRectCornerRadii&) const;
   1715 
   1716  /**
   1717   * Returns one em unit, adjusted for font inflation if needed, in app units.
   1718   */
   1719  nscoord OneEmInAppUnits() const;
   1720 
   1721  /**
   1722   * Returns the ascent/descent metrics to be used for CSS Ruby positioning
   1723   * (if the "normalize metrics" option is enabled). These are derived from the
   1724   * first available font's "trimmed ascent" and "trimmed descent", where any
   1725   * internal leading included in the font's metrics has been trimmed equally
   1726   * from top and bottom, such that the trimmed values total 1em.
   1727   *
   1728   * @param aRubyMetricsFactor scale to be applied to the em-normalized
   1729   * "trimmed" metrics, to adjust how tightly ruby annotations are positioned
   1730   * around the base text.
   1731   */
   1732  virtual mozilla::RubyMetrics RubyMetrics(float aRubyMetricsFactor) const;
   1733 
   1734  /**
   1735   * `GetNaturalBaselineBOffset`, but determines the baseline sharing group
   1736   * through `GetDefaultBaselineSharingGroup` (If not specified), assuming line
   1737   * layout context, and never fails, returning a synthesized baseline through
   1738   * `SynthesizeFallbackBaseline`. Unlike `GetNaturalBaselineBOffset`, Result is
   1739   * always relative to the block start of the frame.
   1740   */
   1741  nscoord GetLogicalBaseline(mozilla::WritingMode aWM) const;
   1742  /**
   1743   * Same as the above, but with baseline sharing group & export
   1744   * context specified.
   1745   */
   1746  nscoord GetLogicalBaseline(mozilla::WritingMode aWM,
   1747                             BaselineSharingGroup aBaselineGroup,
   1748                             BaselineExportContext aExportContext) const;
   1749 
   1750  /**
   1751   * Return true if the frame has a first(last) inline-axis baseline per
   1752   * CSS Box Alignment.  If so, the returned baseline is the distance from
   1753   * the relevant block-axis border-box edge (Start for
   1754   * BaselineSharingGroup::First, end for BaselineSharingGroup::Last), where
   1755   * a positive value points towards the content-box.
   1756   * Some frames can export different baselines depending if it's in a line
   1757   * layout context or any other context (e.g. Flex, grid).
   1758   * https://drafts.csswg.org/css-align-3/#baseline-export
   1759   * @note The returned value is only valid when reflow is not needed.
   1760   * @note You should only call this on frames with a WM that's parallel to aWM.
   1761   * @note We're approaching `nsLayoutUtils::Get(First|Last)LineBaseline` ==
   1762   * `GetNaturalBaselineBOffset(aWM, (First|Last), Other)`. Grid relies on
   1763   * baseline synthesis behaviour in `nsLayoutUtils` implementations (bug
   1764   * 1609403), which blocks its removal.
   1765   * @param aWM the writing-mode of the alignment context.
   1766   * @return the baseline offset, if one exists
   1767   */
   1768  virtual Maybe<nscoord> GetNaturalBaselineBOffset(
   1769      mozilla::WritingMode aWM, BaselineSharingGroup aBaselineGroup,
   1770      BaselineExportContext aExportContext) const {
   1771    return Nothing{};
   1772  }
   1773 
   1774  struct CaretBlockAxisMetrics {
   1775    nscoord mOffset = 0;
   1776    nscoord mExtent = 0;
   1777  };
   1778  /**
   1779   * Get the offset (Block start of the caret) and extent of the caret in this
   1780   * frame. The returned offset is corrected for vertical & line-inverted
   1781   * writing modes.
   1782   */
   1783  CaretBlockAxisMetrics GetCaretBlockAxisMetrics(mozilla::WritingMode,
   1784                                                 const nsFontMetrics&) const;
   1785  // Gets the page-name value to be used for the page that contains this frame
   1786  // during paginated reflow.
   1787  // This only inspects the first in-flow child of this frame, and if that
   1788  // is a container frame then its first in-flow child, until it reaches the
   1789  // deepest child of the tree.
   1790  // This will resolve auto values, including the case where no frame has a
   1791  // page-name set in which case it will return the empty atom. It will never
   1792  // return null.
   1793  // This is intended to be used either on the root frame to find the first
   1794  // page's page-name, or on a newly created continuation to find what the new
   1795  // page's page-name will be.
   1796  //
   1797  // The auto page value can be set by the caller. This is useful when trying
   1798  // to compute a page value in the middle of a frame tree. In that case the
   1799  // auto value can be found from the AutoPageValue frame property of the
   1800  // parent frame. A null auto value is interpreted as the empty-string atom.
   1801  const nsAtom* ComputePageValue(const nsAtom* aAutoValue = nullptr) const
   1802      MOZ_NONNULL_RETURN;
   1803 
   1804  ///////////////////////////////////////////////////////////////////////////////
   1805  // The public visibility API.
   1806  ///////////////////////////////////////////////////////////////////////////////
   1807 
   1808  /// @return true if we're tracking visibility for this frame.
   1809  bool TrackingVisibility() const {
   1810    return HasAnyStateBits(NS_FRAME_VISIBILITY_IS_TRACKED);
   1811  }
   1812 
   1813  /// @return the visibility state of this frame. See the Visibility enum
   1814  /// for the possible return values and their meanings.
   1815  Visibility GetVisibility() const;
   1816 
   1817  /// Update the visibility state of this frame synchronously.
   1818  /// XXX(seth): Avoid using this method; we should be relying on the refresh
   1819  /// driver for visibility updates. This method, which replaces
   1820  /// nsLayoutUtils::UpdateApproximateFrameVisibility(), exists purely as a
   1821  /// temporary measure to avoid changing behavior during the transition from
   1822  /// the old image visibility code.
   1823  void UpdateVisibilitySynchronously();
   1824 
   1825  // A frame property which stores the visibility state of this frame. Right
   1826  // now that consists of an approximate visibility counter represented as a
   1827  // uint32_t. When the visibility of this frame is not being tracked, this
   1828  // property is absent.
   1829  NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(VisibilityStateProperty, uint32_t);
   1830 
   1831 protected:
   1832  /**
   1833   * Get the position of the baseline on which the caret needs to be placed,
   1834   * relative to the top of the frame.  This is mostly needed for frames
   1835   * which return a baseline from GetBaseline which is not useful for
   1836   * caret positioning.
   1837   */
   1838  virtual nscoord GetCaretBaseline() const {
   1839    return GetLogicalBaseline(GetWritingMode());
   1840  }
   1841 
   1842  // Gets a caret baseline suitable for the frame if the frame doesn't have one.
   1843  //
   1844  // @param aBSize the content box block size of the line container. Needed to
   1845  // resolve line-height: -moz-block-height. NS_UNCONSTRAINEDSIZE is fine
   1846  // otherwise.
   1847  //
   1848  // TODO(emilio): Now we support align-content on blocks it seems we could
   1849  // get rid of line-height: -moz-block-height.
   1850  nscoord GetFontMetricsDerivedCaretBaseline(
   1851      nscoord aBSize = NS_UNCONSTRAINEDSIZE) const;
   1852 
   1853  /**
   1854   * Subclasses can call this method to enable visibility tracking for this
   1855   * frame.
   1856   *
   1857   * If visibility tracking was previously disabled, this will schedule an
   1858   * update an asynchronous update of visibility.
   1859   */
   1860  void EnableVisibilityTracking();
   1861 
   1862  /**
   1863   * Subclasses can call this method to disable visibility tracking for this
   1864   * frame.
   1865   *
   1866   * Note that if visibility tracking was previously enabled, disabling
   1867   * visibility tracking will cause a synchronous call to OnVisibilityChange().
   1868   */
   1869  void DisableVisibilityTracking();
   1870 
   1871  /**
   1872   * Called when a frame transitions between visibility states (for example,
   1873   * from nonvisible to visible, or from visible to nonvisible).
   1874   *
   1875   * @param aNewVisibility    The new visibility state.
   1876   * @param aNonvisibleAction A requested action if the frame has become
   1877   *                          nonvisible. If Nothing(), no action is
   1878   *                          requested. If DISCARD_IMAGES is specified, the
   1879   *                          frame is requested to ask any images it's
   1880   *                          associated with to discard their surfaces if
   1881   *                          possible.
   1882   *
   1883   * Subclasses which override this method should call their parent class's
   1884   * implementation.
   1885   */
   1886  virtual void OnVisibilityChange(
   1887      Visibility aNewVisibility,
   1888      const Maybe<OnNonvisible>& aNonvisibleAction = Nothing());
   1889 
   1890  /**
   1891   * Synthesize a baseline for this element. The returned baseline is the
   1892   * distance from the relevant block-axis border-box edge (Start for
   1893   * BaselineSharingGroup::First, end for BaselineSharingGroup::Last), where a
   1894   * positive value points towards the content-box.
   1895   * @note This always returns a synthesized baseline, even if the element may
   1896   * have an actual baseline.
   1897   */
   1898  virtual nscoord SynthesizeFallbackBaseline(
   1899      mozilla::WritingMode aWM, BaselineSharingGroup aBaselineGroup) const;
   1900 
   1901 public:
   1902  /**
   1903   * Get the suitable baseline sharing group for this element, assuming line
   1904   * layout.
   1905   */
   1906  virtual BaselineSharingGroup GetDefaultBaselineSharingGroup() const {
   1907    return BaselineSharingGroup::First;
   1908  }
   1909 
   1910  ///////////////////////////////////////////////////////////////////////////////
   1911  // Internal implementation for the approximate frame visibility API.
   1912  ///////////////////////////////////////////////////////////////////////////////
   1913 
   1914  /**
   1915   * We track the approximate visibility of frames using a counter; if it's
   1916   * non-zero, then the frame is considered visible. Using a counter allows us
   1917   * to account for situations where the frame may be visible in more than one
   1918   * place (for example, via -moz-element), and it simplifies the
   1919   * implementation of our approximate visibility tracking algorithms.
   1920   *
   1921   * @param aNonvisibleAction A requested action if the frame has become
   1922   *                          nonvisible. If Nothing(), no action is
   1923   *                          requested. If DISCARD_IMAGES is specified, the
   1924   *                          frame is requested to ask any images it's
   1925   *                          associated with to discard their surfaces if
   1926   *                          possible.
   1927   */
   1928  void DecApproximateVisibleCount(
   1929      const Maybe<OnNonvisible>& aNonvisibleAction = Nothing());
   1930  void IncApproximateVisibleCount();
   1931 
   1932  /**
   1933   * Get the specified child list.
   1934   *
   1935   * @param   aListID identifies the requested child list.
   1936   * @return  the child list.  If the requested list is unsupported by this
   1937   *          frame type, an empty list will be returned.
   1938   */
   1939  virtual const nsFrameList& GetChildList(ChildListID aListID) const;
   1940  const nsFrameList& PrincipalChildList() const {
   1941    return GetChildList(mozilla::FrameChildListID::Principal);
   1942  }
   1943 
   1944  /**
   1945   * Sub-classes should override this methods if they want to append their own
   1946   * child lists into aLists.
   1947   */
   1948  virtual void GetChildLists(nsTArray<ChildList>* aLists) const;
   1949 
   1950  /**
   1951   * Returns the child lists for this frame.
   1952   */
   1953  AutoTArray<ChildList, 4> ChildLists() const {
   1954    AutoTArray<ChildList, 4> childLists;
   1955    GetChildLists(&childLists);
   1956    return childLists;
   1957  }
   1958 
   1959  /**
   1960   * Returns the child lists for this frame, including ones belong to a child
   1961   * document.
   1962   */
   1963  AutoTArray<ChildList, 4> CrossDocChildLists();
   1964 
   1965  /**
   1966   * Child frames are linked together in a doubly-linked list
   1967   */
   1968  nsIFrame* GetNextSibling() const { return mNextSibling; }
   1969  void SetNextSibling(nsIFrame* aNextSibling) {
   1970    NS_ASSERTION(this != aNextSibling,
   1971                 "Creating a circular frame list, this is very bad.");
   1972    if (mNextSibling && mNextSibling->GetPrevSibling() == this) {
   1973      mNextSibling->mPrevSibling = nullptr;
   1974    }
   1975    mNextSibling = aNextSibling;
   1976    if (mNextSibling) {
   1977      mNextSibling->mPrevSibling = this;
   1978    }
   1979  }
   1980 
   1981  nsIFrame* GetPrevSibling() const { return mPrevSibling; }
   1982 
   1983  /**
   1984   * Builds the display lists for the content represented by this frame
   1985   * and its descendants. The background+borders of this element must
   1986   * be added first, before any other content.
   1987   *
   1988   * This should only be called by methods in nsFrame. Instead of calling this
   1989   * directly, call either BuildDisplayListForStackingContext or
   1990   * BuildDisplayListForChild.
   1991   *
   1992   * See nsDisplayList.h for more information about display lists.
   1993   */
   1994  virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
   1995                                const nsDisplayListSet& aLists) {}
   1996  /**
   1997   * Displays the caret onto the given display list builder. The caret is
   1998   * painted on top of the rest of the display list items.
   1999   */
   2000  void DisplayCaret(nsDisplayListBuilder* aBuilder, nsDisplayList* aList);
   2001 
   2002  /**
   2003   * Get the preferred caret color at the offset.
   2004   *
   2005   * @param aOffset is offset of the content.
   2006   */
   2007  virtual nscolor GetCaretColorAt(int32_t aOffset);
   2008 
   2009  bool IsThemed(nsITheme::Transparency* aTransparencyState = nullptr) const {
   2010    return IsThemed(StyleDisplay(), aTransparencyState);
   2011  }
   2012  bool IsThemed(const nsStyleDisplay* aDisp,
   2013                nsITheme::Transparency* aTransparencyState = nullptr) const {
   2014    if (!aDisp->HasAppearance()) {
   2015      return false;
   2016    }
   2017    nsIFrame* mutable_this = const_cast<nsIFrame*>(this);
   2018    nsPresContext* pc = PresContext();
   2019    nsITheme* theme = pc->Theme();
   2020    if (!theme->ThemeSupportsWidget(pc, mutable_this,
   2021                                    aDisp->EffectiveAppearance())) {
   2022      return false;
   2023    }
   2024    if (aTransparencyState) {
   2025      *aTransparencyState = theme->GetWidgetTransparency(
   2026          mutable_this, aDisp->EffectiveAppearance());
   2027    }
   2028    return true;
   2029  }
   2030 
   2031  /**
   2032   * Builds a display list for the content represented by this frame,
   2033   * treating this frame as the root of a stacking context.
   2034   * Optionally sets aCreatedContainerItem to true if we created a
   2035   * single container display item for the stacking context, and no
   2036   * other wrapping items are needed.
   2037   */
   2038  void BuildDisplayListForStackingContext(
   2039      nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
   2040      bool* aCreatedContainerItem = nullptr);
   2041 
   2042  enum class DisplayChildFlag {
   2043    ForcePseudoStackingContext,
   2044    ForceStackingContext,
   2045    Inline,
   2046  };
   2047  using DisplayChildFlags = mozilla::EnumSet<DisplayChildFlag>;
   2048 
   2049  /**
   2050   * Adjusts aDirtyRect for the child's offset, checks that the dirty rect
   2051   * actually intersects the child (or its descendants), calls BuildDisplayList
   2052   * on the child if necessary, and puts things in the right lists if the child
   2053   * is positioned.
   2054   *
   2055   * @param aFlags a set of of DisplayChildFlag values that are applicable for
   2056   * this operation.
   2057   */
   2058  void BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
   2059                                nsIFrame* aChild,
   2060                                const nsDisplayListSet& aLists,
   2061                                DisplayChildFlags aFlags = {});
   2062 
   2063  void BuildDisplayListForSimpleChild(nsDisplayListBuilder* aBuilder,
   2064                                      nsIFrame* aChild,
   2065                                      const nsDisplayListSet& aLists);
   2066 
   2067  /**
   2068   * Helper for BuildDisplayListForChild, to implement this special-case for
   2069   * grid (and flex) items from the spec:
   2070   *   The painting order of grid items is exactly the same as inline blocks,
   2071   *   except that [...], and 'z-index' values other than 'auto' create a
   2072   *   stacking context even if 'position' is 'static' (behaving exactly as if
   2073   *   'position' were 'relative'). https://drafts.csswg.org/css-grid/#z-order
   2074   *
   2075   * Flex items also have the same special-case described in
   2076   * https://drafts.csswg.org/css-flexbox/#painting
   2077   */
   2078  static DisplayChildFlags DisplayFlagsForFlexOrGridItem() {
   2079    return DisplayChildFlags{DisplayChildFlag::ForcePseudoStackingContext};
   2080  }
   2081 
   2082  bool RefusedAsyncAnimation() const {
   2083    return GetProperty(RefusedAsyncAnimationProperty());
   2084  }
   2085 
   2086  /**
   2087   * Returns true if this frame is transformed (e.g. has CSS, SVG, or custom
   2088   * transforms) or if its parent is an SVG frame that has children-only
   2089   * transforms (e.g.  an SVG viewBox attribute) or if its transform-style is
   2090   * preserve-3d or the frame has transform animations.
   2091   */
   2092  bool IsTransformed() const;
   2093 
   2094  /**
   2095   * Same as IsTransformed, except that it doesn't take SVG transforms
   2096   * into account.
   2097   */
   2098  bool IsCSSTransformed() const;
   2099 
   2100  /**
   2101   * True if this frame has any animation of transform in effect.
   2102   */
   2103  bool HasAnimationOfTransform() const;
   2104 
   2105  /**
   2106   * True if this frame has any animation of opacity in effect.
   2107   *
   2108   * EffectSet is just an optimization.
   2109   */
   2110  bool HasAnimationOfOpacity(mozilla::EffectSet* = nullptr) const;
   2111 
   2112  /**
   2113   * Returns true if the frame is translucent or the frame has opacity
   2114   * animations for the purposes of creating a stacking context.
   2115   *
   2116   * @param aStyleDisplay:  This function needs style display struct.
   2117   *
   2118   * @param aStyleEffects:  This function needs style effects struct.
   2119   *
   2120   * @param aEffectSet: This function may need to look up EffectSet property.
   2121   *   If a caller already have one, pass it in can save property look up
   2122   *   time; otherwise, just leave it as nullptr.
   2123   */
   2124  bool HasOpacity(const nsStyleDisplay* aStyleDisplay,
   2125                  const nsStyleEffects* aStyleEffects,
   2126                  mozilla::EffectSet* aEffectSet = nullptr) const {
   2127    return HasOpacityInternal(1.0f, aStyleDisplay, aStyleEffects, aEffectSet);
   2128  }
   2129  /**
   2130   * Returns true if the frame is translucent for display purposes.
   2131   *
   2132   * @param aStyleDisplay:  This function needs style display struct.
   2133   *
   2134   * @param aStyleEffects:  This function needs style effects struct.
   2135   *
   2136   * @param aEffectSet: This function may need to look up EffectSet property.
   2137   *   If a caller already have one, pass it in can save property look up
   2138   *   time; otherwise, just leave it as nullptr.
   2139   */
   2140  bool HasVisualOpacity(const nsStyleDisplay* aStyleDisplay,
   2141                        const nsStyleEffects* aStyleEffects,
   2142                        mozilla::EffectSet* aEffectSet = nullptr) const {
   2143    // Treat an opacity value of 0.99 and above as opaque.  This is an
   2144    // optimization aimed at Web content which use opacity:0.99 as a hint for
   2145    // creating a stacking context only.
   2146    return HasOpacityInternal(0.99f, aStyleDisplay, aStyleEffects, aEffectSet);
   2147  }
   2148 
   2149  /**
   2150   * Returns a matrix (in pixels) for the current frame. The matrix should be
   2151   * relative to the current frame's coordinate space.
   2152   *
   2153   * @param aFrame The frame to compute the transform for.
   2154   * @param aAppUnitsPerPixel The number of app units per graphics unit.
   2155   */
   2156  using ComputeTransformFunction = Matrix4x4 (*)(const nsIFrame*,
   2157                                                 float aAppUnitsPerPixel);
   2158  /** Returns the transform getter of this frame, if any. */
   2159  virtual ComputeTransformFunction GetTransformGetter() const {
   2160    return nullptr;
   2161  }
   2162 
   2163  /**
   2164   * Returns true if this frame's parent is an SVG frame that has children-only
   2165   * transforms (e.g. an SVG viewBox attribute).
   2166   * If aFromParentTransforms is non-null, then aFromParentTransforms will be
   2167   * set to these transforms.
   2168   */
   2169  bool GetParentSVGTransforms(Matrix* aFromParentTransforms = nullptr) const {
   2170    if (!HasAnyStateBits(NS_FRAME_SVG_LAYOUT)) {
   2171      return false;
   2172    }
   2173    return DoGetParentSVGTransforms(aFromParentTransforms);
   2174  }
   2175  virtual bool DoGetParentSVGTransforms(Matrix* = nullptr) const;
   2176 
   2177  /**
   2178   * Returns whether this frame will attempt to extend the 3d transforms of its
   2179   * children. This requires transform-style: preserve-3d, as well as no
   2180   * clipping or svg effects.
   2181   *
   2182   * @param aStyleDisplay:  If the caller has this->StyleDisplay(), providing
   2183   *   it here will improve performance.
   2184   *
   2185   * @param aStyleEffects:  If the caller has this->StyleEffects(), providing
   2186   *   it here will improve performance.
   2187   *
   2188   * @param aEffectSetForOpacity: This function may need to look up the
   2189   *   EffectSet for opacity animations on this frame.
   2190   *   If the caller already has looked up this EffectSet, it may pass it in to
   2191   *   save an extra property lookup.
   2192   */
   2193  bool Extend3DContext(
   2194      const nsStyleDisplay* aStyleDisplay, const nsStyleEffects* aStyleEffects,
   2195      mozilla::EffectSet* aEffectSetForOpacity = nullptr) const;
   2196  bool Extend3DContext(
   2197      mozilla::EffectSet* aEffectSetForOpacity = nullptr) const {
   2198    return Extend3DContext(StyleDisplay(), StyleEffects(),
   2199                           aEffectSetForOpacity);
   2200  }
   2201 
   2202  /**
   2203   * Returns whether this frame has a parent that Extend3DContext() and has
   2204   * its own transform (or hidden backface) to be combined with the parent's
   2205   * transform.
   2206   */
   2207  bool Combines3DTransformWithAncestors() const;
   2208 
   2209  /**
   2210   * Returns whether this frame has a hidden backface and has a parent that
   2211   * Extend3DContext(). This is useful because in some cases the hidden
   2212   * backface can safely be ignored if it could not be visible anyway.
   2213   *
   2214   */
   2215  bool In3DContextAndBackfaceIsHidden() const;
   2216 
   2217  bool IsPreserve3DLeaf(const nsStyleDisplay* aStyleDisplay,
   2218                        mozilla::EffectSet* aEffectSet = nullptr) const {
   2219    return Combines3DTransformWithAncestors() &&
   2220           !Extend3DContext(aStyleDisplay, StyleEffects(), aEffectSet);
   2221  }
   2222  bool IsPreserve3DLeaf(mozilla::EffectSet* aEffectSet = nullptr) const {
   2223    return IsPreserve3DLeaf(StyleDisplay(), aEffectSet);
   2224  }
   2225 
   2226  bool HasPerspective() const;
   2227 
   2228  bool ChildrenHavePerspective(const nsStyleDisplay* aStyleDisplay) const;
   2229  bool ChildrenHavePerspective() const {
   2230    return ChildrenHavePerspective(StyleDisplay());
   2231  }
   2232 
   2233  /**
   2234   * Includes the overflow area of all descendants that participate in the
   2235   * current 3d context into aOverflowAreas.
   2236   */
   2237  void ComputePreserve3DChildrenOverflow(
   2238      mozilla::OverflowAreas& aOverflowAreas);
   2239 
   2240  void RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame);
   2241 
   2242  /**
   2243   * Returns whether z-index applies to this frame.
   2244   */
   2245  bool ZIndexApplies() const;
   2246 
   2247  /**
   2248   * Returns the computed z-index for this frame, returning Nothing() for
   2249   * z-index: auto, and for frames that don't support z-index.
   2250   */
   2251  Maybe<int32_t> ZIndex() const;
   2252 
   2253  /**
   2254   * Returns whether this frame is the anchor of some ancestor scroll frame. As
   2255   * this frame is moved, the scroll frame will apply adjustments to keep this
   2256   * scroll frame in the same relative position.
   2257   *
   2258   * aOutContainer will optionally be set to the scroll anchor container for
   2259   * this frame if this frame is an anchor.
   2260   */
   2261  bool IsScrollAnchor(
   2262      mozilla::layout::ScrollAnchorContainer** aOutContainer = nullptr);
   2263 
   2264  /**
   2265   * Returns whether this frame is the anchor of some ancestor scroll frame, or
   2266   * has a descendant which is the scroll anchor.
   2267   */
   2268  bool IsInScrollAnchorChain() const;
   2269  void SetInScrollAnchorChain(bool aInChain);
   2270 
   2271  /**
   2272   * Returns the number of ancestors between this and the root of our frame tree
   2273   */
   2274  uint32_t GetDepthInFrameTree() const;
   2275 
   2276  /**
   2277   * Event handling of GUI events.
   2278   *
   2279   * @param aEvent event structure describing the type of event and rge widget
   2280   * where the event originated.
   2281   *
   2282   * @param aEventStatus a return value indicating whether the event was
   2283   * handled and whether default processing should be done
   2284   *
   2285   * XXX From a frame's perspective it's unclear what the effect of the event
   2286   * status is. Does it cause the event to continue propagating through the
   2287   * frame hierarchy or is it just returned to the widgets?
   2288   *
   2289   * @see     WidgetGUIEvent
   2290   * @see     nsEventStatus
   2291   */
   2292  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   2293  virtual nsresult HandleEvent(nsPresContext* aPresContext,
   2294                               mozilla::WidgetGUIEvent* aEvent,
   2295                               nsEventStatus* aEventStatus);
   2296 
   2297  /**
   2298   * Search for selectable content at point and attempt to select
   2299   * based on the start and end selection behaviours.
   2300   *
   2301   * @param aPoint Point at which selection will occur. Coordinates
   2302   * should be relative to this frame.
   2303   * @param aBeginAmountType, aEndAmountType Selection behavior, see
   2304   * nsIFrame for definitions.
   2305   * @param aSelectFlags Selection flags defined in nsIFrame.h.
   2306   * @return success or failure at finding suitable content to select.
   2307   */
   2308  MOZ_CAN_RUN_SCRIPT nsresult
   2309  SelectByTypeAtPoint(const nsPoint& aPoint, nsSelectionAmount aBeginAmountType,
   2310                      nsSelectionAmount aEndAmountType, uint32_t aSelectFlags);
   2311 
   2312  MOZ_CAN_RUN_SCRIPT nsresult PeekBackwardAndForwardForSelection(
   2313      nsSelectionAmount aAmountBack, nsSelectionAmount aAmountForward,
   2314      int32_t aStartPos, bool aJumpLines, uint32_t aSelectFlags);
   2315 
   2316  enum { SELECT_ACCUMULATE = 0x01 };
   2317 
   2318 protected:
   2319  // Fire DOM event. If no aContent argument use frame's mContent.
   2320  void FireDOMEvent(const nsAString& aDOMEventName,
   2321                    nsIContent* aContent = nullptr);
   2322 
   2323  // Selection Methods
   2324 
   2325  MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD
   2326  HandlePress(nsPresContext* aPresContext, mozilla::WidgetGUIEvent* aEvent,
   2327              nsEventStatus* aEventStatus);
   2328 
   2329  /**
   2330   * MoveCaretToEventPoint() moves caret at the point of aMouseEvent.
   2331   *
   2332   * @param aPresContext        Must not be nullptr.
   2333   * @param aMouseEvent         Must not be nullptr, the message must be
   2334   *                            eMouseDown and its button must be primary or
   2335   *                            middle button.
   2336   * @param aEventStatus        [out] Must not be nullptr.  This method ignores
   2337   *                            its initial value, but callees may refer it.
   2338   */
   2339  MOZ_CAN_RUN_SCRIPT nsresult MoveCaretToEventPoint(
   2340      nsPresContext* aPresContext, mozilla::WidgetMouseEvent* aMouseEvent,
   2341      nsEventStatus* aEventStatus);
   2342 
   2343  /**
   2344   * Check whether aSecondaryButtonMouseEvent should or should not cause moving
   2345   * caret at event point.  This is designed only for the secondary mouse button
   2346   * event (i.e., right button event in general).
   2347   *
   2348   * @param aFrameSelection         The nsFrameSelection which should handle the
   2349   *                                caret move with.
   2350   * @param aSecondaryButtonEvent   Must be the button value is
   2351   *                                MouseButton::eSecondary.
   2352   * @param aContentAtEventPoint    The content node at the event point.
   2353   * @param aOffsetAtEventPoint     The offset in aContentAtEventPoint where
   2354   *                                aSecondaryButtonEvent clicked.
   2355   */
   2356  [[nodiscard]] bool MovingCaretToEventPointAllowedIfSecondaryButtonEvent(
   2357      const nsFrameSelection& aFrameSelection,
   2358      mozilla::WidgetMouseEvent& aSecondaryButtonEvent,
   2359      const nsIContent& aContentAtEventPoint,
   2360      int32_t aOffsetAtEventPoint) const;
   2361 
   2362  MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD HandleMultiplePress(
   2363      nsPresContext* aPresContext, mozilla::WidgetGUIEvent* aEvent,
   2364      nsEventStatus* aEventStatus, bool aControlHeld);
   2365 
   2366  /**
   2367   * @param aPresContext must be non-nullptr.
   2368   * @param aEvent must be non-nullptr.
   2369   * @param aEventStatus must be non-nullptr.
   2370   */
   2371  MOZ_CAN_RUN_SCRIPT
   2372  NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
   2373                        mozilla::WidgetGUIEvent* aEvent,
   2374                        nsEventStatus* aEventStatus);
   2375 
   2376  MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHOD
   2377  HandleRelease(nsPresContext* aPresContext, mozilla::WidgetGUIEvent* aEvent,
   2378                nsEventStatus* aEventStatus);
   2379 
   2380  // Test if we are selecting a table object:
   2381  //  Most table/cell selection requires that Ctrl (Cmd on Mac) key is down
   2382  //   during a mouse click or drag. Exception is using Shift+click when
   2383  //   already in "table/cell selection mode" to extend a block selection
   2384  //  Get the parent content node and offset of the frame
   2385  //   of the enclosing cell or table (if not inside a cell)
   2386  //  aTarget tells us what table element to select (currently only cell and
   2387  //  table supported) (enums for this are defined in nsIFrame.h)
   2388  nsresult GetDataForTableSelection(const nsFrameSelection* aFrameSelection,
   2389                                    mozilla::PresShell* aPresShell,
   2390                                    mozilla::WidgetMouseEvent* aMouseEvent,
   2391                                    nsIContent** aParentContent,
   2392                                    int32_t* aContentOffset,
   2393                                    mozilla::TableSelectionMode* aTarget);
   2394 
   2395  // Whether this frame should move the selection as a response to mouse moves /
   2396  // presses / drags.
   2397  bool ShouldHandleSelectionMovementEvents();
   2398 
   2399 public:
   2400  virtual nsIContent* GetContentForEvent(const mozilla::WidgetEvent*) const;
   2401 
   2402  // This structure keeps track of the content node and offsets associated with
   2403  // a point; there is a primary and a secondary offset associated with any
   2404  // point.  The primary and secondary offsets differ when the point is over a
   2405  // non-text object.  The primary offset is the expected position of the
   2406  // cursor calculated from a point; the secondary offset, when it is different,
   2407  // indicates that the point is in the boundaries of some selectable object.
   2408  // Note that the primary offset can be after the secondary offset; for places
   2409  // that need the beginning and end of the object, the StartOffset and
   2410  // EndOffset helpers can be used.
   2411  struct MOZ_STACK_CLASS ContentOffsets {
   2412    ContentOffsets() = default;
   2413    bool IsNull() { return !content; }
   2414    // Helpers for places that need the ends of the offsets and expect them in
   2415    // numerical order, as opposed to wanting the primary and secondary offsets
   2416    int32_t StartOffset() { return std::min(offset, secondaryOffset); }
   2417    int32_t EndOffset() { return std::max(offset, secondaryOffset); }
   2418 
   2419    nsCOMPtr<nsIContent> content;
   2420    int32_t offset = 0;
   2421    int32_t secondaryOffset = 0;
   2422    // This value indicates whether the associated content is before or after
   2423    // the offset; the most visible use is to allow the caret to know which line
   2424    // to display on.
   2425    mozilla::CaretAssociationHint associate{0};  // Before
   2426  };
   2427  enum {
   2428    IGNORE_SELECTION_STYLE = 1 << 0,
   2429    // Treat visibility:hidden frames as non-selectable
   2430    SKIP_HIDDEN = 1 << 1,
   2431    // Do not return content in native anonymous subtree (if the frame is in a
   2432    // native anonymous subtree, the method may return content in same subtree).
   2433    IGNORE_NATIVE_ANONYMOUS_SUBTREE = 1 << 2,
   2434  };
   2435  /**
   2436   * This function calculates the content offsets for selection relative to
   2437   * a point.  Note that this should generally only be callled on the event
   2438   * frame associated with an event because this function does not account
   2439   * for frame lists other than the primary one.
   2440   * @param aPoint point relative to this frame
   2441   */
   2442  ContentOffsets GetContentOffsetsFromPoint(const nsPoint& aPoint,
   2443                                            uint32_t aFlags = 0);
   2444 
   2445  virtual ContentOffsets GetContentOffsetsFromPointExternal(
   2446      const nsPoint& aPoint, uint32_t aFlags = 0) {
   2447    return GetContentOffsetsFromPoint(aPoint, aFlags);
   2448  }
   2449 
   2450  // Helper for GetContentAndOffsetsFromPoint; calculation of content offsets
   2451  // in this function assumes there is no child frame that can be targeted.
   2452  virtual ContentOffsets CalcContentOffsetsFromFramePoint(
   2453      const nsPoint& aPoint);
   2454 
   2455  /**
   2456   * Ensure that `this` gets notifed when `aImage`s underlying image request
   2457   * loads or animates.
   2458   *
   2459   * This in practice is only needed for the canvas frame and table cell
   2460   * backgrounds, which are the only cases that should paint a background that
   2461   * isn't its own. The canvas paints the background from the root element or
   2462   * body, and the table cell paints the background for its row.
   2463   *
   2464   * For regular frames, this is done in DidSetComputedStyle.
   2465   *
   2466   * NOTE: It's unclear if we even actually _need_ this for the second case, as
   2467   * invalidating the row should invalidate all the cells. For the canvas case
   2468   * this is definitely needed as it paints the background from somewhere "down"
   2469   * in the frame tree.
   2470   *
   2471   * Returns whether the image was in fact associated with the frame.
   2472   */
   2473  [[nodiscard]] bool AssociateImage(const mozilla::StyleImage&);
   2474 
   2475  /**
   2476   * This needs to be called if the above caller returned true, once the above
   2477   * caller doesn't care about getting notified anymore.
   2478   */
   2479  void DisassociateImage(const mozilla::StyleImage&);
   2480 
   2481  mozilla::StyleImageRendering UsedImageRendering() const;
   2482  mozilla::StyleTouchAction UsedTouchAction() const;
   2483 
   2484  enum class AllowCustomCursorImage {
   2485    No,
   2486    Yes,
   2487  };
   2488 
   2489  /**
   2490   * This structure holds information about a cursor. AllowCustomCursorImage
   2491   * is `No`, then no cursor image should be loaded from the style specified on
   2492   * `mStyle`, or the frame's style.
   2493   *
   2494   * The `mStyle` member is used for `<area>` elements.
   2495   */
   2496  struct MOZ_STACK_CLASS Cursor {
   2497    mozilla::StyleCursorKind mCursor = mozilla::StyleCursorKind::Auto;
   2498    AllowCustomCursorImage mAllowCustomCursor = AllowCustomCursorImage::Yes;
   2499    RefPtr<mozilla::ComputedStyle> mStyle;
   2500  };
   2501 
   2502  /**
   2503   * Get the cursor for a given frame.
   2504   */
   2505  virtual Cursor GetCursor(const nsPoint&);
   2506 
   2507  /**
   2508   * Get a point (in the frame's coordinate space) given an offset into
   2509   * the content. This point should be on the baseline of text with
   2510   * the correct horizontal offset
   2511   */
   2512  virtual nsresult GetPointFromOffset(int32_t inOffset, nsPoint* outPoint);
   2513 
   2514  /**
   2515   * Get a list of character rects in a given range.
   2516   * This is similar version of GetPointFromOffset.
   2517   */
   2518  virtual nsresult GetCharacterRectsInRange(int32_t aInOffset, int32_t aLength,
   2519                                            nsTArray<nsRect>& aRects);
   2520 
   2521  /**
   2522   * Get the child frame of this frame which contains the given
   2523   * content offset. outChildFrame may be this frame, or nullptr on return.
   2524   * outContentOffset returns the content offset relative to the start
   2525   * of the returned node. You can also pass a hint which tells the method
   2526   * to stick to the end of the first found frame or the beginning of the
   2527   * next in case the offset falls on a boundary.
   2528   */
   2529  virtual nsresult GetChildFrameContainingOffset(
   2530      int32_t inContentOffset,
   2531      bool inHint,  // false stick left
   2532      int32_t* outFrameContentOffset, nsIFrame** outChildFrame);
   2533 
   2534  /**
   2535   * Get the current frame-state value for this frame. aResult is
   2536   * filled in with the state bits.
   2537   */
   2538  nsFrameState GetStateBits() const { return mState; }
   2539 
   2540  /**
   2541   * Update the current frame-state value for this frame.
   2542   */
   2543  void AddStateBits(nsFrameState aBits) { mState |= aBits; }
   2544  void RemoveStateBits(nsFrameState aBits) { mState &= ~aBits; }
   2545  void AddOrRemoveStateBits(nsFrameState aBits, bool aVal) {
   2546    aVal ? AddStateBits(aBits) : RemoveStateBits(aBits);
   2547  }
   2548 
   2549  /**
   2550   * Checks if the current frame-state includes all of the listed bits
   2551   */
   2552  bool HasAllStateBits(nsFrameState aBits) const {
   2553    return (mState & aBits) == aBits;
   2554  }
   2555 
   2556  /**
   2557   * Checks if the current frame-state includes any of the listed bits
   2558   */
   2559  bool HasAnyStateBits(nsFrameState aBits) const { return mState & aBits; }
   2560 
   2561 private:
   2562  /**
   2563   * Called when this frame becomes primary for mContent.
   2564   */
   2565  void InitPrimaryFrame();
   2566  /**
   2567   * Called when the primary frame style changes.
   2568   *
   2569   * Kind of like DidSetComputedStyle, but the first computed style is set
   2570   * before SetPrimaryFrame, so we need this tweak.
   2571   */
   2572  void HandlePrimaryFrameStyleChange(ComputedStyle* aOldStyle);
   2573 
   2574 public:
   2575  /**
   2576   * Return true if this frame is the primary frame for mContent.
   2577   */
   2578  bool IsPrimaryFrame() const { return mIsPrimaryFrame; }
   2579 
   2580  void SetIsPrimaryFrame(bool aIsPrimary) {
   2581    if (mIsPrimaryFrame == aIsPrimary) {
   2582      return;
   2583    }
   2584    mIsPrimaryFrame = aIsPrimary;
   2585    if (aIsPrimary) {
   2586      InitPrimaryFrame();
   2587    }
   2588  }
   2589 
   2590  bool ShouldPropagateRepaintsToRoot() const;
   2591 
   2592  /**
   2593   * @return true if this frame is used as a fieldset's rendered legend.
   2594   */
   2595  bool IsRenderedLegend() const;
   2596 
   2597  /**
   2598   * This call is invoked on the primary frame for a character data content
   2599   * node, when it is changed in the content tree.
   2600   */
   2601  virtual nsresult CharacterDataChanged(const CharacterDataChangeInfo&);
   2602 
   2603  /**
   2604   * This call is invoked when the value of a content objects's attribute
   2605   * is changed.
   2606   * The first frame that maps that content is asked to deal
   2607   * with the change by doing whatever is appropriate.
   2608   *
   2609   * @param aNameSpaceID the namespace of the attribute
   2610   * @param aAttribute the atom name of the attribute
   2611   * @param aModType Whether or not the attribute was added, changed, or
   2612   * removed.
   2613   */
   2614  virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
   2615                                    AttrModType aModType);
   2616 
   2617  /**
   2618   * When the element states of mContent change, this method is invoked on the
   2619   * primary frame of that element.
   2620   *
   2621   * @param aStates the changed states
   2622   */
   2623  virtual void ElementStateChanged(mozilla::dom::ElementState aStates);
   2624 
   2625  /**
   2626   * Continuation member functions
   2627   */
   2628  virtual nsIFrame* GetPrevContinuation() const;
   2629  virtual void SetPrevContinuation(nsIFrame*);
   2630  virtual nsIFrame* GetNextContinuation() const;
   2631  virtual void SetNextContinuation(nsIFrame*);
   2632  virtual nsIFrame* FirstContinuation() const {
   2633    return const_cast<nsIFrame*>(this);
   2634  }
   2635  virtual nsIFrame* LastContinuation() const {
   2636    return const_cast<nsIFrame*>(this);
   2637  }
   2638 
   2639  /**
   2640   * GetTailContinuation gets the last non-overflow-container continuation
   2641   * in the continuation chain, i.e. where the next sibling element
   2642   * should attach).
   2643   */
   2644  nsIFrame* GetTailContinuation();
   2645 
   2646  /**
   2647   * Flow member functions
   2648   */
   2649  virtual nsIFrame* GetPrevInFlow() const;
   2650  virtual void SetPrevInFlow(nsIFrame*);
   2651 
   2652  virtual nsIFrame* GetNextInFlow() const;
   2653  virtual void SetNextInFlow(nsIFrame*);
   2654 
   2655  /**
   2656   * Return the first frame in our current flow.
   2657   */
   2658  virtual nsIFrame* FirstInFlow() const { return const_cast<nsIFrame*>(this); }
   2659 
   2660  /**
   2661   * Return the last frame in our current flow.
   2662   */
   2663  virtual nsIFrame* LastInFlow() const { return const_cast<nsIFrame*>(this); }
   2664 
   2665  /**
   2666   * Useful for line participants. Find the line container frame for this line.
   2667   */
   2668  nsIFrame* FindLineContainer() const;
   2669 
   2670  /**
   2671   * Mark any stored intrinsic inline size information as dirty (requiring
   2672   * re-calculation).  Note that this should generally not be called
   2673   * directly; PresShell::FrameNeedsReflow() will call it instead.
   2674   */
   2675  virtual void MarkIntrinsicISizesDirty();
   2676 
   2677  /**
   2678   * Make this frame and all descendants dirty (if not already).
   2679   * Exceptions: TableColGroupFrame children.
   2680   */
   2681  void MarkSubtreeDirty();
   2682 
   2683  /**
   2684   * Get the min-content intrinsic inline size of the frame.  This must be
   2685   * less than or equal to the max-content intrinsic inline size.
   2686   *
   2687   * This is *not* affected by the CSS 'min-width', 'width', and
   2688   * 'max-width' properties on this frame, but it is affected by the
   2689   * values of those properties on this frame's descendants.  (It may be
   2690   * called during computation of the values of those properties, so it
   2691   * cannot depend on any values in the nsStylePosition for this frame.)
   2692   *
   2693   * The value returned should **NOT** include the space required for
   2694   * padding and border.
   2695   *
   2696   * Note that many frames will cache the result of this function call
   2697   * unless MarkIntrinsicISizesDirty is called.
   2698   *
   2699   * It is not acceptable for a frame to mark itself dirty when this
   2700   * method is called.
   2701   *
   2702   * This method must not return a negative value.
   2703   */
   2704  nscoord GetMinISize(const mozilla::IntrinsicSizeInput& aInput) {
   2705    return IntrinsicISize(aInput, mozilla::IntrinsicISizeType::MinISize);
   2706  }
   2707 
   2708  /**
   2709   * Get the max-content intrinsic inline size of the frame.  This must be
   2710   * greater than or equal to the min-content intrinsic inline size.
   2711   *
   2712   * Otherwise, all the comments for |GetMinISize| above apply.
   2713   */
   2714  nscoord GetPrefISize(const mozilla::IntrinsicSizeInput& aInput) {
   2715    return IntrinsicISize(aInput, mozilla::IntrinsicISizeType::PrefISize);
   2716  }
   2717 
   2718  /**
   2719   * A helper to implement GetMinISize() and GetPrefISize(). A derived class
   2720   * should override this method to return its intrinsic size.
   2721   *
   2722   * All the comments for GetMinISize() and GetPrefISize() apply.
   2723   */
   2724  virtual nscoord IntrinsicISize(const mozilla::IntrinsicSizeInput& aInput,
   2725                                 mozilla::IntrinsicISizeType aType) {
   2726    return 0;
   2727  }
   2728 
   2729  /**
   2730   * |InlineIntrinsicISize| represents the intrinsic inline size information
   2731   * in inline layout.  Code that determines the intrinsic inline size of a
   2732   * region of inline layout accumulates the result into this structure.
   2733   * This pattern is needed because we need to maintain state
   2734   * information about whitespace (for both collapsing and trimming).
   2735   */
   2736  struct InlineIntrinsicISizeData {
   2737    // The line. This may be null if the inlines are not associated with
   2738    // a block or if we just don't know the line.
   2739    const LineListIterator* mLine = nullptr;
   2740 
   2741    // The line container. Private, to ensure we always use SetLineContainer
   2742    // to update it.
   2743    //
   2744    // Note that nsContainerFrame::DoInlineIntrinsicISize will clear the
   2745    // |mLine| and |mLineContainer| fields when following a next-in-flow link,
   2746    // so we must not assume these can always be dereferenced.
   2747   private:
   2748    nsIFrame* mLineContainer = nullptr;
   2749 
   2750    // Setter and getter for the lineContainer field:
   2751   public:
   2752    void SetLineContainer(nsIFrame* aLineContainer) {
   2753      mLineContainer = aLineContainer;
   2754    }
   2755    nsIFrame* LineContainer() const { return mLineContainer; }
   2756 
   2757    // The max-content intrinsic inline size for all previous lines.
   2758    nscoord mPrevLines = 0;
   2759 
   2760    // The max-content intrinsic inline size for the current line.  At a line
   2761    // break (mandatory for max-content inline size; allowed for min-content
   2762    // inline size), the caller should call |Break()|.
   2763    nscoord mCurrentLine = 0;
   2764 
   2765    // This contains the inline size of the trimmable whitespace at the end of
   2766    // |mCurrentLine|; it is zero if there is no such whitespace.
   2767    nscoord mTrailingWhitespace = 0;
   2768 
   2769    // True if initial collapsable whitespace should be skipped.  This
   2770    // should be true at the beginning of a block, after hard breaks
   2771    // and when the last text ended with whitespace.
   2772    bool mSkipWhitespace = true;
   2773 
   2774    // Floats encountered in the lines.
   2775    class FloatInfo final {
   2776     public:
   2777      FloatInfo(const nsIFrame* aFrame, nscoord aISize)
   2778          : mFrame(aFrame), mISize(aISize) {}
   2779      const nsIFrame* Frame() const { return mFrame; }
   2780      nscoord ISize() const { return mISize; }
   2781 
   2782     private:
   2783      const nsIFrame* mFrame;
   2784      nscoord mISize;
   2785    };
   2786 
   2787    nsTArray<FloatInfo> mFloats;
   2788  };
   2789 
   2790  struct InlineMinISizeData : public InlineIntrinsicISizeData {
   2791    // The default implementation for nsIFrame::AddInlineMinISize.
   2792    void DefaultAddInlineMinISize(nsIFrame* aFrame, nscoord aISize,
   2793                                  bool aAllowBreak = true);
   2794 
   2795    // We need to distinguish forced and optional breaks for cases where the
   2796    // current line total is negative. When it is, we need to ignore optional
   2797    // breaks to prevent min-content inline size from ending up bigger than
   2798    // max-content inline size.
   2799    void ForceBreak();
   2800 
   2801    // If the break here is actually taken, aHyphenWidth must be added to the
   2802    // width of the current line.
   2803    void OptionallyBreak(nscoord aHyphenWidth = 0);
   2804 
   2805    // Whether we're currently at the start of the line.  If we are, we
   2806    // can't break (for example, between the text-indent and the first
   2807    // word).
   2808    bool mAtStartOfLine = true;
   2809  };
   2810 
   2811  struct InlinePrefISizeData : public InlineIntrinsicISizeData {
   2812    /**
   2813     * Finish the current line and start a new line.
   2814     *
   2815     * @param aClearType controls whether isize of floats are considered
   2816     * and what floats are kept for the next line:
   2817     *  * |None| skips handling floats, which means no floats are
   2818     *    removed, and isizes of floats are not considered either.
   2819     *  * |Both| takes floats into consideration when computing isize
   2820     *    of the current line, and removes all floats after that.
   2821     *  * |Left| and |Right| do the same as |Both| except that they only
   2822     *    remove floats on the given side, and any floats on the other
   2823     *    side that are prior to a float on the given side that has a
   2824     *    'clear' property that clears them.
   2825     */
   2826    void ForceBreak(mozilla::UsedClear aClearType = mozilla::UsedClear::Both);
   2827 
   2828    // The default implementation for nsIFrame::AddInlinePrefISize.
   2829    void DefaultAddInlinePrefISize(nscoord aISize);
   2830 
   2831    // True if the current line contains nothing other than placeholders.
   2832    bool mLineIsEmpty = true;
   2833  };
   2834 
   2835  /**
   2836   * Add the min-content intrinsic inline size of a frame in a way suitable for
   2837   * use in inline layout to an |InlineMinISizeData| object that
   2838   * represents the intrinsic inline size information of all the previous
   2839   * frames in the inline layout region.
   2840   *
   2841   * All *allowed* breakpoints within the frame determine what counts as
   2842   * a line for the |InlineMinISizeData|.  This means that
   2843   * |aData->mTrailingWhitespace| will always be zero (unlike for
   2844   * AddInlinePrefISize).
   2845   *
   2846   * All the comments for |GetMinISize| apply, except that this function
   2847   * is responsible for adding padding, border, and margin and for
   2848   * considering the effects of 'inline-size', 'min-inline-size', and
   2849   * 'max-inline-size'.
   2850   *
   2851   * This may be called on any frame.  Frames that do not participate in
   2852   * line breaking can inherit the default implementation on nsIFrame,
   2853   * which calls |GetMinISize|.
   2854   */
   2855  virtual void AddInlineMinISize(const mozilla::IntrinsicSizeInput& aInput,
   2856                                 InlineMinISizeData* aData);
   2857 
   2858  /**
   2859   * Add the max-content intrinsic inline size of a frame in a way suitable for
   2860   * use in inline layout to an |InlinePrefISizeData| object that
   2861   * represents the intrinsic inline size information of all the previous
   2862   * frames in the inline layout region.
   2863   *
   2864   * All the comments for |AddInlineMinISize| and |GetPrefISize| apply,
   2865   * except that this fills in an |InlinePrefISizeData| structure
   2866   * based on using all *mandatory* breakpoints within the frame.
   2867   */
   2868  virtual void AddInlinePrefISize(const mozilla::IntrinsicSizeInput& aInput,
   2869                                  InlinePrefISizeData* aData);
   2870 
   2871  /**
   2872   * Intrinsic size of a frame in a single axis.
   2873   *
   2874   * This can represent either isize or bsize.
   2875   */
   2876  struct IntrinsicSizeOffsetData {
   2877    nscoord padding = 0;
   2878    nscoord border = 0;
   2879    nscoord margin = 0;
   2880    nscoord BorderPadding() const { return border + padding; };
   2881    nscoord MarginBorderPadding() const { return margin + border + padding; }
   2882  };
   2883 
   2884  /**
   2885   * Return the isize components of padding, border, and margin
   2886   * that contribute to the intrinsic width that applies to the parent.
   2887   * @param aPercentageBasis the percentage basis to use for padding/margin -
   2888   *   i.e. the Containing Block's inline-size
   2889   */
   2890  virtual IntrinsicSizeOffsetData IntrinsicISizeOffsets(
   2891      nscoord aPercentageBasis = NS_UNCONSTRAINEDSIZE);
   2892 
   2893  /**
   2894   * Return the bsize components of padding, border, and margin
   2895   * that contribute to the intrinsic width that applies to the parent.
   2896   * @param aPercentageBasis the percentage basis to use for padding/margin -
   2897   *   i.e. the Containing Block's inline-size
   2898   */
   2899  IntrinsicSizeOffsetData IntrinsicBSizeOffsets(
   2900      nscoord aPercentageBasis = NS_UNCONSTRAINEDSIZE);
   2901 
   2902  virtual mozilla::IntrinsicSize GetIntrinsicSize();
   2903 
   2904  /**
   2905   * Get the preferred aspect ratio of this frame, or a default-constructed
   2906   * AspectRatio if it has none.
   2907   *
   2908   * https://drafts.csswg.org/css-sizing-4/#preferred-aspect-ratio
   2909   */
   2910  mozilla::AspectRatio GetAspectRatio() const;
   2911 
   2912  /**
   2913   * Get the intrinsic aspect ratio of this frame, or a default-constructed
   2914   * AspectRatio if it has no intrinsic ratio.
   2915   *
   2916   * The intrinsic ratio is the ratio of the width/height of a box with an
   2917   * intrinsic size or the intrinsic aspect ratio of a scalable vector image
   2918   * without an intrinsic size. A frame class implementing a replaced element
   2919   * should override this method if it has a intrinsic ratio.
   2920   */
   2921  virtual mozilla::AspectRatio GetIntrinsicRatio() const;
   2922 
   2923  /**
   2924   * Compute the size that a frame will occupy.  Called while
   2925   * constructing the ReflowInput to be used to Reflow the frame,
   2926   * in order to fill its mComputedWidth and mComputedHeight member
   2927   * variables.
   2928   *
   2929   * Note that the reason that border and padding need to be passed
   2930   * separately is so that the 'box-sizing' property can be handled.
   2931   * Thus aMargin includes absolute positioning offsets as well.
   2932   *
   2933   * @param aWM  The writing mode to use for the returned size (need not match
   2934   *             this frame's writing mode). This is also the writing mode of
   2935   *             the passed-in LogicalSize parameters.
   2936   * @param aCBSize  The size of the element's containing block.  (Well,
   2937   *                 the BSize() component isn't really.)
   2938   * @param aAvailableISize  The available inline-size for 'auto' inline-size.
   2939   *                         This is usually the same as aCBSize.ISize(),
   2940   *                         but differs in cases such as block
   2941   *                         formatting context roots next to floats, or
   2942   *                         in some cases of float reflow in quirks
   2943   *                         mode.
   2944   * @param aMargin  The sum of the inline / block margins ***AND***
   2945   *                 absolute positioning offsets (inset-block and
   2946   *                 inset-inline) of the frame, including actual values
   2947   *                 resulting from percentages and from the
   2948   *                 "hypothetical box" for absolute positioning, but
   2949   *                 not including actual values resulting from 'auto'
   2950   *                 margins or ignored 'auto' values in absolute
   2951   *                 positioning.
   2952   * @param aBorderPadding  The sum of the frame's inline / block border-widths
   2953   *                        and padding (including actual values resulting from
   2954   *                        percentage padding values).
   2955   * @param aSizeOverride Optional override values for size properties, which
   2956   *                      this function will use internally instead of the
   2957   *                      actual property values.
   2958   * @param aFlags   Flags to further customize behavior (definitions in
   2959   *                 LayoutConstants.h).
   2960   *
   2961   * The return value includes the computed LogicalSize and AspectRatioUsage
   2962   * which indicates whether the inline/block size is affected by aspect-ratio
   2963   * or not. The BSize() of the returned LogicalSize may be
   2964   * NS_UNCONSTRAINEDSIZE, but the ISize() must not be. We need AspectRatioUsage
   2965   * during reflow because the final size may be affected by the content size
   2966   * after applying aspect-ratio.
   2967   * https://drafts.csswg.org/css-sizing-4/#aspect-ratio-minimum
   2968   *
   2969   */
   2970  enum class AspectRatioUsage : uint8_t {
   2971    None,
   2972    ToComputeISize,
   2973    ToComputeBSize,
   2974  };
   2975  struct SizeComputationResult {
   2976    mozilla::LogicalSize mLogicalSize;
   2977    AspectRatioUsage mAspectRatioUsage = AspectRatioUsage::None;
   2978  };
   2979  virtual SizeComputationResult ComputeSize(
   2980      const SizeComputationInput& aSizingInput, mozilla::WritingMode aWM,
   2981      const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
   2982      const mozilla::LogicalSize& aMargin,
   2983      const mozilla::LogicalSize& aBorderPadding,
   2984      const mozilla::StyleSizeOverrides& aSizeOverrides,
   2985      mozilla::ComputeSizeFlags aFlags);
   2986 
   2987  static nscoord ComputeBSizeValueAsPercentageBasis(
   2988      const mozilla::StyleSize& aStyleBSize,
   2989      const mozilla::StyleSize& aStyleMinBSize,
   2990      const mozilla::StyleMaxSize& aStyleMaxBSize, nscoord aCBBSize,
   2991      nscoord aContentEdgeToBoxSizingBSize);
   2992 
   2993 protected:
   2994  /**
   2995   * A helper, used by |nsIFrame::ComputeSize| (for frames that need to
   2996   * override only this part of ComputeSize), that computes the size
   2997   * that should be returned when inline-size, block-size, and
   2998   * [min|max]-[inline-size|block-size] are all 'auto' or equivalent.
   2999   *
   3000   * In general, frames that can accept any computed inline-size/block-size
   3001   * should override only ComputeAutoSize, and frames that cannot do so need to
   3002   * override ComputeSize to enforce their inline-size/block-size invariants.
   3003   *
   3004   * Implementations may optimize by returning a garbage inline-size if
   3005   * StylePosition()->ISize() is not 'auto' (or inline-size override in
   3006   * aSizeOverrides is not 'auto' if provided), and likewise for BSize(), since
   3007   * in such cases the result is guaranteed to be unused.
   3008   *
   3009   * Most of the frame are not expected to check the aSizeOverrides parameter
   3010   * apart from checking the inline size override for 'auto' if they want to
   3011   * optimize and return garbage inline-size.
   3012   */
   3013  virtual mozilla::LogicalSize ComputeAutoSize(
   3014      const SizeComputationInput& aSizingInput, mozilla::WritingMode aWM,
   3015      const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
   3016      const mozilla::LogicalSize& aMargin,
   3017      const mozilla::LogicalSize& aBorderPadding,
   3018      const mozilla::StyleSizeOverrides& aSizeOverrides,
   3019      mozilla::ComputeSizeFlags aFlags);
   3020 
   3021  /**
   3022   * A helper used by |nsIFrame::ComputeAutoSize|, computing auto sizes of
   3023   * frames that are absolutely positioned. Any class that overrides
   3024   * `ComputeAutoSize` may use this function to maintain the standard absolute
   3025   * size computation specified in [1].
   3026   *
   3027   * [1]: https://drafts.csswg.org/css-position-3/#abspos-auto-size
   3028   */
   3029  mozilla::LogicalSize ComputeAbsolutePosAutoSize(
   3030      const SizeComputationInput& aSizingInput, mozilla::WritingMode aWM,
   3031      const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
   3032      const mozilla::LogicalSize& aMargin,
   3033      const mozilla::LogicalSize& aBorderPadding,
   3034      const mozilla::StyleSizeOverrides& aSizeOverrides,
   3035      const mozilla::ComputeSizeFlags& aFlags);
   3036 
   3037  /**
   3038   * Precondition helper function to determine if
   3039   * |nsIFrame::ComputeAbsolutePosAutoSize| can be called on this frame.
   3040   */
   3041  bool IsAbsolutelyPositionedWithDefiniteContainingBlock() const;
   3042 
   3043  /**
   3044   * Utility function for ComputeAutoSize implementations.  Return
   3045   * max(GetMinISize(), min(aISizeInCB, GetPrefISize()))
   3046   */
   3047  nscoord ShrinkISizeToFit(const mozilla::IntrinsicSizeInput& aInput,
   3048                           nscoord aISizeInCB,
   3049                           mozilla::ComputeSizeFlags aFlags);
   3050 
   3051  /**
   3052   * A helper for derived classes to implement min-content & max-content
   3053   * intrinsic inline size in terms of AddInlineMinISize() and
   3054   * AddInlinePrefISize().
   3055   */
   3056  nscoord IntrinsicISizeFromInline(const mozilla::IntrinsicSizeInput& aInput,
   3057                                   mozilla::IntrinsicISizeType aType);
   3058 
   3059 public:
   3060  /**
   3061   * Compute a tight bounding rectangle for the frame. This is a rectangle
   3062   * that encloses the pixels that are actually drawn. We're allowed to be
   3063   * conservative and currently we don't try very hard. The rectangle is
   3064   * in appunits and relative to the origin of this frame.
   3065   *
   3066   * This probably only needs to include frame bounds, glyph bounds, and
   3067   * text decorations, but today it sometimes includes other things that
   3068   * contribute to ink overflow.
   3069   *
   3070   * @param aDrawTarget a draw target that can be used if we need
   3071   * to do measurement
   3072   */
   3073  virtual nsRect ComputeTightBounds(DrawTarget* aDrawTarget) const;
   3074 
   3075  /**
   3076   * This function is similar to GetPrefISize and ComputeTightBounds: it
   3077   * computes the left and right coordinates of a preferred tight bounding
   3078   * rectangle for the frame. This is a rectangle that would enclose the pixels
   3079   * that are drawn if we lay out the element without taking any optional line
   3080   * breaks. The rectangle is in appunits and relative to the origin of this
   3081   * frame. Currently, this function is only implemented for nsBlockFrame and
   3082   * nsTextFrame and is used to determine intrinsic widths of MathML token
   3083   * elements.
   3084 
   3085   * @param aContext a rendering context that can be used if we need
   3086   * to do measurement
   3087   * @param aX      computed left coordinate of the tight bounding rectangle
   3088   * @param aXMost  computed intrinsic width of the tight bounding rectangle
   3089   *
   3090   */
   3091  virtual nsresult GetPrefWidthTightBounds(gfxContext* aContext, nscoord* aX,
   3092                                           nscoord* aXMost);
   3093 
   3094  /**
   3095   * The frame is given an available size and asked for its desired
   3096   * size.  This is the frame's opportunity to reflow its children.
   3097   *
   3098   * If the frame has the NS_FRAME_IS_DIRTY bit set then it is
   3099   * responsible for completely reflowing itself and all of its
   3100   * descendants.
   3101   *
   3102   * Otherwise, if the frame has the NS_FRAME_HAS_DIRTY_CHILDREN bit
   3103   * set, then it is responsible for reflowing at least those
   3104   * children that have NS_FRAME_HAS_DIRTY_CHILDREN or NS_FRAME_IS_DIRTY
   3105   * set.
   3106   *
   3107   * If a difference in available size from the previous reflow causes
   3108   * the frame's size to change, it should reflow descendants as needed.
   3109   *
   3110   * Calculates the size of this frame after reflowing (calling Reflow on, and
   3111   * updating the size and position of) its children, as necessary.  The
   3112   * calculated size is returned to the caller via the ReflowOutput
   3113   * outparam.  (The caller is responsible for setting the actual size and
   3114   * position of this frame.)
   3115   *
   3116   * A frame's children must _all_ be reflowed if the frame is dirty (the
   3117   * NS_FRAME_IS_DIRTY bit is set on it).  Otherwise, individual children
   3118   * must be reflowed if they are dirty or have the NS_FRAME_HAS_DIRTY_CHILDREN
   3119   * bit set on them.  Otherwise, whether children need to be reflowed depends
   3120   * on the frame's type (it's up to individual Reflow methods), and on what
   3121   * has changed.  For example, a change in the width of the frame may require
   3122   * all of its children to be reflowed (even those without dirty bits set on
   3123   * them), whereas a change in its height might not.
   3124   * (ReflowInput::ShouldReflowAllKids may be helpful in deciding whether
   3125   * to reflow all the children, but for some frame types it might result in
   3126   * over-reflow.)
   3127   *
   3128   * Note: if it's only the overflow rect(s) of a frame that need to be
   3129   * updated, then UpdateOverflow should be called instead of Reflow.
   3130   *
   3131   * @param aReflowOutput <i>out</i> parameter where you should return the
   3132   *          desired size and ascent/descent info. You should include any
   3133   *          space you want for border/padding in the desired size you return.
   3134   *
   3135   *          It's okay to return a desired size that exceeds the avail
   3136   *          size if that's the smallest you can be, i.e. it's your
   3137   *          minimum size.
   3138   *
   3139   *          For an incremental reflow you are responsible for invalidating
   3140   *          any area within your frame that needs repainting (including
   3141   *          borders). If your new desired size is different than your current
   3142   *          size, then your parent frame is responsible for making sure that
   3143   *          the difference between the two rects is repainted
   3144   *
   3145   * @param aReflowInput information about your reflow including the reason
   3146   *          for the reflow and the available space in which to lay out. Each
   3147   *          dimension of the available space can either be constrained or
   3148   *          unconstrained (a value of NS_UNCONSTRAINEDSIZE).
   3149   *
   3150   *          Note that the available space can be negative. In this case you
   3151   *          still must return an accurate desired size. If you're a container
   3152   *          you must <b>always</b> reflow at least one frame regardless of the
   3153   *          available space
   3154   *
   3155   * @param aStatus a return value indicating whether the frame is complete
   3156   *          and whether the next-in-flow is dirty and needs to be reflowed
   3157   */
   3158  virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aReflowOutput,
   3159                      const ReflowInput& aReflowInput, nsReflowStatus& aStatus);
   3160 
   3161  // Option flags for ReflowChild(), FinishReflowChild()
   3162  enum class ReflowChildFlags : uint32_t {
   3163    Default = 0,
   3164 
   3165    // Don't move the frame.
   3166    NoMoveFrame = (1 << 0),
   3167 
   3168    // Only applies to ReflowChild; if true, don't delete the next-in-flow, even
   3169    // if the reflow is fully complete.
   3170    NoDeleteNextInFlowChild = 1 << 1,
   3171 
   3172    // Only applies to FinishReflowChild.  Tell it to call
   3173    // ApplyRelativePositioning.
   3174    ApplyRelativePositioning = 1 << 2,
   3175  };
   3176 
   3177  /**
   3178   * Post-reflow hook. After a frame is reflowed this method will be called
   3179   * informing the frame that this reflow process is complete, and telling the
   3180   * frame the status returned by the Reflow member function.
   3181   *
   3182   * This call may be invoked many times, while NS_FRAME_IN_REFLOW is set,
   3183   * before it is finally called once with a NS_FRAME_REFLOW_COMPLETE value.
   3184   * When called with a NS_FRAME_REFLOW_COMPLETE value the NS_FRAME_IN_REFLOW
   3185   * bit in the frame state will be cleared.
   3186   *
   3187   * XXX This doesn't make sense. If the frame is reflowed but not complete,
   3188   * then the status should have IsIncomplete() equal to true.
   3189   * XXX Don't we want the semantics to dictate that we only call this once for
   3190   * a given reflow?
   3191   */
   3192  virtual void DidReflow(nsPresContext* aPresContext,
   3193                         const ReflowInput* aReflowInput);
   3194 
   3195  /**
   3196   * Updates the overflow areas of the frame. This can be called if an
   3197   * overflow area of the frame's children has changed without reflowing.
   3198   * @return true if either of the overflow areas for this frame have changed.
   3199   */
   3200  bool UpdateOverflow();
   3201 
   3202  /**
   3203   * Computes any overflow area created by the frame itself (outside of the
   3204   * frame bounds) and includes it into aOverflowAreas.
   3205   *
   3206   * Returns false if updating overflow isn't supported for this frame.
   3207   * If the frame requires a reflow instead, then it is responsible
   3208   * for scheduling one.
   3209   */
   3210  virtual bool ComputeCustomOverflow(mozilla::OverflowAreas& aOverflowAreas);
   3211 
   3212  /**
   3213   * Computes any overflow area created by children of this frame and
   3214   * includes it into aOverflowAreas. If aAsIfScrolled is true, then it behaves
   3215   * as if we were the scrolled content frame.
   3216   */
   3217  virtual void UnionChildOverflow(mozilla::OverflowAreas& aOverflowAreas,
   3218                                  bool aAsIfScrolled = false);
   3219  /**
   3220   * Computes the clipping rectangle for the given frame based on its 'overflow'
   3221   * properties. Returns true if the clip has a border radius.
   3222   */
   3223  bool ComputeOverflowClipRectRelativeToSelf(
   3224      const mozilla::PhysicalAxes aClipAxes, nsRect& aOutRect,
   3225      nsRectCornerRadii& aOutRadii) const;
   3226 
   3227  // Returns the applicable overflow-clip-margin values relative to our
   3228  // border-box. If aAllowNegative is false, prevents us from returning margins
   3229  // that are less than zero. This is useful for overflow computation (where you
   3230  // don't want the box to shrink).
   3231  nsMargin OverflowClipMargin(mozilla::PhysicalAxes aClipAxes,
   3232                              bool aAllowNegative = true) const;
   3233 
   3234  // Returns the axes on which this frame should apply overflow clipping.
   3235  mozilla::PhysicalAxes ShouldApplyOverflowClipping(
   3236      const nsStyleDisplay* aDisp) const;
   3237 
   3238  // Returns whether this frame is a block that was supposed to be a
   3239  // scrollframe, but that was suppressed for print.
   3240  bool IsSuppressedScrollableBlockForPrint() const;
   3241 
   3242  /**
   3243   * Helper method used by block reflow to identify runs of text so
   3244   * that proper word-breaking can be done.
   3245   *
   3246   * @return
   3247   *    true if we can continue a "text run" through the frame. A
   3248   *    text run is text that should be treated contiguously for line
   3249   *    and word breaking.
   3250   */
   3251  virtual bool CanContinueTextRun() const;
   3252 
   3253  /**
   3254   * Computes an approximation of the rendered text of the frame and its
   3255   * continuations. Returns nothing for non-text frames.
   3256   * The appended text will often not contain all the whitespace from source,
   3257   * depending on CSS white-space processing.
   3258   * if aEndOffset goes past end, use the text up to the string's end.
   3259   * Call this on the primary frame for a text node.
   3260   * aStartOffset and aEndOffset can be content offsets or offsets in the
   3261   * rendered text, depending on aOffsetType.
   3262   * Returns a string, as well as offsets identifying the start of the text
   3263   * within the rendered text for the whole node, and within the text content
   3264   * of the node.
   3265   */
   3266  struct RenderedText {
   3267    nsAutoString mString;
   3268    uint32_t mOffsetWithinNodeRenderedText;
   3269    int32_t mOffsetWithinNodeText;
   3270    RenderedText()
   3271        : mOffsetWithinNodeRenderedText(0), mOffsetWithinNodeText(0) {}
   3272  };
   3273  enum class TextOffsetType {
   3274    // Passed-in start and end offsets are within the content text.
   3275    OffsetsInContentText,
   3276    // Passed-in start and end offsets are within the rendered text.
   3277    OffsetsInRenderedText,
   3278  };
   3279  enum class TrailingWhitespace {
   3280    Trim,
   3281    // Spaces preceding a caret at the end of a line should not be trimmed
   3282    DontTrim,
   3283  };
   3284  virtual RenderedText GetRenderedText(
   3285      uint32_t aStartOffset = 0, uint32_t aEndOffset = UINT32_MAX,
   3286      TextOffsetType aOffsetType = TextOffsetType::OffsetsInContentText,
   3287      TrailingWhitespace aTrimTrailingWhitespace = TrailingWhitespace::Trim) {
   3288    return RenderedText();
   3289  }
   3290 
   3291  /**
   3292   * Returns true if the frame contains any non-collapsed characters.
   3293   * This method is only available for text frames, and it will return false
   3294   * for all other frame types.
   3295   */
   3296  virtual bool HasAnyNoncollapsedCharacters() { return false; }
   3297 
   3298  /**
   3299   * Returns true if events of the given type targeted at this frame
   3300   * should only be dispatched to the system group.
   3301   */
   3302  virtual bool OnlySystemGroupDispatch(mozilla::EventMessage aMessage) const {
   3303    return false;
   3304  }
   3305 
   3306  template <typename SizeOrMaxSize>
   3307  static inline bool IsIntrinsicKeyword(const SizeOrMaxSize& aSize) {
   3308    // All keywords other than auto/none/-moz-available depend on intrinsic
   3309    // sizes.
   3310    return aSize.IsMaxContent() || aSize.IsMinContent() ||
   3311           aSize.IsFitContent() || aSize.IsFitContentFunction();
   3312  }
   3313 
   3314  // Returns true iff this frame's computed block-size property is one of the
   3315  // intrinsic-sizing keywords.
   3316  bool HasIntrinsicKeywordForBSize() const {
   3317    const auto bSize = StylePosition()->BSize(
   3318        GetWritingMode(), AnchorPosResolutionParams::From(this));
   3319    return IsIntrinsicKeyword(*bSize);
   3320  }
   3321 
   3322 public:
   3323  // Gets the widget owned by this frame.
   3324  nsIWidget* GetOwnWidget() const;
   3325 
   3326  /**
   3327   * Get the offset between the coordinate systems of |this| and aOther.
   3328   * Adding the return value to a point in the coordinate system of |this|
   3329   * will transform the point to the coordinate system of aOther.
   3330   *
   3331   * aOther must be non-null.
   3332   *
   3333   * This function is fastest when aOther is an ancestor of |this|.
   3334   *
   3335   * This function _DOES NOT_ work across document boundaries.
   3336   * Use this function only when |this| and aOther are in the same document.
   3337   *
   3338   * NOTE: this actually returns the offset from aOther to |this|, but
   3339   * that offset is added to transform _coordinates_ from |this| to
   3340   * aOther.
   3341   */
   3342  nsPoint GetOffsetTo(const nsIFrame* aOther) const;
   3343 
   3344  // GetOffsetTo() to the root of this document.
   3345  nsPoint GetOffsetToRootFrame() const;
   3346 
   3347  /**
   3348   * Just like GetOffsetTo, but treats all scrollframes as scrolled to
   3349   * their origin.
   3350   */
   3351  nsPoint GetOffsetToIgnoringScrolling(const nsIFrame* aOther) const;
   3352 
   3353  /**
   3354   * Get the offset between the coordinate systems of |this| and aOther
   3355   * expressed in appunits per dev pixel of |this|' document. Adding the return
   3356   * value to a point that is relative to the origin of |this| will make the
   3357   * point relative to the origin of aOther but in the appunits per dev pixel
   3358   * ratio of |this|.
   3359   *
   3360   * aOther must be non-null.
   3361   *
   3362   * This function is fastest when aOther is an ancestor of |this|.
   3363   *
   3364   * This function works across document boundaries.
   3365   *
   3366   * Because this function may cross document boundaries that have different
   3367   * app units per dev pixel ratios it needs to be used very carefully.
   3368   *
   3369   * NOTE: this actually returns the offset from aOther to |this|, but
   3370   * that offset is added to transform _coordinates_ from |this| to
   3371   * aOther.
   3372   */
   3373  nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther) const;
   3374 
   3375  /**
   3376   * Like GetOffsetToCrossDoc, but the caller can specify which appunits
   3377   * to return the result in.
   3378   */
   3379  nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther, const int32_t aAPD) const;
   3380 
   3381  /**
   3382   * Get the rect of the frame relative to the top-left corner of the
   3383   * screen in CSS pixels.
   3384   * @return the CSS pixel rect of the frame relative to the top-left
   3385   *         corner of the screen.
   3386   */
   3387  mozilla::CSSIntRect GetScreenRect() const;
   3388 
   3389  /**
   3390   * Get the screen rect of the frame in app units.
   3391   * @return the app unit rect of the frame in screen coordinates.
   3392   */
   3393  nsRect GetScreenRectInAppUnits() const;
   3394 
   3395  /**
   3396   * Returns the nearest widget containing this frame. If this frame has a
   3397   * view and the view has a widget, then this frame's widget is
   3398   * returned, otherwise this frame's geometric parent is checked
   3399   * recursively upwards.
   3400   */
   3401  nsIWidget* GetNearestWidget() const;
   3402 
   3403  /**
   3404   * Whether the frame is a subgrid right now.
   3405   */
   3406  bool IsSubgrid() const;
   3407 
   3408  /**
   3409   * Same as GetNearestWidget() above but uses an outparam to return the offset
   3410   * of this frame to the returned widget expressed in appunits of |this| (the
   3411   * widget might be in a different document with a different zoom).
   3412   */
   3413  nsIWidget* GetNearestWidget(nsPoint& aOffset) const;
   3414 
   3415  /**
   3416   * Whether the content for this frame is disabled, used for event handling.
   3417   */
   3418  bool IsContentDisabled() const;
   3419 
   3420  enum class IncludeContentVisibility {
   3421    Auto,
   3422    Hidden,
   3423  };
   3424 
   3425  constexpr static mozilla::EnumSet<IncludeContentVisibility>
   3426  IncludeAllContentVisibility() {
   3427    return {IncludeContentVisibility::Auto, IncludeContentVisibility::Hidden};
   3428  }
   3429 
   3430  /**
   3431   * Returns true if this frame's `content-visibility: auto` element is
   3432   * considered relevant content.
   3433   */
   3434  bool IsContentRelevant() const;
   3435 
   3436  /**
   3437   * Whether this frame hides its contents via the `content-visibility`
   3438   * property.
   3439   * @param aInclude specifies what kind of `content-visibility` to include.
   3440   */
   3441  bool HidesContent(const mozilla::EnumSet<IncludeContentVisibility>& =
   3442                        IncludeAllContentVisibility()) const;
   3443 
   3444  /**
   3445   * Whether this frame hides its contents via the `content-visibility`
   3446   * property, while doing layout. This might return false when `HidesContent()`
   3447   * returns true in the case that hidden content is being forced to lay out
   3448   * by position or size queries from script.
   3449   */
   3450  bool HidesContentForLayout() const;
   3451 
   3452  /**
   3453   * returns the closest ancestor with `content-visibility` property.
   3454   * @param aInclude specifies what kind of `content-visibility` to include.
   3455   */
   3456  nsIFrame* GetClosestContentVisibilityAncestor(
   3457      const mozilla::EnumSet<IncludeContentVisibility>& =
   3458          IncludeAllContentVisibility()) const;
   3459 
   3460  /**
   3461   * Returns true if this frame is entirely hidden due the `content-visibility`
   3462   * property on an ancestor.
   3463   * @param aInclude specifies what kind of `content-visibility` to include.
   3464   */
   3465  bool IsHiddenByContentVisibilityOnAnyAncestor(
   3466      const mozilla::EnumSet<IncludeContentVisibility>& =
   3467          IncludeAllContentVisibility()) const;
   3468 
   3469  /**
   3470   * @brief Returns true if the frame is hidden=until-found or in a closed
   3471   *        <details> element.
   3472   *
   3473   * The frame is considered hidden=until-found, if all parent frames are either
   3474   * visible or hidden=until-found. If a hidden=until-found element is inside a
   3475   * content-visibility:hidden element (or vice versa), this returns false.
   3476   *
   3477   * Similarly, if the frame is inside a closed details element, and it is not
   3478   * hidden, this also returns true.
   3479   */
   3480  bool IsHiddenUntilFoundOrClosedDetails() const;
   3481 
   3482  /**
   3483   * Returns true is this frame is hidden by its first unskipped in flow
   3484   * ancestor due to `content-visibility`.
   3485   */
   3486  bool IsHiddenByContentVisibilityOfInFlowParentForLayout() const;
   3487 
   3488  /**
   3489   * Returns true if this frame has a SelectionType::eNormal type selection in
   3490   * somewhere in its subtree of frames. This is used to determine content
   3491   * relevancy for `content-visibility: auto`.
   3492   */
   3493  bool HasSelectionInSubtree();
   3494 
   3495  /**
   3496   * Update the whether or not this frame is considered relevant content for the
   3497   * purposes of `content-visibility: auto` according to the rules specified in
   3498   * https://drafts.csswg.org/css-contain-2/#relevant-to-the-user.
   3499   * Returns true if the over-all relevancy changed.
   3500   */
   3501  bool UpdateIsRelevantContent(const ContentRelevancy& aRelevancyToUpdate);
   3502 
   3503  /**
   3504   * Get the "type" of the frame.
   3505   *
   3506   * @see mozilla::LayoutFrameType
   3507   */
   3508  mozilla::LayoutFrameType Type() const {
   3509    MOZ_ASSERT(uint8_t(mClass) < std::size(sLayoutFrameTypes));
   3510    return sLayoutFrameTypes[uint8_t(mClass)];
   3511  }
   3512 
   3513  /** Return this frame's class id */
   3514  ClassID GetClassID() const { return mClass; }
   3515 
   3516  /**
   3517   * Get the type flags of the frame.
   3518   *
   3519   * @see mozilla::LayoutFrameType
   3520   */
   3521  ClassFlags GetClassFlags() const {
   3522    MOZ_ASSERT(uint8_t(mClass) < std::size(sLayoutFrameClassFlags));
   3523    return sLayoutFrameClassFlags[uint8_t(mClass)];
   3524  }
   3525 
   3526  bool HasAnyClassFlag(ClassFlags aFlag) const {
   3527    return bool(GetClassFlags() & aFlag);
   3528  }
   3529 
   3530  /**
   3531   * Is this a leaf frame?  Frames that want the frame constructor to be able to
   3532   * construct kids for them should return false, all others should return true.
   3533   *
   3534   * Note that returning true here does not mean that the frame _can't_ have
   3535   * kids. It could still have kids created via nsIAnonymousContentCreator.
   3536   *
   3537   * Returning true indicates that "normal" (non-anonymous, CSS generated
   3538   * content, etc) children should not be constructed.
   3539   */
   3540  bool IsLeaf() const {
   3541    auto bits = GetClassFlags();
   3542    if (MOZ_UNLIKELY(bits & ClassFlags::LeafDynamic)) {
   3543      return IsLeafDynamic();
   3544    }
   3545    return bool(bits & ClassFlags::Leaf);
   3546  }
   3547  virtual bool IsLeafDynamic() const { return false; }
   3548 
   3549 #define CLASS_FLAG_METHOD(name_, flag_) \
   3550  bool name_() const { return HasAnyClassFlag(ClassFlags::flag_); }
   3551 #define CLASS_FLAG_METHOD0(name_) CLASS_FLAG_METHOD(name_, name_)
   3552 
   3553  CLASS_FLAG_METHOD(IsMathMLFrame, MathML);
   3554  CLASS_FLAG_METHOD(IsSVGFrame, SVG);
   3555  CLASS_FLAG_METHOD(IsSVGContainerFrame, SVGContainer);
   3556  CLASS_FLAG_METHOD(IsBidiInlineContainer, BidiInlineContainer);
   3557  CLASS_FLAG_METHOD(IsLineParticipant, LineParticipant);
   3558  CLASS_FLAG_METHOD(HasReplacedSizing, ReplacedSizing);
   3559  CLASS_FLAG_METHOD(IsTablePart, TablePart);
   3560  CLASS_FLAG_METHOD0(CanContainOverflowContainers)
   3561  CLASS_FLAG_METHOD0(SupportsCSSTransforms);
   3562  CLASS_FLAG_METHOD0(SupportsContainLayoutAndPaint)
   3563  CLASS_FLAG_METHOD0(SupportsAspectRatio)
   3564  CLASS_FLAG_METHOD(IsSVGRenderingObserverContainer,
   3565                    SVGRenderingObserverContainer);
   3566 
   3567 #undef CLASS_FLAG_METHOD
   3568 #undef CLASS_FLAG_METHOD0
   3569 
   3570 #ifdef __GNUC__
   3571 #  pragma GCC diagnostic push
   3572 #  pragma GCC diagnostic ignored "-Wtype-limits"
   3573 #endif
   3574 #ifdef __clang__
   3575 #  pragma clang diagnostic push
   3576 #  pragma clang diagnostic ignored "-Wunknown-pragmas"
   3577 #  pragma clang diagnostic ignored "-Wtautological-unsigned-zero-compare"
   3578 #endif
   3579 
   3580 #define FRAME_TYPE(name_, first_class_, last_class_)                 \
   3581  bool Is##name_##Frame() const {                                    \
   3582    return uint8_t(mClass) >= uint8_t(ClassID::first_class_##_id) && \
   3583           uint8_t(mClass) <= uint8_t(ClassID::last_class_##_id);    \
   3584  }
   3585 #include "mozilla/FrameTypeList.h"
   3586 #undef FRAME_TYPE
   3587 
   3588 #ifdef __GNUC__
   3589 #  pragma GCC diagnostic pop
   3590 #endif
   3591 #ifdef __clang__
   3592 #  pragma clang diagnostic pop
   3593 #endif
   3594 
   3595  bool IsReplaced() const;
   3596 
   3597  /**
   3598   * Returns a transformation matrix that converts points in this frame's
   3599   * coordinate space to points in some ancestor frame's coordinate space.
   3600   * The frame decides which ancestor it will use as a reference point.
   3601   * If this frame has no ancestor, aOutAncestor will be set to null.
   3602   *
   3603   * @param aViewportType specifies whether the starting point is layout
   3604   *   or visual coordinates
   3605   * @param aStopAtAncestor don't look further than aStopAtAncestor. If null,
   3606   *   all ancestors (including across documents) will be traversed.
   3607   * @param aOutAncestor [out] The ancestor frame the frame has chosen. If this
   3608   *   frame has no ancestor, *aOutAncestor will be set to null. If this frame
   3609   *   IsTransformed(), then *aOutAncestor will be the parent frame.
   3610   * @return A Matrix4x4 that converts points in the coordinate space
   3611   *   RelativeTo{this, aViewportType} into points in aOutAncestor's
   3612   *   coordinate space.
   3613   */
   3614  enum {
   3615    IN_CSS_UNITS = 1 << 0,
   3616    STOP_AT_STACKING_CONTEXT_AND_DISPLAY_PORT = 1 << 1
   3617  };
   3618  Matrix4x4Flagged GetTransformMatrix(mozilla::ViewportType aViewportType,
   3619                                      mozilla::RelativeTo aStopAtAncestor,
   3620                                      nsIFrame** aOutAncestor,
   3621                                      uint32_t aFlags = 0) const;
   3622 
   3623  /**
   3624   * Return true if this frame's preferred size property or max size property
   3625   * contains a percentage value that should be resolved against zero when
   3626   * calculating its min-content contribution in the corresponding axis.
   3627   *
   3628   * This is a special case for webcompat required by CSS Sizing 3 §5.2.1c
   3629   * https://drafts.csswg.org/css-sizing-3/#replaced-percentage-min-contribution,
   3630   * and applies only to some replaced elements and form control elements. See
   3631   * CSS Sizing 3 §5.2.2 for the list of elements this rule applies to.
   3632   * https://drafts.csswg.org/css-sizing-3/#min-content-zero
   3633   *
   3634   * Bug 1463700: some callers may not match the spec by resolving the entire
   3635   * preferred size property or max size property against zero.
   3636   */
   3637  bool IsPercentageResolvedAgainstZero(
   3638      const mozilla::StyleSize& aStyleSize,
   3639      const mozilla::StyleMaxSize& aStyleMaxSize) const;
   3640 
   3641  // Type of preferred size/min size/max size.
   3642  enum class SizeProperty { Size, MinSize, MaxSize };
   3643  /**
   3644   * This is simliar to the above method but accepts LengthPercentage. Return
   3645   * true if the frame's preferred size property or max size property contains
   3646   * a percentage value that should be resolved against zero. For min size, it
   3647   * always returns true.
   3648   */
   3649  bool IsPercentageResolvedAgainstZero(const mozilla::LengthPercentage& aSize,
   3650                                       SizeProperty aProperty) const;
   3651 
   3652  /**
   3653   * Returns true if the frame is a block wrapper.
   3654   */
   3655  bool IsBlockWrapper() const;
   3656 
   3657  /**
   3658   * Returns true if the frame is an instance of nsBlockFrame or one of its
   3659   * subclasses.
   3660   */
   3661  bool IsBlockFrameOrSubclass() const;
   3662 
   3663  /**
   3664   * Returns true if the frame is an instance of nsImageFrame or one of its
   3665   * subclasses.
   3666   */
   3667  bool IsImageFrameOrSubclass() const;
   3668 
   3669  /**
   3670   * Returns true if the frame is an instance of ScrollContainerFrame or one of
   3671   * its subclasses.
   3672   */
   3673  bool IsScrollContainerOrSubclass() const;
   3674 
   3675  /**
   3676   * Get this frame's CSS containing block.
   3677   *
   3678   * The algorithm is defined in
   3679   * http://www.w3.org/TR/CSS2/visudet.html#containing-block-details.
   3680   *
   3681   * NOTE: This is guaranteed to return a non-null pointer when invoked on any
   3682   * frame other than the root frame.
   3683   *
   3684   * Requires SKIP_SCROLLED_FRAME to get behaviour matching the spec, otherwise
   3685   * it can return anonymous inner scrolled frames. Bug 1204044 is filed for
   3686   * investigating whether any of the callers actually require the default
   3687   * behaviour.
   3688   */
   3689  enum {
   3690    // If the containing block is an anonymous scrolled frame, then skip over
   3691    // this and return the outer scroll frame.
   3692    SKIP_SCROLLED_FRAME = 0x01
   3693  };
   3694  nsIFrame* GetContainingBlock(uint32_t aFlags,
   3695                               const nsStyleDisplay* aStyleDisplay) const;
   3696  nsIFrame* GetContainingBlock(uint32_t aFlags = 0) const {
   3697    return GetContainingBlock(aFlags, StyleDisplay());
   3698  }
   3699 
   3700  /**
   3701   * If this frame can be a block container, i.e. whether it can serve as a
   3702   * containing block for its descendants. See also GetNearestBlockContainer()
   3703   * and GetContainingBlock().
   3704   */
   3705  bool IsBlockContainer() const;
   3706 
   3707  /**
   3708   * Is this frame a containing block for floating elements?
   3709   * Note that very few frames are, so default to false.
   3710   */
   3711  virtual bool IsFloatContainingBlock() const { return false; }
   3712 
   3713  /**
   3714   * Marks all display items created by this frame as needing a repaint,
   3715   * and calls SchedulePaint() if requested and one is not already pending.
   3716   *
   3717   * This includes all display items created by this frame, including
   3718   * container types.
   3719   *
   3720   * @param aDisplayItemKey If specified, only issues an invalidate
   3721   * if this frame painted a display item of that type during the
   3722   * previous paint. SVG rendering observers are always notified.
   3723   * @param aRebuildDisplayItems If true, then adds this frame to the
   3724   * list of modified frames for display list building. Only pass false
   3725   * if you're sure that the relevant display items will be rebuilt
   3726   * already (possibly by an ancestor being in the modified list).
   3727   */
   3728  virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0,
   3729                               bool aRebuildDisplayItems = true);
   3730 
   3731  /**
   3732   * Same as InvalidateFrame(), but only mark a fixed rect as needing
   3733   * repainting.
   3734   *
   3735   * @param aRect The rect to invalidate, relative to the TopLeft of the
   3736   * frame's border box.
   3737   * @param aDisplayItemKey If specified, only issues an invalidate
   3738   * if this frame painted a display item of that type during the
   3739   * previous paint. SVG rendering observers are always notified.
   3740   * @param aRebuildDisplayItems If true, then adds this frame to the
   3741   * list of modified frames for display list building. Only pass false
   3742   * if you're sure that the relevant display items will be rebuilt
   3743   * already (possibly by an ancestor being in the modified list).
   3744   */
   3745  virtual void InvalidateFrameWithRect(const nsRect& aRect,
   3746                                       uint32_t aDisplayItemKey = 0,
   3747                                       bool aRebuildDisplayItems = true);
   3748 
   3749  /**
   3750   * Calls InvalidateFrame() on all frames descendant frames (including
   3751   * this one).
   3752   *
   3753   * This function doesn't walk through placeholder frames to invalidate
   3754   * the out-of-flow frames.
   3755   *
   3756   * @param aRebuildDisplayItems If true, then adds this frame to the
   3757   * list of modified frames for display list building. Only pass false
   3758   * if you're sure that the relevant display items will be rebuilt
   3759   * already (possibly by an ancestor being in the modified list).
   3760   */
   3761  void InvalidateFrameSubtree(bool aRebuildDisplayItems = true);
   3762 
   3763  /**
   3764   * Called when a frame is about to be removed and needs to be invalidated.
   3765   * Normally does nothing since DLBI handles removed frames.
   3766   */
   3767  virtual void InvalidateFrameForRemoval() {}
   3768 
   3769  /**
   3770   * Checks if a frame has had InvalidateFrame() called on it since the
   3771   * last paint.
   3772   *
   3773   * If true, then the invalid rect is returned in aRect, with an
   3774   * empty rect meaning all pixels drawn by this frame should be
   3775   * invalidated.
   3776   * If false, aRect is left unchanged.
   3777   */
   3778  bool IsInvalid(nsRect& aRect);
   3779 
   3780  /**
   3781   * Check if any frame within the frame subtree (including this frame)
   3782   * returns true for IsInvalid().
   3783   */
   3784  bool HasInvalidFrameInSubtree() {
   3785    return HasAnyStateBits(NS_FRAME_NEEDS_PAINT |
   3786                           NS_FRAME_DESCENDANT_NEEDS_PAINT);
   3787  }
   3788 
   3789  /**
   3790   * Removes the invalid state from the current frame and all
   3791   * descendant frames.
   3792   */
   3793  void ClearInvalidationStateBits();
   3794 
   3795  /**
   3796   * Ensures that the refresh driver is running, and schedules a view
   3797   * manager flush on the next tick.
   3798   *
   3799   * The view manager flush will update the layer tree, repaint any
   3800   * invalid areas in the layer tree and schedule a layer tree
   3801   * composite operation to display the layer tree.
   3802   *
   3803   * In general it is not necessary for frames to call this when they change.
   3804   * For example, changes that result in a reflow will have this called for
   3805   * them by PresContext::DoReflow when the reflow begins. Style changes that
   3806   * do not trigger a reflow should have this called for them by
   3807   * DoApplyRenderingChangeToTree.
   3808   *
   3809   * @param aType PAINT_COMPOSITE_ONLY : No changes have been made
   3810   * that require a layer tree update, so only schedule a layer
   3811   * tree composite.
   3812   */
   3813  enum PaintType { PAINT_DEFAULT = 0, PAINT_COMPOSITE_ONLY };
   3814  void SchedulePaint(PaintType aType = PAINT_DEFAULT,
   3815                     bool aFrameChanged = true);
   3816 
   3817  // Similar to SchedulePaint() but without calling
   3818  // InvalidateRenderingObservers() for SVG.
   3819  void SchedulePaintWithoutInvalidatingObservers(
   3820      PaintType aType = PAINT_DEFAULT);
   3821 
   3822  /**
   3823   * Checks if the layer tree includes a dedicated layer for this
   3824   * frame/display item key pair, and invalidates at least aDamageRect
   3825   * area within that layer.
   3826   *
   3827   * If no layer is found, calls InvalidateFrame() instead.
   3828   *
   3829   * @param aDamageRect Area of the layer to invalidate.
   3830   * @param aFrameDamageRect If no layer is found, the area of the frame to
   3831   *                         invalidate. If null, the entire frame will be
   3832   *                         invalidated.
   3833   * @param aDisplayItemKey Display item type.
   3834   * @param aFlags UPDATE_IS_ASYNC : Will skip the invalidation
   3835   * if the found layer is being composited by a remote
   3836   * compositor.
   3837   * @return Layer, if found, nullptr otherwise.
   3838   */
   3839  enum { UPDATE_IS_ASYNC = 1 << 0 };
   3840  void InvalidateLayer(DisplayItemType aDisplayItemKey,
   3841                       const nsIntRect* aDamageRect = nullptr,
   3842                       const nsRect* aFrameDamageRect = nullptr,
   3843                       uint32_t aFlags = 0);
   3844 
   3845  void MarkNeedsDisplayItemRebuild();
   3846 
   3847  /**
   3848   * Returns a rect that encompasses everything that might be painted by
   3849   * this frame.  This includes this frame, all its descendant frames, this
   3850   * frame's outline, and descendant frames' outline, but does not include
   3851   * areas clipped out by the CSS "overflow" and "clip" properties.
   3852   *
   3853   * HasOverflowAreas() (below) will return true when this overflow
   3854   * rect has been explicitly set, even if it matches mRect.
   3855   * XXX Note: because of a space optimization using the formula above,
   3856   * during reflow this function does not give accurate data if
   3857   * FinishAndStoreOverflow has been called but mRect hasn't yet been
   3858   * updated yet.  FIXME: This actually isn't true, but it should be.
   3859   *
   3860   * The ink overflow rect should NEVER be used for things that
   3861   * affect layout.  The scrollable overflow rect is permitted to affect
   3862   * layout.
   3863   *
   3864   * @return the rect relative to this frame's origin, but after
   3865   * CSS transforms have been applied (i.e. not really this frame's coordinate
   3866   * system, and may not contain the frame's border-box, e.g. if there
   3867   * is a CSS transform scaling it down)
   3868   */
   3869  nsRect InkOverflowRect() const {
   3870    return GetOverflowRect(mozilla::OverflowType::Ink);
   3871  }
   3872 
   3873  /**
   3874   * Returns a rect that encompasses the area of this frame that the
   3875   * user should be able to scroll to reach.  This is similar to
   3876   * InkOverflowRect, but does not include outline or shadows, and
   3877   * may in the future include more margins than ink overflow does.
   3878   * It does not include areas clipped out by the CSS "overflow" and
   3879   * "clip" properties.
   3880   *
   3881   * HasOverflowAreas() (below) will return true when this overflow
   3882   * rect has been explicitly set, even if it matches mRect.
   3883   * XXX Note: because of a space optimization using the formula above,
   3884   * during reflow this function does not give accurate data if
   3885   * FinishAndStoreOverflow has been called but mRect hasn't yet been
   3886   * updated yet.
   3887   *
   3888   * @return the rect relative to this frame's origin, but after
   3889   * CSS transforms have been applied (i.e. not really this frame's coordinate
   3890   * system, and may not contain the frame's border-box, e.g. if there
   3891   * is a CSS transform scaling it down)
   3892   */
   3893  nsRect ScrollableOverflowRect() const {
   3894    return GetOverflowRect(mozilla::OverflowType::Scrollable);
   3895  }
   3896 
   3897  mozilla::OverflowAreas GetOverflowAreas() const;
   3898 
   3899  /**
   3900   * Same as GetOverflowAreas, except in this frame's coordinate
   3901   * system (before transforms are applied).
   3902   *
   3903   * @return the overflow areas relative to this frame, before any CSS
   3904   * transforms have been applied, i.e. in this frame's coordinate system
   3905   */
   3906  mozilla::OverflowAreas GetOverflowAreasRelativeToSelf() const;
   3907 
   3908  /**
   3909   * Same as GetOverflowAreas, except relative to the parent frame.
   3910   *
   3911   * @return the overflow area relative to the parent frame, in the parent
   3912   * frame's coordinate system
   3913   */
   3914  mozilla::OverflowAreas GetOverflowAreasRelativeToParent() const;
   3915 
   3916  /**
   3917   * Same as GetOverflowAreasRelativeToParent(), except that it also unions in
   3918   * the normal position overflow area if this frame is relatively or sticky
   3919   * positioned.
   3920   *
   3921   * @return the overflow area relative to the parent frame, in the parent
   3922   * frame's coordinate system
   3923   */
   3924  mozilla::OverflowAreas GetActualAndNormalOverflowAreasRelativeToParent()
   3925      const;
   3926 
   3927  /**
   3928   * Same as ScrollableOverflowRect, except relative to the parent
   3929   * frame.
   3930   *
   3931   * @return the rect relative to the parent frame, in the parent frame's
   3932   * coordinate system
   3933   */
   3934  nsRect ScrollableOverflowRectRelativeToParent() const;
   3935 
   3936  /**
   3937   * Same as ScrollableOverflowRect, except in this frame's coordinate
   3938   * system (before transforms are applied).
   3939   *
   3940   * @return the rect relative to this frame, before any CSS transforms have
   3941   * been applied, i.e. in this frame's coordinate system
   3942   */
   3943  nsRect ScrollableOverflowRectRelativeToSelf() const;
   3944 
   3945  /**
   3946   * Like InkOverflowRect, except in this frame's
   3947   * coordinate system (before transforms are applied).
   3948   *
   3949   * @return the rect relative to this frame, before any CSS transforms have
   3950   * been applied, i.e. in this frame's coordinate system
   3951   */
   3952  nsRect InkOverflowRectRelativeToSelf() const;
   3953 
   3954  /**
   3955   * Same as InkOverflowRect, except relative to the parent
   3956   * frame.
   3957   *
   3958   * @return the rect relative to the parent frame, in the parent frame's
   3959   * coordinate system
   3960   */
   3961  nsRect InkOverflowRectRelativeToParent() const;
   3962 
   3963  /**
   3964   * Returns this frame's ink overflow rect as it would be before taking
   3965   * account of SVG effects or transforms. The rect returned is relative to
   3966   * this frame.
   3967   */
   3968  nsRect PreEffectsInkOverflowRect() const;
   3969 
   3970  /**
   3971   * Store the overflow area in the frame's mOverflow.mInkOverflowDeltas
   3972   * fields or as a frame property in OverflowAreasProperty() so that it can
   3973   * be retrieved later without reflowing the frame. Returns true if either of
   3974   * the overflow areas changed.
   3975   */
   3976  bool FinishAndStoreOverflow(mozilla::OverflowAreas& aOverflowAreas,
   3977                              nsSize aNewSize, nsSize* aOldSize = nullptr,
   3978                              const nsStyleDisplay* aStyleDisplay = nullptr);
   3979 
   3980  bool FinishAndStoreOverflow(ReflowOutput* aMetrics,
   3981                              const nsStyleDisplay* aStyleDisplay = nullptr) {
   3982    return FinishAndStoreOverflow(aMetrics->mOverflowAreas,
   3983                                  nsSize(aMetrics->Width(), aMetrics->Height()),
   3984                                  nullptr, aStyleDisplay);
   3985  }
   3986 
   3987  /**
   3988   * Returns whether the frame has an overflow rect that is different from
   3989   * its border-box.
   3990   */
   3991  bool HasOverflowAreas() const {
   3992    return mOverflow.mType != OverflowStorageType::None;
   3993  }
   3994 
   3995  /**
   3996   * Removes any stored overflow rects (visual and scrollable) from the frame.
   3997   * Returns true if the overflow changed.
   3998   */
   3999  bool ClearOverflowRects();
   4000 
   4001  /**
   4002   * Determine whether borders, padding, margins etc should NOT be applied
   4003   * on certain sides of the frame.
   4004   * @see mozilla::Sides in gfx/2d/BaseMargin.h
   4005   * @see mozilla::LogicalSides in layout/generic/WritingModes.h
   4006   *
   4007   * @note (See also bug 743402, comment 11) GetSkipSides() checks to see
   4008   *       if this frame has a previous or next continuation to determine
   4009   *       if a side should be skipped.
   4010   *       So this only works after the entire frame tree has been reflowed.
   4011   *       During reflow, if this frame can be split in the block axis, you
   4012   *       should use nsSplittableFrame::PreReflowBlockLevelLogicalSkipSides().
   4013   */
   4014  Sides GetSkipSides() const;
   4015  virtual LogicalSides GetLogicalSkipSides() const {
   4016    return LogicalSides(mWritingMode);
   4017  }
   4018 
   4019  /**
   4020   * @returns true if this frame is selected.
   4021   */
   4022  bool IsSelected() const {
   4023    return (GetContent() && GetContent()->IsMaybeSelected()) ? IsFrameSelected()
   4024                                                             : false;
   4025  }
   4026 
   4027  /**
   4028   * Shouldn't be called if this is a `nsTextFrame`. Call the
   4029   * `nsTextFrame::SelectionStateChanged` overload instead.
   4030   */
   4031  void SelectionStateChanged() {
   4032    MOZ_ASSERT(!IsTextFrame());
   4033    InvalidateFrameSubtree();  // TODO: should this deal with continuations?
   4034  }
   4035 
   4036  /**
   4037   * Called to discover where this frame, or a parent frame has user-select
   4038   * style applied, which affects that way that it is selected.
   4039   * NOTE: Even if this returns true it does NOT mean the `user-select` style
   4040   * is not `none`.  If the content is editable or a text control element, this
   4041   * returns true.
   4042   *
   4043   * @param aSelectStyle out param. Returns the type of selection style found
   4044   * (using values defined in nsStyleConsts.h).
   4045   *
   4046   * @return Whether the frame can be selected (i.e. is not affected by
   4047   * user-select: none)
   4048   */
   4049  [[nodiscard]] bool IsSelectable(
   4050      mozilla::StyleUserSelect* aSelectStyle = nullptr) const;
   4051 
   4052  /**
   4053   * Return true if the frame should paint normal selection.  This may return
   4054   * true even if IsSelectable() in some cases.  E.g., when the normal selection
   4055   * is the result of "Find in Page".
   4056   * NOTE: This returns true even if the display selection is OFF since it
   4057   * should've already been checked before this is called and this should be
   4058   * cheaper as far as possible because of a part of painting.
   4059   */
   4060  [[nodiscard]] bool ShouldPaintNormalSelection() const;
   4061 
   4062  /**
   4063   * Returns whether this frame should have the content-block-size of a line,
   4064   * even if empty.
   4065   */
   4066  bool ShouldHaveLineIfEmpty() const;
   4067 
   4068  /**
   4069   * Called to retrieve the SelectionController associated with the frame.
   4070   */
   4071  nsISelectionController* GetSelectionController() const;
   4072 
   4073  /**
   4074   * Return the display value of selections which is default to SELECTION_OFF if
   4075   * there is no selection controller.
   4076   */
   4077  int16_t GetDisplaySelection() const;
   4078 
   4079  /**
   4080   * Call to get nsFrameSelection for this frame.
   4081   */
   4082  already_AddRefed<nsFrameSelection> GetFrameSelection();
   4083 
   4084  /**
   4085   * GetConstFrameSelection returns an object which methods are safe to use for
   4086   * example in nsIFrame code.
   4087   */
   4088  const nsFrameSelection* GetConstFrameSelection() const;
   4089 
   4090  /**
   4091   * called to find the previous/next character, word, or line. Returns the
   4092   * actual nsIFrame and the frame offset. THIS DOES NOT CHANGE SELECTION STATE.
   4093   * Uses frame's begin selection state to start. If no selection on this frame
   4094   * will return NS_ERROR_FAILURE.
   4095   *
   4096   * @param aPos is defined in nsFrameSelection
   4097   */
   4098  virtual nsresult PeekOffset(mozilla::PeekOffsetStruct* aPos);
   4099 
   4100 private:
   4101  nsresult PeekOffsetForCharacter(mozilla::PeekOffsetStruct* aPos,
   4102                                  int32_t aOffset);
   4103  nsresult PeekOffsetForWord(mozilla::PeekOffsetStruct* aPos, int32_t aOffset);
   4104  nsresult PeekOffsetForLine(mozilla::PeekOffsetStruct* aPos);
   4105  nsresult PeekOffsetForLineEdge(mozilla::PeekOffsetStruct* aPos);
   4106 
   4107  /**
   4108   * Search for the first paragraph boundary before or after the given position
   4109   * @param  aPos See description in nsFrameSelection.h. The following fields
   4110   *              are used by this method:
   4111   *              Input: mDirection
   4112   *              Output: mResultContent, mContentOffset
   4113   */
   4114  nsresult PeekOffsetForParagraph(mozilla::PeekOffsetStruct* aPos);
   4115 
   4116 public:
   4117  // given a frame five me the first/last leaf available
   4118  // XXX Robert O'Callahan wants to move these elsewhere
   4119  // FIXME: Only GetLastLeaf() never returns a leaf frame in native anonymous
   4120  // subtrees under aFrame.  However, GetFirstLeaf() may return a leaf frame
   4121  // in a native anonymous subtree.
   4122  static void GetLastLeaf(nsIFrame** aFrame);
   4123  static void GetFirstLeaf(nsIFrame** aFrame);
   4124 
   4125  struct SelectablePeekReport {
   4126    /** the previous/next selectable leaf frame */
   4127    nsIFrame* mFrame = nullptr;
   4128    /**
   4129     * 0 indicates that we arrived at the beginning of the output frame; -1
   4130     * indicates that we arrived at its end.
   4131     */
   4132    int32_t mOffset = 0;
   4133    /** whether the input frame and the returned frame are on different lines */
   4134    bool mJumpedLine = false;
   4135    /** whether we met a hard break between the input and the returned frame */
   4136    bool mJumpedHardBreak = false;
   4137    /** whether we met a child placeholder frame */
   4138    bool mFoundPlaceholder = false;
   4139    /** whether we jumped over a non-selectable frame during the search */
   4140    bool mMovedOverNonSelectableText = false;
   4141    /** whether we met selectable text frame that isn't editable during the
   4142     *  search */
   4143    bool mHasSelectableFrame = false;
   4144    /** whether we ignored a br frame */
   4145    bool mIgnoredBrFrame = false;
   4146 
   4147    FrameSearchResult PeekOffsetNoAmount(bool aForward) {
   4148      return mFrame->PeekOffsetNoAmount(aForward, &mOffset);
   4149    }
   4150    FrameSearchResult PeekOffsetCharacter(bool aForward,
   4151                                          PeekOffsetCharacterOptions aOptions) {
   4152      return mFrame->PeekOffsetCharacter(aForward, &mOffset, aOptions);
   4153    };
   4154 
   4155    /** Transfers frame and offset info for PeekOffset() result */
   4156    void TransferTo(mozilla::PeekOffsetStruct& aPos) const;
   4157    bool Failed() { return !mFrame; }
   4158 
   4159    explicit SelectablePeekReport(nsIFrame* aFrame = nullptr,
   4160                                  int32_t aOffset = 0)
   4161        : mFrame(aFrame), mOffset(aOffset) {}
   4162    MOZ_IMPLICIT SelectablePeekReport(
   4163        const mozilla::GenericErrorResult<nsresult>&& aErr);
   4164  };
   4165 
   4166  /**
   4167   * Called to find the previous/next non-anonymous selectable leaf frame.
   4168   *
   4169   * @param aDirection the direction to move in (eDirPrevious or eDirNext)
   4170   * @param aOptions the other options which is same as
   4171   * PeekOffsetStruct::mOptions.
   4172   * @param aAncestorLimiter if set, this refers only the frames for its
   4173   * descendants.
   4174   * FIXME: Due to the include hell, we cannot use the alias, PeekOffsetOptions
   4175   * is not available in this header file.
   4176   */
   4177  SelectablePeekReport GetFrameFromDirection(
   4178      nsDirection aDirection,
   4179      const mozilla::EnumSet<mozilla::PeekOffsetOption>& aOptions,
   4180      const mozilla::dom::Element* aAncestorLimiter);
   4181  SelectablePeekReport GetFrameFromDirection(
   4182      const mozilla::PeekOffsetStruct& aPos);
   4183 
   4184  /**
   4185   * Return:
   4186   * (1) the containing block frame for a line; i.e. the frame which
   4187   * supports a line iterator, or null if none can be found; and
   4188   * (2) the frame to use to get a line number, which will be direct child of
   4189   * the returned containing block.
   4190   * @param aLockScroll true to avoid breaking outside scrollframes.
   4191   */
   4192  std::pair<nsIFrame*, nsIFrame*> GetContainingBlockForLine(
   4193      bool aLockScroll) const;
   4194 
   4195 private:
   4196  Result<bool, nsresult> IsVisuallyAtLineEdge(nsILineIterator* aLineIterator,
   4197                                              int32_t aLine,
   4198                                              nsDirection aDirection);
   4199  Result<bool, nsresult> IsLogicallyAtLineEdge(nsILineIterator* aLineIterator,
   4200                                               int32_t aLine,
   4201                                               nsDirection aDirection);
   4202 
   4203 public:
   4204  /**
   4205   * Called to tell a frame that one of its child frames is dirty (i.e.,
   4206   * has the NS_FRAME_IS_DIRTY *or* NS_FRAME_HAS_DIRTY_CHILDREN bit
   4207   * set).  This should always set the NS_FRAME_HAS_DIRTY_CHILDREN on
   4208   * the frame, and may do other work.
   4209   */
   4210  virtual void ChildIsDirty(nsIFrame* aChild);
   4211 
   4212  /**
   4213   * Called to retrieve this frame's accessible.
   4214   * If this frame implements Accessibility return a valid accessible
   4215   * If not return NS_ERROR_NOT_IMPLEMENTED.
   4216   * Note: LocalAccessible must be refcountable. Do not implement directly on
   4217   * your frame Use a mediatior of some kind.
   4218   */
   4219 #ifdef ACCESSIBILITY
   4220  virtual mozilla::a11y::AccType AccessibleType();
   4221 #endif
   4222 
   4223  /**
   4224   * Get the frame whose style should be the parent of this frame's style (i.e.,
   4225   * provide the parent style).
   4226   *
   4227   * This frame must either be an ancestor of this frame or a child.  If
   4228   * this returns a child frame, then the child frame must be sure to
   4229   * return a grandparent or higher!  Furthermore, if a child frame is
   4230   * returned it must have the same GetContent() as this frame.
   4231   *
   4232   * @param aProviderFrame (out) the frame associated with the returned value
   4233   *     or nullptr if the style is for display:contents content.
   4234   * @return The style that should be the parent of this frame's style. Null is
   4235   *         permitted, and means that this frame's style should be the root of
   4236   *         the style tree.
   4237   */
   4238  virtual ComputedStyle* GetParentComputedStyle(
   4239      nsIFrame** aProviderFrame) const {
   4240    return DoGetParentComputedStyle(aProviderFrame);
   4241  }
   4242 
   4243  /**
   4244   * Do the work for getting the parent ComputedStyle frame so that
   4245   * other frame's |GetParentComputedStyle| methods can call this
   4246   * method on *another* frame.  (This function handles out-of-flow
   4247   * frames by using the frame manager's placeholder map and it also
   4248   * handles block-within-inline and generated content wrappers.)
   4249   *
   4250   * @param aProviderFrame (out) the frame associated with the returned value
   4251   *   or null if the ComputedStyle is for display:contents content.
   4252   * @return The ComputedStyle that should be the parent of this frame's
   4253   *   ComputedStyle.  Null is permitted, and means that this frame's
   4254   *   ComputedStyle should be the root of the ComputedStyle tree.
   4255   */
   4256  ComputedStyle* DoGetParentComputedStyle(nsIFrame** aProviderFrame) const;
   4257 
   4258  /**
   4259   * Adjust the given parent frame to the right ComputedStyle parent frame for
   4260   * the child, given the pseudo-type of the prospective child.  This handles
   4261   * things like walking out of table pseudos and so forth.
   4262   *
   4263   * @param aProspectiveParent what GetParent() on the child returns.
   4264   *                           Must not be null.
   4265   * @param aChildPseudo the child's pseudo type, if any.
   4266   */
   4267  static nsIFrame* CorrectStyleParentFrame(
   4268      nsIFrame* aProspectiveParent, mozilla::PseudoStyleType aChildPseudo);
   4269 
   4270  /**
   4271   * Called by RestyleManager to update the style of anonymous boxes
   4272   * directly associated with this frame.
   4273   *
   4274   * The passed-in ServoRestyleState can be used to create new ComputedStyles as
   4275   * needed, as well as posting changes to the change list.
   4276   *
   4277   * It's guaranteed to already have a change in it for this frame and this
   4278   * frame's content.
   4279   *
   4280   * This function will be called after this frame's style has already been
   4281   * updated.  This function will only be called on frames which have the
   4282   * NS_FRAME_OWNS_ANON_BOXES bit set.
   4283   */
   4284  void UpdateStyleOfOwnedAnonBoxes(mozilla::ServoRestyleState& aRestyleState) {
   4285    if (HasAnyStateBits(NS_FRAME_OWNS_ANON_BOXES)) {
   4286      DoUpdateStyleOfOwnedAnonBoxes(aRestyleState);
   4287    }
   4288  }
   4289 
   4290  mozilla::ContainSizeAxes GetContainSizeAxes() const {
   4291    return StyleDisplay()->GetContainSizeAxes(*this);
   4292  }
   4293 
   4294  // Common steps to all replaced elements given an unconstrained intrinsic
   4295  // size.
   4296  mozilla::IntrinsicSize FinishIntrinsicSize(
   4297      const mozilla::ContainSizeAxes& aAxes,
   4298      const mozilla::IntrinsicSize& aUncontainedSize) const {
   4299    auto result = aAxes.ContainIntrinsicSize(aUncontainedSize, *this);
   4300    result.Zoom(Style()->EffectiveZoom());
   4301    return result;
   4302  }
   4303 
   4304  Maybe<nscoord> ContainIntrinsicBSize(nscoord aNoneValue = 0) const {
   4305    return GetContainSizeAxes().ContainIntrinsicBSize(*this, aNoneValue);
   4306  }
   4307 
   4308  Maybe<nscoord> ContainIntrinsicISize(nscoord aNoneValue = 0) const {
   4309    return GetContainSizeAxes().ContainIntrinsicISize(*this, aNoneValue);
   4310  }
   4311 
   4312 protected:
   4313  // This does the actual work of UpdateStyleOfOwnedAnonBoxes.  It calls
   4314  // AppendDirectlyOwnedAnonBoxes to find all of the anonymous boxes
   4315  // owned by this frame, and then updates styles on each of them.
   4316  void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoRestyleState& aRestyleState);
   4317 
   4318  // A helper for DoUpdateStyleOfOwnedAnonBoxes for the specific case
   4319  // of the owned anon box being a child of this frame.
   4320  void UpdateStyleOfChildAnonBox(nsIFrame* aChildFrame,
   4321                                 mozilla::ServoRestyleState& aRestyleState);
   4322 
   4323  // Allow ServoRestyleState to call UpdateStyleOfChildAnonBox.
   4324  friend class mozilla::ServoRestyleState;
   4325 
   4326 public:
   4327  // A helper both for UpdateStyleOfChildAnonBox, and to update frame-backed
   4328  // pseudo-elements in RestyleManager.
   4329  //
   4330  // This gets a ComputedStyle that will be the new style for `aChildFrame`, and
   4331  // takes care of updating it, calling CalcStyleDifference, and adding to the
   4332  // change list as appropriate.
   4333  //
   4334  // If aContinuationComputedStyle is not Nothing, it should be used for
   4335  // continuations instead of aNewComputedStyle.  In either case, changehints
   4336  // are only computed based on aNewComputedStyle.
   4337  //
   4338  // Returns the generated change hint for the frame.
   4339  static nsChangeHint UpdateStyleOfOwnedChildFrame(
   4340      nsIFrame* aChildFrame, ComputedStyle* aNewComputedStyle,
   4341      mozilla::ServoRestyleState& aRestyleState,
   4342      const Maybe<ComputedStyle*>& aContinuationComputedStyle = Nothing());
   4343 
   4344  struct OwnedAnonBox {
   4345    typedef void (*UpdateStyleFn)(nsIFrame* aOwningFrame, nsIFrame* aAnonBox,
   4346                                  mozilla::ServoRestyleState& aRestyleState);
   4347 
   4348    explicit OwnedAnonBox(nsIFrame* aAnonBoxFrame,
   4349                          UpdateStyleFn aUpdateStyleFn = nullptr)
   4350        : mAnonBoxFrame(aAnonBoxFrame), mUpdateStyleFn(aUpdateStyleFn) {}
   4351 
   4352    nsIFrame* mAnonBoxFrame;
   4353    UpdateStyleFn mUpdateStyleFn;
   4354  };
   4355 
   4356  /**
   4357   * Appends information about all of the anonymous boxes owned by this frame,
   4358   * including other anonymous boxes owned by those which this frame owns
   4359   * directly.
   4360   */
   4361  void AppendOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) {
   4362    if (HasAnyStateBits(NS_FRAME_OWNS_ANON_BOXES)) {
   4363      if (IsInlineFrame()) {
   4364        // See comment in nsIFrame::DoUpdateStyleOfOwnedAnonBoxes for why
   4365        // we skip nsInlineFrames.
   4366        return;
   4367      }
   4368      DoAppendOwnedAnonBoxes(aResult);
   4369    }
   4370  }
   4371 
   4372 protected:
   4373  // This does the actual work of AppendOwnedAnonBoxes.
   4374  void DoAppendOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult);
   4375 
   4376 public:
   4377  /**
   4378   * Hook subclasses can override to return their owned anonymous boxes.
   4379   *
   4380   * This function only appends anonymous boxes that are directly owned by
   4381   * this frame, i.e. direct children or (for certain frames) a wrapper
   4382   * parent, unlike AppendOwnedAnonBoxes, which will append all anonymous
   4383   * boxes transitively owned by this frame.
   4384   */
   4385  virtual void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult);
   4386 
   4387  /**
   4388   * Determines whether a frame is visible for painting;
   4389   * taking into account whether it is painting a selection or printing.
   4390   */
   4391  bool IsVisibleForPainting() const;
   4392  /**
   4393   * Determines whether a frame is visible for painting or collapsed;
   4394   * taking into account whether it is painting a selection or printing,
   4395   */
   4396  bool IsVisibleOrCollapsedForPainting() const;
   4397 
   4398  /**
   4399   * Determines if this frame is a stacking context.
   4400   */
   4401  bool IsStackingContext(const nsStyleDisplay*, const nsStyleEffects*);
   4402  bool IsStackingContext();
   4403 
   4404  // Whether we should paint backgrounds or not.
   4405  struct ShouldPaintBackground {
   4406    bool mColor = false;
   4407    bool mImage = false;
   4408  };
   4409  ShouldPaintBackground ComputeShouldPaintBackground() const;
   4410 
   4411  /**
   4412   * Determine whether the frame is logically empty, which is roughly
   4413   * whether the layout would be the same whether or not the frame is
   4414   * present.  Placeholder frames should return true.  Block frames
   4415   * should be considered empty whenever margins collapse through them,
   4416   * even though those margins are relevant.  Text frames containing
   4417   * only whitespace that does not contribute to the height of the line
   4418   * should return true.
   4419   */
   4420  virtual bool IsEmpty();
   4421  /**
   4422   * Return the same as IsEmpty(). This may only be called after the frame
   4423   * has been reflowed and before any further style or content changes.
   4424   */
   4425  virtual bool CachedIsEmpty();
   4426  /**
   4427   * Determine whether the frame is logically empty, assuming that all
   4428   * its children are empty.
   4429   */
   4430  virtual bool IsSelfEmpty();
   4431 
   4432  /**
   4433   * IsGeneratedContentFrame returns whether a frame corresponds to
   4434   * generated content
   4435   *
   4436   * @return whether the frame correspods to generated content
   4437   */
   4438  bool IsGeneratedContentFrame() const {
   4439    return HasAnyStateBits(NS_FRAME_GENERATED_CONTENT);
   4440  }
   4441 
   4442  /**
   4443   * IsPseudoFrame returns whether a frame is a pseudo frame (eg an
   4444   * anonymous table-row frame created for a CSS table-cell without an
   4445   * enclosing table-row.
   4446   *
   4447   * @param aParentContent the content node corresponding to the parent frame
   4448   * @return whether the frame is a pseudo frame
   4449   */
   4450  bool IsPseudoFrame(const nsIContent* aParentContent) {
   4451    return mContent == aParentContent;
   4452  }
   4453 
   4454  /**
   4455   * Support for reading and writing properties on the frame.
   4456   * These call through to the frame's FrameProperties object, if it
   4457   * exists, but avoid creating it if no property is ever set.
   4458   */
   4459  template <typename T>
   4460  FrameProperties::PropertyType<T> GetProperty(
   4461      FrameProperties::Descriptor<T> aProperty,
   4462      bool* aFoundResult = nullptr) const {
   4463    return mProperties.Get(aProperty, aFoundResult);
   4464  }
   4465 
   4466  template <typename T>
   4467  bool HasProperty(FrameProperties::Descriptor<T> aProperty) const {
   4468    return mProperties.Has(aProperty);
   4469  }
   4470 
   4471  /**
   4472   * Add a property, or update an existing property for the given descriptor.
   4473   *
   4474   * Note: This function asserts if updating an existing nsFrameList property.
   4475   */
   4476  template <typename T>
   4477  void SetProperty(FrameProperties::Descriptor<T> aProperty,
   4478                   FrameProperties::PropertyType<T> aValue) {
   4479    if constexpr (std::is_same_v<T, nsFrameList>) {
   4480      MOZ_ASSERT(aValue, "Shouldn't set nullptr to a nsFrameList property!");
   4481      MOZ_ASSERT(!HasProperty(aProperty),
   4482                 "Shouldn't update an existing nsFrameList property!");
   4483    }
   4484    mProperties.Set(aProperty, aValue, this);
   4485  }
   4486 
   4487  // Unconditionally add a property; use ONLY if the descriptor is known
   4488  // to NOT already be present.
   4489  template <typename T>
   4490  void AddProperty(FrameProperties::Descriptor<T> aProperty,
   4491                   FrameProperties::PropertyType<T> aValue) {
   4492    mProperties.Add(aProperty, aValue);
   4493  }
   4494 
   4495  /**
   4496   * Remove a property and return its value without destroying it. May return
   4497   * nullptr.
   4498   *
   4499   * Note: The caller is responsible for handling the life cycle of the returned
   4500   * value.
   4501   */
   4502  template <typename T>
   4503  [[nodiscard]] FrameProperties::PropertyType<T> TakeProperty(
   4504      FrameProperties::Descriptor<T> aProperty, bool* aFoundResult = nullptr) {
   4505    return mProperties.Take(aProperty, aFoundResult);
   4506  }
   4507 
   4508  template <typename T>
   4509  bool RemoveProperty(FrameProperties::Descriptor<T> aProperty) {
   4510    return mProperties.Remove(aProperty, this);
   4511  }
   4512 
   4513  /**
   4514   * Set the deletable property with a given value if it doesn't already exist;
   4515   * otherwise, allocate a copy of the passed-in value and insert that as a new
   4516   * value. Returns the pointer to the property, guaranteed non-null, value that
   4517   * then can be used to update the property value further.
   4518   *
   4519   * Note: As the name suggests, this will behave properly only for properties
   4520   * declared with NS_DECLARE_FRAME_PROPERTY_DELETABLE!
   4521   */
   4522  template <typename T, typename... Params>
   4523  FrameProperties::PropertyType<T> SetOrUpdateDeletableProperty(
   4524      FrameProperties::Descriptor<T> aProperty, Params&&... aParams) {
   4525    bool found;
   4526    using DataType = std::remove_pointer_t<FrameProperties::PropertyType<T>>;
   4527    DataType* storedValue = GetProperty(aProperty, &found);
   4528    if (!found) {
   4529      storedValue = new DataType{aParams...};
   4530      AddProperty(aProperty, storedValue);
   4531    } else {
   4532      *storedValue = DataType{aParams...};
   4533    }
   4534    return storedValue;
   4535  }
   4536 
   4537  void RemoveAllProperties() { mProperties.RemoveAll(this); }
   4538 
   4539  // nsIFrames themselves are in the nsPresArena, and so are not measured here.
   4540  // Instead, this measures heap-allocated things hanging off the nsIFrame, and
   4541  // likewise for its descendants.
   4542  virtual void AddSizeOfExcludingThisForTree(nsWindowSizes& aWindowSizes) const;
   4543 
   4544  /**
   4545   * Return true if and only if this frame obeys visibility:hidden.
   4546   * if it does not, then nsContainerFrame will hide its view even though
   4547   * this means children can't be made visible again.
   4548   */
   4549  virtual bool SupportsVisibilityHidden() { return true; }
   4550 
   4551  /**
   4552   * Returns the clip rect set via the 'clip' property, if the 'clip' property
   4553   * applies to this frame; otherwise returns Nothing(). The 'clip' property
   4554   * applies to HTML frames if they are absolutely positioned. The 'clip'
   4555   * property applies to SVG frames regardless of the value of the 'position'
   4556   * property.
   4557   *
   4558   * The coordinates of the returned rectangle are relative to this frame's
   4559   * origin.
   4560   */
   4561  Maybe<nsRect> GetClipPropClipRect(const nsStyleDisplay* aDisp,
   4562                                    const nsStyleEffects* aEffects,
   4563                                    const nsSize& aSize) const;
   4564 
   4565  /** Whether this frame is a stacking context for view transitions purposes */
   4566  bool ForcesStackingContextForViewTransition() const;
   4567 
   4568  /**
   4569   * Check if this frame is focusable and in the current tab order.
   4570   * Tabbable is indicated by a nonnegative tabindex & is a subset of focusable.
   4571   * For example, only the selected radio button in a group is in the
   4572   * tab order, unless the radio group has no selection in which case
   4573   * all of the visible, non-disabled radio buttons in the group are
   4574   * in the tab order. On the other hand, all of the visible, non-disabled
   4575   * radio buttons are always focusable via clicking or script.
   4576   * Also, depending on the pref accessibility.tabfocus some widgets may be
   4577   * focusable but removed from the tab order. This is the default on
   4578   * Mac OS X, where fewer items are focusable.
   4579   * @return whether the frame is focusable via mouse, kbd or script.
   4580   */
   4581  [[nodiscard]] Focusable IsFocusable(
   4582      mozilla::IsFocusableFlags = mozilla::IsFocusableFlags(0));
   4583 
   4584 protected:
   4585  // Helper for IsFocusable.
   4586  bool IsFocusableDueToScrollFrame();
   4587 
   4588  /**
   4589   * Returns true if this box clips its children, e.g., if this box is an
   4590   * scrollbox or has overflow: clip in both axes.
   4591   */
   4592  bool DoesClipChildrenInBothAxes() const;
   4593 
   4594 private:
   4595  nscoord ComputeISizeValueFromAspectRatio(
   4596      mozilla::WritingMode aWM, const mozilla::LogicalSize& aCBSize,
   4597      const mozilla::LogicalSize& aContentEdgeToBoxSizing,
   4598      const mozilla::LengthPercentage& aBSize,
   4599      const mozilla::AspectRatio& aAspectRatio) const;
   4600 
   4601 public:
   4602  /**
   4603   * @return true if this text frame ends with a newline character.  It
   4604   * should return false if this is not a text frame.
   4605   */
   4606  virtual bool HasSignificantTerminalNewline() const;
   4607 
   4608  struct CaretPosition {
   4609    CaretPosition();
   4610    ~CaretPosition();
   4611 
   4612    nsCOMPtr<nsIContent> mResultContent;
   4613    int32_t mContentOffset;
   4614  };
   4615 
   4616  /**
   4617   * gets the first or last possible caret position within the frame
   4618   *
   4619   * @param  [in] aStart
   4620   *         true  for getting the first possible caret position
   4621   *         false for getting the last possible caret position
   4622   * @return The caret position in a CaretPosition.
   4623   *         the returned value is a 'best effort' in case errors
   4624   *         are encountered rummaging through the frame.
   4625   */
   4626  CaretPosition GetExtremeCaretPosition(bool aStart);
   4627 
   4628  /**
   4629   * Query whether this frame supports getting a line iterator.
   4630   * @return true if a line iterator is supported.
   4631   */
   4632  virtual bool CanProvideLineIterator() const { return false; }
   4633 
   4634  /**
   4635   * Get a line iterator for this frame, if supported.
   4636   *
   4637   * @return nullptr if no line iterator is supported.
   4638   * @note dispose the line iterator using nsILineIterator::DisposeLineIterator
   4639   */
   4640  virtual nsILineIterator* GetLineIterator() { return nullptr; }
   4641 
   4642  /**
   4643   * If this frame is a next-in-flow, and its prev-in-flow has something on its
   4644   * overflow list, pull those frames into the child list of this one.
   4645   */
   4646  virtual void PullOverflowsFromPrevInFlow() {}
   4647 
   4648  /**
   4649   * Accessors for the absolute containing block.
   4650   */
   4651  bool IsAbsoluteContainer() const {
   4652    return !!(mState & NS_FRAME_HAS_ABSPOS_CHILDREN);
   4653  }
   4654  bool HasAbsolutelyPositionedChildren() const;
   4655  mozilla::AbsoluteContainingBlock* GetAbsoluteContainingBlock() const;
   4656  void MarkAsAbsoluteContainingBlock();
   4657  void MarkAsNotAbsoluteContainingBlock();
   4658  // Child frame types override this function to select their own child list
   4659  // name
   4660  virtual mozilla::FrameChildListID GetAbsoluteListID() const {
   4661    return mozilla::FrameChildListID::Absolute;
   4662  }
   4663 
   4664  // Checks if we (or any of our descendants) have NS_FRAME_PAINTED_THEBES set,
   4665  // and clears this bit if so.
   4666  bool CheckAndClearPaintedState();
   4667 
   4668  // Checks if we (or any of our descendents) have mBuiltDisplayList set, and
   4669  // clears this bit if so.
   4670  bool CheckAndClearDisplayListState();
   4671 
   4672  // CSS visibility just doesn't cut it because it doesn't inherit through
   4673  // documents. Also if this frame is in a hidden card of a deck then it isn't
   4674  // visible either and that isn't expressed using CSS visibility. Also if it
   4675  // is in a hidden view (there are a few cases left and they are hopefully
   4676  // going away soon).
   4677  // If the VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY flag is passed then we
   4678  // ignore the chrome/content boundary, otherwise we stop looking when we
   4679  // reach it.
   4680  enum { VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY = 0x01 };
   4681  bool IsVisibleConsideringAncestors(uint32_t aFlags = 0) const;
   4682 
   4683  struct FrameWithDistance {
   4684    nsIFrame* mFrame;
   4685    nscoord mXDistance;
   4686    nscoord mYDistance;
   4687  };
   4688 
   4689  /**
   4690   * Finds a frame that is closer to a specified point than a current
   4691   * distance.  Distance is measured as for text selection -- a closer x
   4692   * distance beats a closer y distance.
   4693   *
   4694   * Normally, this function will only check the distance between this
   4695   * frame's rectangle and the specified point.  SVGTextFrame overrides
   4696   * this so that it can manage all of its descendant frames and take
   4697   * into account any SVG text layout.
   4698   *
   4699   * If aPoint is closer to this frame's rectangle than aCurrentBestFrame
   4700   * indicates, then aCurrentBestFrame is updated with the distance between
   4701   * aPoint and this frame's rectangle, and with a pointer to this frame.
   4702   * If aPoint is not closer, then aCurrentBestFrame is left unchanged.
   4703   *
   4704   * @param aPoint The point to check for its distance to this frame.
   4705   * @param aCurrentBestFrame Pointer to a struct that will be updated with
   4706   *   a pointer to this frame and its distance to aPoint, if this frame
   4707   *   is indeed closer than the current distance in aCurrentBestFrame.
   4708   */
   4709  virtual void FindCloserFrameForSelection(
   4710      const nsPoint& aPoint, FrameWithDistance* aCurrentBestFrame);
   4711 
   4712  /**
   4713   * Is this a flex item? (i.e. a non-abs-pos child of a flex container)
   4714   */
   4715  inline bool IsFlexItem() const;
   4716  /**
   4717   * Is this a grid item? (i.e. a non-abs-pos child of a grid container)
   4718   */
   4719  inline bool IsGridItem() const;
   4720  /**
   4721   * Is this a flex or grid item? (i.e. a non-abs-pos child of a flex/grid
   4722   * container)
   4723   */
   4724  inline bool IsFlexOrGridItem() const;
   4725  inline bool IsFlexOrGridContainer() const;
   4726 
   4727  /**
   4728   * Is this flex container emulating legacy display:-webkit-{inline-}box?
   4729   *
   4730   * @note only valid to call on nsFlexContainerFrames.
   4731   */
   4732  inline bool IsLegacyWebkitBox() const;
   4733 
   4734  /**
   4735   * Return true if this frame has masonry layout in aAxis (in the writing
   4736   * mode aWM).
   4737   * @note only valid to call on nsGridContainerFrames
   4738   */
   4739  inline bool IsMasonry(mozilla::WritingMode aWM,
   4740                        mozilla::LogicalAxis aAxis) const;
   4741 
   4742  /**
   4743   * @return true if this frame is used as a table caption.
   4744   */
   4745  inline bool IsTableCaption() const;
   4746 
   4747  inline bool IsBlockOutside() const;
   4748  inline bool IsInlineOutside() const;
   4749  inline mozilla::StyleDisplay GetDisplay() const;
   4750  inline bool IsFloating() const;
   4751  inline bool IsAbsPosContainingBlock() const;
   4752  inline bool IsFixedPosContainingBlock() const;
   4753  inline bool IsRelativelyOrStickyPositioned() const;
   4754  // TODO: create implicit anchor and explicit anchor versions of this method:
   4755  inline bool HasAnchorPosName() const;
   4756 
   4757  // Note: In general, you'd want to call IsRelativelyOrStickyPositioned()
   4758  // unless you want to deal with "position:relative" and "position:sticky"
   4759  // differently.
   4760  inline bool IsRelativelyPositioned() const;
   4761  inline bool IsStickyPositioned() const;
   4762 
   4763  inline bool IsAbsolutelyPositioned(
   4764      const nsStyleDisplay* aStyleDisplay = nullptr) const;
   4765  inline bool IsTrueOverflowContainer() const;
   4766 
   4767  // Does this frame have "column-span: all" style.
   4768  //
   4769  // Note this only checks computed style, but not testing whether the
   4770  // containing block formatting context was established by a multicol. Callers
   4771  // need to use IsColumnSpanInMulticolSubtree() to check whether multi-column
   4772  // effects apply or not.
   4773  inline bool IsColumnSpan() const;
   4774 
   4775  // Like IsColumnSpan(), but this also checks whether the frame has a
   4776  // multi-column ancestor or not.
   4777  inline bool IsColumnSpanInMulticolSubtree() const;
   4778 
   4779  // Returns true if this frame makes any reference to anchors.
   4780  inline bool HasAnchorPosReference() const;
   4781 
   4782  /**
   4783   * Returns the vertical-align value to be used for layout, if it is one
   4784   * of the enumerated values.  If this is an SVG text frame, it returns a value
   4785   * that corresponds to the value of dominant-baseline.  If the
   4786   * vertical-align property has length or percentage value, this returns
   4787   * Nothing().
   4788   */
   4789  Maybe<mozilla::StyleVerticalAlignKeyword> VerticalAlignEnum() const;
   4790 
   4791  /**
   4792   * Adds the NS_FRAME_IN_POPUP state bit to aFrame, and
   4793   * all descendant frames (including cross-doc ones).
   4794   */
   4795  static void AddInPopupStateBitToDescendants(nsIFrame* aFrame);
   4796  /**
   4797   * Removes the NS_FRAME_IN_POPUP state bit from aFrame and
   4798   * all descendant frames (including cross-doc ones), unless
   4799   * the frame is a popup itself.
   4800   */
   4801  static void RemoveInPopupStateBitFromDescendants(nsIFrame* aFrame);
   4802 
   4803  /**
   4804   * Return true if aFrame is in an {ib} split and is NOT one of the
   4805   * continuations of the first inline in it.
   4806   */
   4807  bool FrameIsNonFirstInIBSplit() const {
   4808    return HasAnyStateBits(NS_FRAME_PART_OF_IBSPLIT) &&
   4809           FirstContinuation()->GetProperty(nsIFrame::IBSplitPrevSibling());
   4810  }
   4811 
   4812  /**
   4813   * Return true if aFrame is in an {ib} split and is NOT one of the
   4814   * continuations of the last inline in it.
   4815   */
   4816  bool FrameIsNonLastInIBSplit() const {
   4817    return HasAnyStateBits(NS_FRAME_PART_OF_IBSPLIT) &&
   4818           FirstContinuation()->GetProperty(nsIFrame::IBSplitSibling());
   4819  }
   4820 
   4821  /**
   4822   * Return whether this is a frame whose width is used when computing
   4823   * the font size inflation of its descendants.
   4824   */
   4825  bool IsContainerForFontSizeInflation() const {
   4826    return HasAnyStateBits(NS_FRAME_FONT_INFLATION_CONTAINER);
   4827  }
   4828 
   4829  /**
   4830   * Return whether this frame or any of its children is dirty.
   4831   */
   4832  bool IsSubtreeDirty() const {
   4833    return HasAnyStateBits(NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN);
   4834  }
   4835 
   4836  /**
   4837   * Returns true if the frame is an SVGTextFrame or one of its descendants.
   4838   */
   4839  bool IsInSVGTextSubtree() const {
   4840    return HasAnyStateBits(NS_FRAME_IS_SVG_TEXT);
   4841  }
   4842 
   4843  /**
   4844   * Return whether this frame keeps track of overflow areas. (Frames for
   4845   * non-display SVG elements -- e.g. <clipPath> -- do not maintain overflow
   4846   * areas, because they're never painted.)
   4847   */
   4848  bool FrameMaintainsOverflow() const {
   4849    return !HasAllStateBits(NS_FRAME_SVG_LAYOUT | NS_FRAME_IS_NONDISPLAY) &&
   4850           !(IsSVGOuterSVGFrame() && HasAnyStateBits(NS_FRAME_IS_NONDISPLAY));
   4851  }
   4852 
   4853  /*
   4854   * @param aStyleDisplay:  If the caller has this->StyleDisplay(), providing
   4855   *   it here will improve performance.
   4856   */
   4857  bool BackfaceIsHidden(const nsStyleDisplay* aStyleDisplay) const {
   4858    MOZ_ASSERT(aStyleDisplay == StyleDisplay());
   4859    return aStyleDisplay->BackfaceIsHidden();
   4860  }
   4861  bool BackfaceIsHidden() const { return StyleDisplay()->BackfaceIsHidden(); }
   4862 
   4863  /**
   4864   * Returns true if the frame is scrolled out of view.
   4865   */
   4866  bool IsScrolledOutOfView() const;
   4867 
   4868  /**
   4869   * Computes a 2D matrix from the -moz-window-transform property on aFrame.
   4870   * Values that don't result in a 2D matrix will be ignored and an identity
   4871   * matrix will be returned instead.
   4872   */
   4873  Matrix ComputeWidgetTransform() const;
   4874 
   4875  /**
   4876   * @return true iff this frame has one or more associated image requests.
   4877   * @see mozilla::css::ImageLoader.
   4878   */
   4879  bool HasImageRequest() const { return mHasImageRequest; }
   4880 
   4881  /**
   4882   * Update this frame's image request state.
   4883   */
   4884  void SetHasImageRequest(bool aHasRequest) { mHasImageRequest = aHasRequest; }
   4885 
   4886  /**
   4887   * Whether this frame has a first-letter child.  If it does, the frame is
   4888   * actually an nsContainerFrame and the first-letter frame can be gotten by
   4889   * walking up to the nearest ancestor blockframe and getting its first
   4890   * continuation's nsContainerFrame::FirstLetterProperty() property.  This will
   4891   * only return true for the first continuation of the first-letter's parent.
   4892   */
   4893  bool HasFirstLetterChild() const { return mHasFirstLetterChild; }
   4894 
   4895  /**
   4896   * Whether this frame's parent is a wrapper anonymous box.  See documentation
   4897   * for mParentIsWrapperAnonBox.
   4898   */
   4899  bool ParentIsWrapperAnonBox() const { return mParentIsWrapperAnonBox; }
   4900  void SetParentIsWrapperAnonBox() { mParentIsWrapperAnonBox = true; }
   4901 
   4902  /**
   4903   * Whether this is a wrapper anonymous box needing a restyle.
   4904   */
   4905  bool IsWrapperAnonBoxNeedingRestyle() const {
   4906    return mIsWrapperBoxNeedingRestyle;
   4907  }
   4908  void SetIsWrapperAnonBoxNeedingRestyle(bool aNeedsRestyle) {
   4909    mIsWrapperBoxNeedingRestyle = aNeedsRestyle;
   4910  }
   4911 
   4912  bool MayHaveTransformAnimation() const { return mMayHaveTransformAnimation; }
   4913  void SetMayHaveTransformAnimation() {
   4914    AddStateBits(NS_FRAME_MAY_BE_TRANSFORMED);
   4915    mMayHaveTransformAnimation = true;
   4916  }
   4917  bool MayHaveOpacityAnimation() const { return mMayHaveOpacityAnimation; }
   4918  void SetMayHaveOpacityAnimation() { mMayHaveOpacityAnimation = true; }
   4919 
   4920  // Returns true if this frame is visible or may have visible descendants.
   4921  // Note: This function is accurate only on primary frames, because
   4922  // mAllDescendantsAreInvisible is not updated on continuations.
   4923  bool IsVisibleOrMayHaveVisibleDescendants() const {
   4924    return !mAllDescendantsAreInvisible || StyleVisibility()->IsVisible();
   4925  }
   4926  // Update mAllDescendantsAreInvisible flag for this frame and ancestors.
   4927  void UpdateVisibleDescendantsState();
   4928 
   4929  /**
   4930   * If this returns true, the frame it's called on should get the
   4931   * NS_FRAME_HAS_DIRTY_CHILDREN bit set on it by the caller; either directly
   4932   * if it's already in reflow, or via calling FrameNeedsReflow() to schedule a
   4933   * reflow.
   4934   */
   4935  virtual bool RenumberFrameAndDescendants(int32_t* aOrdinal, int32_t aDepth,
   4936                                           int32_t aIncrement,
   4937                                           bool aForCounting) {
   4938    return false;
   4939  }
   4940 
   4941  enum class ExtremumLength {
   4942    MinContent,
   4943    MaxContent,
   4944    MozAvailable,
   4945    Stretch,
   4946    FitContent,
   4947    FitContentFunction,
   4948  };
   4949 
   4950  template <typename SizeOrMaxSize>
   4951  static Maybe<ExtremumLength> ToExtremumLength(const SizeOrMaxSize& aSize) {
   4952    switch (aSize.tag) {
   4953      case SizeOrMaxSize::Tag::MinContent:
   4954        return mozilla::Some(ExtremumLength::MinContent);
   4955      case SizeOrMaxSize::Tag::MaxContent:
   4956        return mozilla::Some(ExtremumLength::MaxContent);
   4957      case SizeOrMaxSize::Tag::MozAvailable:
   4958        return mozilla::Some(ExtremumLength::MozAvailable);
   4959      case SizeOrMaxSize::Tag::WebkitFillAvailable:
   4960      case SizeOrMaxSize::Tag::Stretch:
   4961        return mozilla::Some(ExtremumLength::Stretch);
   4962      case SizeOrMaxSize::Tag::FitContent:
   4963        return mozilla::Some(ExtremumLength::FitContent);
   4964      case SizeOrMaxSize::Tag::FitContentFunction:
   4965        return mozilla::Some(ExtremumLength::FitContentFunction);
   4966      default:
   4967        return mozilla::Nothing();
   4968    }
   4969  }
   4970 
   4971  /**
   4972   * Helper function - computes the content-box inline size for aSize, which is
   4973   * a more complex version to resolve a StyleExtremumLength.
   4974   *
   4975   * @param aAvailableISizeOverride If this has a value, it is used as the
   4976   * available inline-size instead of aCBSize.ISize(aWM) when resolving
   4977   * fit-content.
   4978   */
   4979  struct ISizeComputationResult {
   4980    nscoord mISize = 0;
   4981    AspectRatioUsage mAspectRatioUsage = AspectRatioUsage::None;
   4982  };
   4983  ISizeComputationResult ComputeISizeValue(
   4984      gfxContext* aRenderingContext, const mozilla::WritingMode aWM,
   4985      const mozilla::LogicalSize& aCBSize,
   4986      const mozilla::LogicalSize& aContentEdgeToBoxSizing,
   4987      nscoord aBoxSizingToMarginEdge, ExtremumLength aSize,
   4988      Maybe<nscoord> aAvailableISizeOverride,
   4989      const mozilla::StyleSize& aStyleBSize,
   4990      const mozilla::AspectRatio& aAspectRatio,
   4991      mozilla::ComputeSizeFlags aFlags);
   4992 
   4993  /**
   4994   * Helper function - computes the content-box inline size for aSize, which is
   4995   * a simpler version to resolve a LengthPercentage.
   4996   */
   4997  nscoord ComputeISizeValue(const mozilla::WritingMode aWM,
   4998                            const mozilla::LogicalSize& aCBSize,
   4999                            const mozilla::LogicalSize& aContentEdgeToBoxSizing,
   5000                            const mozilla::LengthPercentage& aSize) const;
   5001 
   5002  /**
   5003   * Compute content-box inline size for aSize.
   5004   *
   5005   * This method doesn't handle 'auto' when aSize is of type StyleSize,
   5006   * nor does it handle 'none' when aSize is of type StyleMaxSize.
   5007   *
   5008   * @param aStyleBSize the style block size of the frame, used to compute
   5009   * intrinsic inline size with aAspectRatio.
   5010   *
   5011   * @param aAspectRatio the preferred aspect-ratio of the frame.
   5012   */
   5013  template <typename SizeOrMaxSize>
   5014  ISizeComputationResult ComputeISizeValue(
   5015      gfxContext* aRenderingContext, const mozilla::WritingMode aWM,
   5016      const mozilla::LogicalSize& aCBSize,
   5017      const mozilla::LogicalSize& aContentEdgeToBoxSizing,
   5018      nscoord aBoxSizingToMarginEdge, const SizeOrMaxSize& aSize,
   5019      const mozilla::StyleSize& aStyleBSize,
   5020      const mozilla::AspectRatio& aAspectRatio,
   5021      mozilla::ComputeSizeFlags aFlags = {}) {
   5022    if (aSize.IsLengthPercentage()) {
   5023      return {ComputeISizeValue(aWM, aCBSize, aContentEdgeToBoxSizing,
   5024                                aSize.AsLengthPercentage())};
   5025    }
   5026    auto length = ToExtremumLength(aSize);
   5027    MOZ_ASSERT(length, "This doesn't handle none / auto");
   5028    Maybe<nscoord> availbleISizeOverride;
   5029    if (aSize.IsFitContentFunction()) {
   5030      availbleISizeOverride.emplace(
   5031          aSize.AsFitContentFunction().Resolve(aCBSize.ISize(aWM)));
   5032    }
   5033    return ComputeISizeValue(
   5034        aRenderingContext, aWM, aCBSize, aContentEdgeToBoxSizing,
   5035        aBoxSizingToMarginEdge, length.valueOr(ExtremumLength::MinContent),
   5036        availbleISizeOverride, aStyleBSize, aAspectRatio, aFlags);
   5037  }
   5038 
   5039  DisplayItemArray& DisplayItems() { return mDisplayItems; }
   5040  const DisplayItemArray& DisplayItems() const { return mDisplayItems; }
   5041 
   5042  void AddDisplayItem(nsDisplayItem* aItem);
   5043  bool RemoveDisplayItem(nsDisplayItem* aItem);
   5044  void RemoveDisplayItemDataForDeletion();
   5045  bool HasDisplayItems();
   5046  bool HasDisplayItem(nsDisplayItem* aItem);
   5047  bool HasDisplayItem(uint32_t aKey);
   5048 
   5049  static void PrintDisplayList(nsDisplayListBuilder* aBuilder,
   5050                               const nsDisplayList& aList, uint32_t aIndent = 0,
   5051                               bool aDumpHtml = false);
   5052  static void PrintDisplayList(nsDisplayListBuilder* aBuilder,
   5053                               const nsDisplayList& aList,
   5054                               std::stringstream& aStream,
   5055                               bool aDumpHtml = false);
   5056  static void PrintDisplayItem(nsDisplayListBuilder* aBuilder,
   5057                               nsDisplayItem* aItem, std::stringstream& aStream,
   5058                               uint32_t aIndent = 0, bool aDumpSublist = false,
   5059                               bool aDumpHtml = false);
   5060 #ifdef MOZ_DUMP_PAINTING
   5061  static void PrintDisplayListSet(nsDisplayListBuilder* aBuilder,
   5062                                  const nsDisplayListSet& aSet,
   5063                                  std::stringstream& aStream,
   5064                                  bool aDumpHtml = false);
   5065 #endif
   5066 
   5067  /**
   5068   * Adds display items for standard CSS background if necessary.
   5069   * Does not check IsVisibleForPainting.
   5070   * @return whether a themed background item was created.
   5071   */
   5072  bool DisplayBackgroundUnconditional(nsDisplayListBuilder* aBuilder,
   5073                                      const nsDisplayListSet& aLists);
   5074  /**
   5075   * Adds display items for standard CSS borders, background and outline for
   5076   * for this frame, as necessary. Checks IsVisibleForPainting and won't
   5077   * display anything if the frame is not visible.
   5078   */
   5079  void DisplayBorderBackgroundOutline(nsDisplayListBuilder* aBuilder,
   5080                                      const nsDisplayListSet& aLists);
   5081  /**
   5082   * Add a display item for the CSS outline. Does not check visibility.
   5083   */
   5084  void DisplayOutlineUnconditional(nsDisplayListBuilder* aBuilder,
   5085                                   const nsDisplayListSet& aLists);
   5086  /**
   5087   * Add a display item for the CSS outline, after calling
   5088   * IsVisibleForPainting to confirm we are visible.
   5089   */
   5090  void DisplayOutline(nsDisplayListBuilder* aBuilder,
   5091                      const nsDisplayListSet& aLists);
   5092 
   5093  /**
   5094   * Add a display item for CSS inset box shadows. Does not check visibility.
   5095   */
   5096  void DisplayInsetBoxShadowUnconditional(nsDisplayListBuilder* aBuilder,
   5097                                          nsDisplayList* aList);
   5098 
   5099  /**
   5100   * Add a display item for CSS inset box shadow, after calling
   5101   * IsVisibleForPainting to confirm we are visible.
   5102   */
   5103  void DisplayInsetBoxShadow(nsDisplayListBuilder* aBuilder,
   5104                             nsDisplayList* aList);
   5105 
   5106  /**
   5107   * Add a display item for CSS outset box shadows. Does not check visibility.
   5108   */
   5109  void DisplayOutsetBoxShadowUnconditional(nsDisplayListBuilder* aBuilder,
   5110                                           nsDisplayList* aList);
   5111 
   5112  /**
   5113   * Add a display item for CSS outset box shadow, after calling
   5114   * IsVisibleForPainting to confirm we are visible.
   5115   */
   5116  void DisplayOutsetBoxShadow(nsDisplayListBuilder* aBuilder,
   5117                              nsDisplayList* aList);
   5118 
   5119  bool ForceDescendIntoIfVisible() const { return mForceDescendIntoIfVisible; }
   5120  void SetForceDescendIntoIfVisible(bool aForce) {
   5121    mForceDescendIntoIfVisible = aForce;
   5122  }
   5123 
   5124  bool BuiltDisplayList() const { return mBuiltDisplayList; }
   5125  void SetBuiltDisplayList(const bool aBuilt) { mBuiltDisplayList = aBuilt; }
   5126 
   5127  bool IsFrameModified() const { return mFrameIsModified; }
   5128  void SetFrameIsModified(const bool aFrameIsModified) {
   5129    mFrameIsModified = aFrameIsModified;
   5130  }
   5131 
   5132  bool HasModifiedDescendants() const { return mHasModifiedDescendants; }
   5133  void SetHasModifiedDescendants(const bool aHasModifiedDescendants) {
   5134    mHasModifiedDescendants = aHasModifiedDescendants;
   5135  }
   5136 
   5137  bool HasOverrideDirtyRegion() const { return mHasOverrideDirtyRegion; }
   5138  void SetHasOverrideDirtyRegion(const bool aHasDirtyRegion) {
   5139    mHasOverrideDirtyRegion = aHasDirtyRegion;
   5140  }
   5141 
   5142  bool MayHaveWillChangeBudget() const { return mMayHaveWillChangeBudget; }
   5143  void SetMayHaveWillChangeBudget(const bool aHasBudget) {
   5144    mMayHaveWillChangeBudget = aHasBudget;
   5145  }
   5146 
   5147  bool HasBSizeChange() const { return mHasBSizeChange; }
   5148  void SetHasBSizeChange(const bool aHasBSizeChange) {
   5149    mHasBSizeChange = aHasBSizeChange;
   5150  }
   5151 
   5152  bool HasPaddingChange() const { return mHasPaddingChange; }
   5153  void SetHasPaddingChange(const bool aHasPaddingChange) {
   5154    mHasPaddingChange = aHasPaddingChange;
   5155  }
   5156 
   5157  bool HasColumnSpanSiblings() const { return mHasColumnSpanSiblings; }
   5158  void SetHasColumnSpanSiblings(bool aHasColumnSpanSiblings) {
   5159    mHasColumnSpanSiblings = aHasColumnSpanSiblings;
   5160  }
   5161 
   5162  bool DescendantMayDependOnItsStaticPosition() const {
   5163    return mDescendantMayDependOnItsStaticPosition;
   5164  }
   5165  void SetDescendantMayDependOnItsStaticPosition(bool aValue) {
   5166    mDescendantMayDependOnItsStaticPosition = aValue;
   5167  }
   5168 
   5169  /**
   5170   * Returns the hit test area of the frame.
   5171   */
   5172  nsRect GetCompositorHitTestArea(nsDisplayListBuilder* aBuilder);
   5173 
   5174  /**
   5175   * Returns the set of flags indicating the properties of the frame that the
   5176   * compositor might care about for hit-testing purposes. Note that this
   5177   * function must be called during Gecko display list construction time (i.e
   5178   * while the frame tree is being traversed) because that is when the display
   5179   * list builder has the necessary state set up correctly.
   5180   */
   5181  mozilla::gfx::CompositorHitTestInfo GetCompositorHitTestInfo(
   5182      nsDisplayListBuilder* aBuilder);
   5183 
   5184  /**
   5185   * Similar to GetCompositorHitTestInfo but this function doesn't consider
   5186   * pointer-events style.
   5187   * This function should be used only for
   5188   * nsDisplayBuilder::SetInheritedCompositorHitTestInfo.
   5189   */
   5190  mozilla::gfx::CompositorHitTestInfo
   5191  GetCompositorHitTestInfoWithoutPointerEvents(nsDisplayListBuilder* aBuilder);
   5192 
   5193  /**
   5194   * Copies aWM to mWritingMode on 'this' and all its ancestors.
   5195   */
   5196  inline void PropagateWritingModeToSelfAndAncestors(mozilla::WritingMode aWM);
   5197 
   5198  /**
   5199   * Observes or unobserves the element with an internal ResizeObserver,
   5200   * depending on whether it needs to update its last remembered size.
   5201   * Also removes a previously stored last remembered size if the element
   5202   * can no longer have it.
   5203   * @see {@link https://drafts.csswg.org/css-sizing-4/#last-remembered}
   5204   */
   5205  void HandleLastRememberedSize();
   5206 
   5207 protected:
   5208  // Members
   5209  nsRect mRect;
   5210  nsCOMPtr<nsIContent> mContent;
   5211  RefPtr<ComputedStyle> mComputedStyle;
   5212 
   5213 private:
   5214  nsPresContext* const mPresContext;
   5215  nsContainerFrame* mParent;
   5216  nsIFrame* mNextSibling;  // doubly-linked list of frames
   5217  nsIFrame* mPrevSibling;  // Do not touch outside SetNextSibling!
   5218 
   5219  DisplayItemArray mDisplayItems;
   5220 
   5221  void MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder);
   5222 
   5223 protected:
   5224  void MarkInReflow() {
   5225 #ifdef DEBUG_dbaron_off
   5226    // bug 81268
   5227    NS_ASSERTION(!(mState & NS_FRAME_IN_REFLOW), "frame is already in reflow");
   5228 #endif
   5229    AddStateBits(NS_FRAME_IN_REFLOW);
   5230  }
   5231 
   5232 private:
   5233  nsFrameState mState;
   5234 
   5235 protected:
   5236  /**
   5237   * List of properties attached to the frame.
   5238   */
   5239  FrameProperties mProperties;
   5240 
   5241  // When there is no scrollable overflow area, and the ink overflow area only
   5242  // slightly larger than mRect, the ink overflow area may be stored a set of
   5243  // four 1-byte deltas from the edges of mRect rather than allocating a whole
   5244  // separate rectangle property. If all four deltas are zero, this means that
   5245  // no overflow area has actually been set (this is the initial state of
   5246  // newly-created frames).
   5247  //
   5248  // Note that these are unsigned values, all measured "outwards" from the edges
   5249  // of mRect, so mLeft and mTop are reversed from our normal coordinate system.
   5250  struct InkOverflowDeltas {
   5251    // The maximum delta value we can store in any of the four edges.
   5252    static constexpr uint8_t kMax = 0xfe;
   5253 
   5254    uint8_t mLeft;
   5255    uint8_t mTop;
   5256    uint8_t mRight;
   5257    uint8_t mBottom;
   5258    bool operator==(const InkOverflowDeltas& aOther) const = default;
   5259    bool operator!=(const InkOverflowDeltas& aOther) const = default;
   5260  };
   5261  enum class OverflowStorageType : uint32_t {
   5262    // No overflow area; code relies on this being an all-zero value.
   5263    None = 0x00000000u,
   5264 
   5265    // Ink overflow is too large to stored in InkOverflowDeltas.
   5266    Large = 0x000000ffu,
   5267  };
   5268  // If mOverflow.mType is OverflowStorageType::Large, then the delta values are
   5269  // not meaningful and the overflow area is stored in OverflowAreasProperty()
   5270  // instead.
   5271  union {
   5272    OverflowStorageType mType;
   5273    InkOverflowDeltas mInkOverflowDeltas;
   5274  } mOverflow;
   5275 
   5276  /** @see GetWritingMode() */
   5277  mozilla::WritingMode mWritingMode;
   5278 
   5279  /** The ClassID of the concrete class of this instance. */
   5280  const ClassID mClass;  // 1 byte
   5281 
   5282  bool mMayHaveRoundedCorners : 1;
   5283 
   5284  /**
   5285   * True iff this frame has one or more associated image requests.
   5286   * @see mozilla::css::ImageLoader.
   5287   */
   5288  bool mHasImageRequest : 1;
   5289 
   5290  /**
   5291   * True if this frame has a continuation that has a first-letter frame, or its
   5292   * placeholder, as a child.  In that case this frame has a blockframe ancestor
   5293   * that has the first-letter frame hanging off it in the
   5294   * nsContainerFrame::FirstLetterProperty() property.
   5295   */
   5296  bool mHasFirstLetterChild : 1;
   5297 
   5298  /**
   5299   * True if this frame's parent is a wrapper anonymous box (e.g. a table
   5300   * anonymous box as specified at
   5301   * <https://www.w3.org/TR/CSS21/tables.html#anonymous-boxes>).
   5302   *
   5303   * We could compute this information directly when we need it, but it wouldn't
   5304   * be all that cheap, and since this information is immutable for the lifetime
   5305   * of the frame we might as well cache it.
   5306   *
   5307   * Note that our parent may itself have mParentIsWrapperAnonBox set to true.
   5308   */
   5309  bool mParentIsWrapperAnonBox : 1;
   5310 
   5311  /**
   5312   * True if this is a wrapper anonymous box needing a restyle.  This is used to
   5313   * track, during stylo post-traversal, whether we've already recomputed the
   5314   * style of this anonymous box, if we end up seeing it twice.
   5315   */
   5316  bool mIsWrapperBoxNeedingRestyle : 1;
   5317 
   5318  /**
   5319   * This bit is used in nsTextFrame::CharacterDataChanged() as an optimization
   5320   * to skip redundant reflow-requests when the character data changes multiple
   5321   * times between reflows. If this flag is set, then it implies that the
   5322   * NS_FRAME_IS_DIRTY state bit is also set (and that intrinsic sizes have
   5323   * been marked as dirty on our ancestor chain).
   5324   *
   5325   * XXXdholbert This bit is *only* used on nsTextFrame, but it lives here on
   5326   * nsIFrame simply because this is where we've got unused state bits
   5327   * available in a gap. If bits become more scarce, we should perhaps consider
   5328   * expanding the range of frame-specific state bits in nsFrameStateBits.h and
   5329   * moving this to be one of those (e.g. by swapping one of the adjacent
   5330   * general-purpose bits to take the place of this bool:1 here, so we can grow
   5331   * that range of frame-specific bits by 1).
   5332   */
   5333  bool mReflowRequestedForCharDataChange : 1;
   5334 
   5335  /**
   5336   * This bit is used during BuildDisplayList to mark frames that need to
   5337   * have display items rebuilt. We will descend into them if they are
   5338   * currently visible, even if they don't intersect the dirty area.
   5339   */
   5340  bool mForceDescendIntoIfVisible : 1;
   5341 
   5342  /**
   5343   * True if we have built display items for this frame since
   5344   * the last call to CheckAndClearDisplayListState, false
   5345   * otherwise. Used for the reftest harness to verify minimal
   5346   * display list building.
   5347   */
   5348  bool mBuiltDisplayList : 1;
   5349 
   5350  /**
   5351   * True if the frame has been marked modified by
   5352   * |MarkNeedsDisplayItemRebuild()|, usually due to a style change or reflow.
   5353   */
   5354  bool mFrameIsModified : 1;
   5355 
   5356  /**
   5357   * True if the frame has modified descendants. Set before display list
   5358   * preprocessing and only used during partial display list builds.
   5359   */
   5360  bool mHasModifiedDescendants : 1;
   5361 
   5362  /**
   5363   * Used by merging based retained display lists to restrict the dirty area
   5364   * during partial display list builds.
   5365   */
   5366  bool mHasOverrideDirtyRegion : 1;
   5367 
   5368  /**
   5369   * True if frame has will-change, and currently has display
   5370   * items consuming some of the will-change budget.
   5371   */
   5372  bool mMayHaveWillChangeBudget : 1;
   5373 
   5374 #ifdef DEBUG
   5375 public:
   5376  /**
   5377   * True if this frame has already been been visited by
   5378   * nsCSSFrameConstructor::AutoFrameConstructionPageName.
   5379   *
   5380   * This is used to assert that we have visited each frame only once, and is
   5381   * not useful otherwise.
   5382   */
   5383  bool mWasVisitedByAutoFrameConstructionPageName : 1;
   5384 #endif
   5385 
   5386 private:
   5387  /**
   5388   * True if this is the primary frame for mContent.
   5389   */
   5390  bool mIsPrimaryFrame : 1;
   5391 
   5392  bool mMayHaveTransformAnimation : 1;
   5393  bool mMayHaveOpacityAnimation : 1;
   5394 
   5395  /**
   5396   * True if we are certain that all descendants are not visible.
   5397   *
   5398   * This flag is conservative in that it might sometimes be false even if, in
   5399   * fact, all descendants are invisible.
   5400   * For example; an element is visibility:visible and has a visibility:hidden
   5401   * child. This flag is stil false in such case.
   5402   */
   5403  bool mAllDescendantsAreInvisible : 1;
   5404 
   5405  bool mHasBSizeChange : 1;
   5406 
   5407  /**
   5408   * True if the frame seems to be in the process of being reflowed with a
   5409   * different amount of inline-axis padding as compared to its most recent
   5410   * reflow. This flag's purpose is to detect cases where the frame's
   5411   * inline-axis content-box-size has changed, without any style change or any
   5412   * change to the border-box size, so that we can mark/invalidate things
   5413   * appropriately in ReflowInput::InitResizeFlags().
   5414   *
   5415   * This flag is set in SizeComputationResult::InitOffsets() and cleared in
   5416   * nsIFrame::DidReflow().
   5417   */
   5418  bool mHasPaddingChange : 1;
   5419 
   5420  /**
   5421   * True if we are or contain the scroll anchor for a scrollable frame.
   5422   */
   5423  bool mInScrollAnchorChain : 1;
   5424 
   5425  /**
   5426   * Suppose a frame was split into multiple parts to separate parts containing
   5427   * column-spans from parts not containing column-spans. This bit is set on all
   5428   * continuations *not* containing column-spans except for the those after the
   5429   * last column-span/non-column-span boundary (i.e., the bit really means it
   5430   * has a *later* sibling across a split). Note that the last part is always
   5431   * created to containing no columns-spans even if it has no children. See
   5432   * nsCSSFrameConstructor::CreateColumnSpanSiblings() for the implementation.
   5433   *
   5434   * If the frame having this bit set is removed, we need to reframe the
   5435   * multi-column container.
   5436   */
   5437  bool mHasColumnSpanSiblings : 1;
   5438 
   5439  /**
   5440   * True if we may have any descendant whose positioning may depend on its
   5441   * static position (and thus which we need to recompute the position for if we
   5442   * move).
   5443   */
   5444  bool mDescendantMayDependOnItsStaticPosition : 1;
   5445 
   5446 protected:
   5447  // Helpers
   5448  /**
   5449   * Can we stop inside this frame when we're skipping non-rendered whitespace?
   5450   *
   5451   * @param aForward [in] Are we moving forward (or backward) in content order.
   5452   *
   5453   * @param aOffset [in/out] At what offset into the frame to start looking.
   5454   * at offset was reached (whether or not we found a place to stop).
   5455   *
   5456   * @return
   5457   *   * STOP: An appropriate offset was found within this frame,
   5458   *     and is given by aOffset.
   5459   *   * CONTINUE: Not found within this frame, need to try the next frame.
   5460   *     See enum FrameSearchResult for more details.
   5461   */
   5462  virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset);
   5463 
   5464  /**
   5465   * Search the frame for the next character
   5466   *
   5467   * @param aForward [in] Are we moving forward (or backward) in content order.
   5468   *
   5469   * @param aOffset [in/out] At what offset into the frame to start looking.
   5470   * on output - what offset was reached (whether or not we found a place to
   5471   * stop).
   5472   *
   5473   * @param aOptions [in] Options, see the comment in PeekOffsetCharacterOptions
   5474   * for the detail.
   5475   *
   5476   * @return
   5477   *   * STOP: An appropriate offset was found within this frame, and is given
   5478   *     by aOffset.
   5479   *   * CONTINUE: Not found within this frame, need to try the next frame. See
   5480   *     enum FrameSearchResult for more details.
   5481   */
   5482  virtual FrameSearchResult PeekOffsetCharacter(
   5483      bool aForward, int32_t* aOffset,
   5484      PeekOffsetCharacterOptions aOptions = PeekOffsetCharacterOptions());
   5485  static_assert(sizeof(PeekOffsetCharacterOptions) <= sizeof(intptr_t),
   5486                "aOptions should be changed to const reference");
   5487 
   5488  struct PeekWordState {
   5489    using Script = mozilla::intl::Script;
   5490    // true when we're still at the start of the search, i.e., we can't return
   5491    // this point as a valid offset!
   5492    bool mAtStart = true;
   5493    // true when we've encountered at least one character of the type before the
   5494    // boundary we're looking for:
   5495    // 1. If we're moving forward and eating whitepace, looking for a word
   5496    //    beginning (i.e. a boundary between whitespace and non-whitespace),
   5497    //    then mSawBeforeType==true means "we already saw some whitespace".
   5498    // 2. Otherwise, looking for a word beginning (i.e. a boundary between
   5499    //    non-whitespace and whitespace), then mSawBeforeType==true means "we
   5500    //    already saw some non-whitespace".
   5501    bool mSawBeforeType = false;
   5502    // true when we've encountered at least one non-newline character
   5503    bool mSawInlineCharacter = false;
   5504    // true when the last character encountered was punctuation
   5505    bool mLastCharWasPunctuation = false;
   5506    // true when the last character encountered was whitespace
   5507    bool mLastCharWasWhitespace = false;
   5508    // true when we've seen non-punctuation since the last whitespace
   5509    bool mSeenNonPunctuationSinceWhitespace = false;
   5510    // Script code of most recent character (other than INHERITED).
   5511    // (Currently only HANGUL vs any-other-script is significant.)
   5512    Script mLastScript = Script::INVALID;
   5513    // text that's *before* the current frame when aForward is true, *after*
   5514    // the current frame when aForward is false. Only includes the text
   5515    // on the current line.
   5516    nsAutoString mContext;
   5517 
   5518    PeekWordState() {}
   5519    void SetSawBeforeType() { mSawBeforeType = true; }
   5520    void SetSawInlineCharacter() { mSawInlineCharacter = true; }
   5521    void Update(bool aAfterPunctuation, bool aAfterWhitespace,
   5522                Script aScript = Script::INVALID) {
   5523      mLastCharWasPunctuation = aAfterPunctuation;
   5524      mLastCharWasWhitespace = aAfterWhitespace;
   5525      if (aAfterWhitespace) {
   5526        mSeenNonPunctuationSinceWhitespace = false;
   5527      } else if (!aAfterPunctuation) {
   5528        mSeenNonPunctuationSinceWhitespace = true;
   5529      }
   5530      if (aScript != Script::INHERITED) {
   5531        mLastScript = aScript;
   5532      }
   5533      mAtStart = false;
   5534    }
   5535  };
   5536 
   5537  /**
   5538   * Search the frame for the next word boundary
   5539   * @param  aForward [in] Are we moving forward (or backward) in content order.
   5540   * @param  aWordSelectEatSpace [in] true: look for non-whitespace following
   5541   *         whitespace (in the direction of movement).
   5542   *         false: look for whitespace following non-whitespace (in the
   5543   *         direction  of movement).
   5544   * @param  aIsKeyboardSelect [in] Was the action initiated by a keyboard
   5545   * operation? If true, punctuation immediately following a word is considered
   5546   * part of that word. Otherwise, a sequence of punctuation is always
   5547   * considered as a word on its own.
   5548   * @param  aOffset [in/out] At what offset into the frame to start looking.
   5549   *         on output - what offset was reached (whether or not we found a
   5550   * place to stop).
   5551   * @param  aState [in/out] the state that is carried from frame to frame
   5552   */
   5553  virtual FrameSearchResult PeekOffsetWord(
   5554      bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
   5555      int32_t* aOffset, PeekWordState* aState, bool aTrimSpaces);
   5556 
   5557 protected:
   5558  /**
   5559   * Check whether we should break at a boundary between punctuation and
   5560   * non-punctuation. Only call it at a punctuation boundary
   5561   * (i.e. exactly one of the previous and next characters are punctuation).
   5562   * @param aForward true if we're moving forward in content order
   5563   * @param aPunctAfter true if the next character is punctuation
   5564   * @param aWhitespaceAfter true if the next character is whitespace
   5565   */
   5566  static bool BreakWordBetweenPunctuation(const PeekWordState* aState,
   5567                                          bool aForward, bool aPunctAfter,
   5568                                          bool aWhitespaceAfter,
   5569                                          bool aIsKeyboardSelect);
   5570 
   5571 private:
   5572  nsRect GetOverflowRect(mozilla::OverflowType aType) const;
   5573 
   5574  // Get a pointer to the overflow areas property attached to the frame.
   5575  mozilla::OverflowAreas* GetOverflowAreasProperty() const {
   5576    MOZ_ASSERT(mOverflow.mType == OverflowStorageType::Large);
   5577    mozilla::OverflowAreas* overflow = GetProperty(OverflowAreasProperty());
   5578    MOZ_ASSERT(overflow);
   5579    return overflow;
   5580  }
   5581 
   5582  nsRect InkOverflowFromDeltas() const {
   5583    MOZ_ASSERT(mOverflow.mType != OverflowStorageType::Large,
   5584               "should not be called when overflow is in a property");
   5585    // Calculate the rect using deltas from the frame's border rect.
   5586    // Note that the mOverflow.mInkOverflowDeltas fields are unsigned, but we
   5587    // will often need to return negative values for the left and top, so take
   5588    // care to cast away the unsigned-ness.
   5589    return nsRect(-(int32_t)mOverflow.mInkOverflowDeltas.mLeft,
   5590                  -(int32_t)mOverflow.mInkOverflowDeltas.mTop,
   5591                  mRect.Width() + mOverflow.mInkOverflowDeltas.mRight +
   5592                      mOverflow.mInkOverflowDeltas.mLeft,
   5593                  mRect.Height() + mOverflow.mInkOverflowDeltas.mBottom +
   5594                      mOverflow.mInkOverflowDeltas.mTop);
   5595  }
   5596 
   5597  /**
   5598   * Set the OverflowArea rect, storing it as deltas or a separate rect
   5599   * depending on its size in relation to the primary frame rect.
   5600   *
   5601   * @return true if any overflow changed.
   5602   */
   5603  bool SetOverflowAreas(const mozilla::OverflowAreas& aOverflowAreas);
   5604 
   5605  bool HasOpacityInternal(float aThreshold, const nsStyleDisplay* aStyleDisplay,
   5606                          const nsStyleEffects* aStyleEffects,
   5607                          mozilla::EffectSet* aEffectSet = nullptr) const;
   5608 
   5609  static constexpr size_t kFrameClassCount =
   5610 #define FRAME_ID(...) 1 +
   5611 #define ABSTRACT_FRAME_ID(...)
   5612 #include "mozilla/FrameIdList.h"
   5613 #undef FRAME_ID
   5614 #undef ABSTRACT_FRAME_ID
   5615      0;
   5616 
   5617  // Maps mClass to LayoutFrameType.
   5618  static const mozilla::LayoutFrameType sLayoutFrameTypes[kFrameClassCount];
   5619  // Maps mClass to LayoutFrameTypeFlags.
   5620  static const ClassFlags sLayoutFrameClassFlags[kFrameClassCount];
   5621 
   5622 #ifdef DEBUG_FRAME_DUMP
   5623 public:
   5624  static void IndentBy(FILE* out, int32_t aIndent) {
   5625    while (--aIndent >= 0) {
   5626      fputs("  ", out);
   5627    }
   5628  }
   5629  void ListTag(FILE* out) const { fputs(ListTag().get(), out); }
   5630  nsAutoCString ListTag(bool aListOnlyDeterministic = false) const;
   5631 
   5632  enum class ListFlag {
   5633    TraverseSubdocumentFrames,
   5634    DisplayInCSSPixels,
   5635    OnlyListDeterministicInfo
   5636  };
   5637  using ListFlags = mozilla::EnumSet<ListFlag>;
   5638 
   5639  template <typename T>
   5640  static std::string ConvertToString(const T& aValue, ListFlags aFlags) {
   5641    // This method can convert all physical types in app units to CSS pixels.
   5642    return aFlags.contains(ListFlag::DisplayInCSSPixels)
   5643               ? mozilla::ToString(mozilla::CSSPixel::FromAppUnits(aValue))
   5644               : mozilla::ToString(aValue);
   5645  }
   5646  static std::string ConvertToString(const mozilla::LogicalRect& aRect,
   5647                                     const mozilla::WritingMode aWM,
   5648                                     ListFlags aFlags);
   5649  static std::string ConvertToString(const mozilla::LogicalSize& aSize,
   5650                                     const mozilla::WritingMode aWM,
   5651                                     ListFlags aFlags);
   5652 
   5653  template <typename T>
   5654  static void ListPtr(nsACString& aTo, const ListFlags& aFlags, const T* aPtr,
   5655                      const char* aPrefix = "=") {
   5656    ListPtr(aTo, aFlags.contains(ListFlag::OnlyListDeterministicInfo), aPtr,
   5657            aPrefix);
   5658  }
   5659 
   5660  template <typename T>
   5661  static void ListPtr(nsACString& aTo, bool aSkip, const T* aPtr,
   5662                      const char* aPrefix = "=") {
   5663    if (aSkip) {
   5664      return;
   5665    }
   5666    aTo += nsPrintfCString("%s%p", aPrefix, static_cast<const void*>(aPtr));
   5667  }
   5668 
   5669  void ListGeneric(nsACString& aTo, const char* aPrefix = "",
   5670                   ListFlags aFlags = ListFlags()) const;
   5671  virtual void List(FILE* out = stderr, const char* aPrefix = "",
   5672                    ListFlags aFlags = ListFlags()) const;
   5673 
   5674  void ListTextRuns(FILE* out = stderr) const;
   5675  virtual void ListTextRuns(FILE* out, nsTHashSet<const void*>& aSeen) const;
   5676 
   5677  virtual void ListWithMatchedRules(FILE* out = stderr,
   5678                                    const char* aPrefix = "") const;
   5679  void ListMatchedRules(FILE* out, const char* aPrefix) const;
   5680 
   5681  /**
   5682   * Dump the frame tree beginning from the root frame.
   5683   */
   5684  void DumpFrameTree() const;
   5685  void DumpFrameTree(bool aListOnlyDeterministic) const;
   5686  void DumpFrameTreeInCSSPixels() const;
   5687  void DumpFrameTreeInCSSPixels(bool aListOnlyDeterministic) const;
   5688 
   5689  /**
   5690   * Dump the frame tree beginning from ourselves.
   5691   */
   5692  void DumpFrameTreeLimited() const;
   5693  void DumpFrameTreeLimitedInCSSPixels() const;
   5694 
   5695  /**
   5696   * Get a printable from of the name of the frame type.
   5697   * XXX This should be eliminated and we use GetType() instead...
   5698   */
   5699  virtual nsresult GetFrameName(nsAString& aResult) const;
   5700  nsresult MakeFrameName(const nsAString& aType, nsAString& aResult) const;
   5701  // Helper function to return the index in parent of the frame's content
   5702  // object. Returns Nothing on error or if the frame doesn't have a content
   5703  // object
   5704  static mozilla::Maybe<uint32_t> ContentIndexInContainer(
   5705      const nsIFrame* aFrame);
   5706 #endif
   5707 
   5708 #ifdef DEBUG
   5709  /**
   5710   * Tracing method that writes a method enter/exit routine to the
   5711   * nspr log using the nsIFrame log module. The tracing is only
   5712   * done when the NS_FRAME_TRACE_CALLS bit is set in the log module's
   5713   * level field.
   5714   */
   5715  void Trace(const char* aMethod, bool aEnter);
   5716  void Trace(const char* aMethod, bool aEnter, const nsReflowStatus& aStatus);
   5717  void TraceMsg(const char* aFormatString, ...) MOZ_FORMAT_PRINTF(2, 3);
   5718 
   5719  // Helper function that verifies that each frame in the list has the
   5720  // NS_FRAME_IS_DIRTY bit set
   5721  static void VerifyDirtyBitSet(const nsFrameList& aFrameList);
   5722 
   5723  static mozilla::LazyLogModule sFrameLogModule;
   5724 #endif
   5725 };
   5726 
   5727 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsIFrame::ReflowChildFlags)
   5728 
   5729 //----------------------------------------------------------------------
   5730 
   5731 /**
   5732 * AutoWeakFrame can be used to keep a reference to a nsIFrame in a safe way.
   5733 * Whenever an nsIFrame object is deleted, the AutoWeakFrames pointing
   5734 * to it will be cleared.  AutoWeakFrame is for variables on the stack or
   5735 * in static storage only, there is also a WeakFrame below for heap uses.
   5736 *
   5737 * Create AutoWeakFrame object when it is sure that nsIFrame object
   5738 * is alive and after some operations which may destroy the nsIFrame
   5739 * (for example any DOM modifications) use IsAlive() or GetFrame() methods to
   5740 * check whether it is safe to continue to use the nsIFrame object.
   5741 *
   5742 * @note The usage of this class should be kept to a minimum.
   5743 */
   5744 class WeakFrame;
   5745 class MOZ_NONHEAP_CLASS AutoWeakFrame {
   5746 public:
   5747  explicit constexpr AutoWeakFrame() : mPrev(nullptr), mFrame(nullptr) {}
   5748 
   5749  AutoWeakFrame(const AutoWeakFrame& aOther) : mPrev(nullptr), mFrame(nullptr) {
   5750    Init(aOther.GetFrame());
   5751  }
   5752 
   5753  MOZ_IMPLICIT AutoWeakFrame(const WeakFrame& aOther);
   5754 
   5755  MOZ_IMPLICIT AutoWeakFrame(nsIFrame* aFrame)
   5756      : mPrev(nullptr), mFrame(nullptr) {
   5757    Init(aFrame);
   5758  }
   5759 
   5760  AutoWeakFrame& operator=(AutoWeakFrame& aOther) {
   5761    Init(aOther.GetFrame());
   5762    return *this;
   5763  }
   5764 
   5765  AutoWeakFrame& operator=(nsIFrame* aFrame) {
   5766    Init(aFrame);
   5767    return *this;
   5768  }
   5769 
   5770  nsIFrame* operator->() { return mFrame; }
   5771 
   5772  operator nsIFrame*() { return mFrame; }
   5773 
   5774  void Clear(mozilla::PresShell* aPresShell);
   5775 
   5776  bool IsAlive() const { return !!mFrame; }
   5777 
   5778  nsIFrame* GetFrame() const { return mFrame; }
   5779 
   5780  AutoWeakFrame* GetPreviousWeakFrame() { return mPrev; }
   5781 
   5782  void SetPreviousWeakFrame(AutoWeakFrame* aPrev) { mPrev = aPrev; }
   5783 
   5784  ~AutoWeakFrame();
   5785 
   5786 private:
   5787  // Not available for the heap!
   5788  void* operator new(size_t) = delete;
   5789  void* operator new[](size_t) = delete;
   5790  void operator delete(void*) = delete;
   5791  void operator delete[](void*) = delete;
   5792 
   5793  void Init(nsIFrame* aFrame);
   5794 
   5795  AutoWeakFrame* mPrev;
   5796  nsIFrame* mFrame;
   5797 };
   5798 
   5799 // Use nsIFrame's fast-path to avoid QueryFrame:
   5800 inline do_QueryFrameHelper<nsIFrame> do_QueryFrame(AutoWeakFrame& s) {
   5801  return do_QueryFrameHelper<nsIFrame>(s.GetFrame());
   5802 }
   5803 
   5804 /**
   5805 * @see AutoWeakFrame
   5806 */
   5807 class MOZ_HEAP_CLASS WeakFrame {
   5808 public:
   5809  WeakFrame() : mFrame(nullptr) {}
   5810 
   5811  WeakFrame(const WeakFrame& aOther) : mFrame(nullptr) {
   5812    Init(aOther.GetFrame());
   5813  }
   5814 
   5815  MOZ_IMPLICIT WeakFrame(const AutoWeakFrame& aOther) : mFrame(nullptr) {
   5816    Init(aOther.GetFrame());
   5817  }
   5818 
   5819  MOZ_IMPLICIT WeakFrame(nsIFrame* aFrame) : mFrame(nullptr) { Init(aFrame); }
   5820 
   5821  ~WeakFrame() {
   5822    Clear(mFrame ? mFrame->PresContext()->GetPresShell() : nullptr);
   5823  }
   5824 
   5825  WeakFrame& operator=(WeakFrame& aOther) {
   5826    Init(aOther.GetFrame());
   5827    return *this;
   5828  }
   5829 
   5830  WeakFrame& operator=(nsIFrame* aFrame) {
   5831    Init(aFrame);
   5832    return *this;
   5833  }
   5834 
   5835  nsIFrame* operator->() { return mFrame; }
   5836  operator nsIFrame*() { return mFrame; }
   5837 
   5838  bool operator==(nsIFrame* const aOther) const { return mFrame == aOther; }
   5839 
   5840  void Clear(mozilla::PresShell* aPresShell);
   5841 
   5842  bool IsAlive() const { return !!mFrame; }
   5843  nsIFrame* GetFrame() const { return mFrame; }
   5844 
   5845 private:
   5846  void Init(nsIFrame* aFrame);
   5847 
   5848  nsIFrame* mFrame;
   5849 };
   5850 
   5851 // Use nsIFrame's fast-path to avoid QueryFrame:
   5852 inline do_QueryFrameHelper<nsIFrame> do_QueryFrame(WeakFrame& s) {
   5853  return do_QueryFrameHelper<nsIFrame>(s.GetFrame());
   5854 }
   5855 
   5856 inline bool nsFrameList::ContinueRemoveFrame(nsIFrame* aFrame) {
   5857  MOZ_ASSERT(!aFrame->GetPrevSibling() || !aFrame->GetNextSibling(),
   5858             "Forgot to call StartRemoveFrame?");
   5859  if (aFrame == mLastChild) {
   5860    MOZ_ASSERT(!aFrame->GetNextSibling(), "broken frame list");
   5861    nsIFrame* prevSibling = aFrame->GetPrevSibling();
   5862    if (!prevSibling) {
   5863      MOZ_ASSERT(aFrame == mFirstChild, "broken frame list");
   5864      mFirstChild = mLastChild = nullptr;
   5865      return true;
   5866    }
   5867    MOZ_ASSERT(prevSibling->GetNextSibling() == aFrame, "Broken frame linkage");
   5868    prevSibling->SetNextSibling(nullptr);
   5869    mLastChild = prevSibling;
   5870    return true;
   5871  }
   5872  if (aFrame == mFirstChild) {
   5873    MOZ_ASSERT(!aFrame->GetPrevSibling(), "broken frame list");
   5874    mFirstChild = aFrame->GetNextSibling();
   5875    aFrame->SetNextSibling(nullptr);
   5876    MOZ_ASSERT(mFirstChild, "broken frame list");
   5877    return true;
   5878  }
   5879  return false;
   5880 }
   5881 
   5882 inline bool nsFrameList::StartRemoveFrame(nsIFrame* aFrame) {
   5883  if (aFrame->GetPrevSibling() && aFrame->GetNextSibling()) {
   5884    UnhookFrameFromSiblings(aFrame);
   5885    return true;
   5886  }
   5887  return ContinueRemoveFrame(aFrame);
   5888 }
   5889 
   5890 // Operators of nsFrameList::Iterator
   5891 // ---------------------------------------------------
   5892 
   5893 inline nsIFrame* nsFrameList::ForwardFrameTraversal::Next(nsIFrame* aFrame) {
   5894  MOZ_ASSERT(aFrame);
   5895  return aFrame->GetNextSibling();
   5896 }
   5897 inline nsIFrame* nsFrameList::ForwardFrameTraversal::Prev(nsIFrame* aFrame) {
   5898  MOZ_ASSERT(aFrame);
   5899  return aFrame->GetPrevSibling();
   5900 }
   5901 
   5902 inline nsIFrame* nsFrameList::BackwardFrameTraversal::Next(nsIFrame* aFrame) {
   5903  MOZ_ASSERT(aFrame);
   5904  return aFrame->GetPrevSibling();
   5905 }
   5906 inline nsIFrame* nsFrameList::BackwardFrameTraversal::Prev(nsIFrame* aFrame) {
   5907  MOZ_ASSERT(aFrame);
   5908  return aFrame->GetNextSibling();
   5909 }
   5910 
   5911 inline AnchorPosResolutionParams AnchorPosResolutionParams::From(
   5912    const nsIFrame* aFrame,
   5913    mozilla::AnchorPosResolutionCache* aAnchorPosResolutionCache) {
   5914  return {aFrame, aFrame->StyleDisplay()->mPosition, aAnchorPosResolutionCache,
   5915          AutoResolutionOverrideParams{aFrame, aAnchorPosResolutionCache}};
   5916 }
   5917 
   5918 #endif /* nsIFrame_h___ */