LCOV - code coverage report
Current view: top level - layout/generic - nsIFrame.h (source / functions) Hit Total Coverage
Test: output.info Lines: 433 733 59.1 %
Date: 2017-07-14 16:53:18 Functions: 231 463 49.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=2 sw=2 et tw=78: */
       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             : #define MAX_REFLOW_DEPTH 200
      17             : 
      18             : /* nsIFrame is in the process of being deCOMtaminated, i.e., this file is eventually
      19             :    going to be eliminated, and all callers will use nsFrame instead.  At the moment
      20             :    we're midway through this process, so you will see inlined functions and member
      21             :    variables in this file.  -dwh */
      22             : 
      23             : #include <algorithm>
      24             : #include <stdio.h>
      25             : 
      26             : #include "CaretAssociationHint.h"
      27             : #include "FrameProperties.h"
      28             : #include "mozilla/layout/FrameChildList.h"
      29             : #include "mozilla/Maybe.h"
      30             : #include "mozilla/SmallPointerArray.h"
      31             : #include "mozilla/WritingModes.h"
      32             : #include "nsDirection.h"
      33             : #include "nsFrameList.h"
      34             : #include "nsFrameState.h"
      35             : #include "mozilla/layers/WebRenderUserData.h"
      36             : #include "mozilla/ReflowOutput.h"
      37             : #include "nsITheme.h"
      38             : #include "nsLayoutUtils.h"
      39             : #include "nsQueryFrame.h"
      40             : #include "nsStringGlue.h"
      41             : #include "nsStyleContext.h"
      42             : #include "nsStyleStruct.h"
      43             : #include "Visibility.h"
      44             : #include "nsChangeHint.h"
      45             : #include "nsStyleContextInlines.h"
      46             : #include "mozilla/gfx/MatrixFwd.h"
      47             : 
      48             : #ifdef ACCESSIBILITY
      49             : #include "mozilla/a11y/AccTypes.h"
      50             : #endif
      51             : 
      52             : /**
      53             :  * New rules of reflow:
      54             :  * 1. you get a WillReflow() followed by a Reflow() followed by a DidReflow() in order
      55             :  *    (no separate pass over the tree)
      56             :  * 2. it's the parent frame's responsibility to size/position the child's view (not
      57             :  *    the child frame's responsibility as it is today) during reflow (and before
      58             :  *    sending the DidReflow() notification)
      59             :  * 3. positioning of child frames (and their views) is done on the way down the tree,
      60             :  *    and sizing of child frames (and their views) on the way back up
      61             :  * 4. if you move a frame (outside of the reflow process, or after reflowing it),
      62             :  *    then you must make sure that its view (or its child frame's views) are re-positioned
      63             :  *    as well. It's reasonable to not position the view until after all reflowing the
      64             :  *    entire line, for example, but the frame should still be positioned and sized (and
      65             :  *    the view sized) during the reflow (i.e., before sending the DidReflow() notification)
      66             :  * 5. the view system handles moving of widgets, i.e., it's not our problem
      67             :  */
      68             : 
      69             : class nsIAtom;
      70             : class nsPresContext;
      71             : class nsIPresShell;
      72             : class nsView;
      73             : class nsIWidget;
      74             : class nsISelectionController;
      75             : class nsBoxLayoutState;
      76             : class nsBoxLayout;
      77             : class nsILineIterator;
      78             : class nsDisplayListBuilder;
      79             : class nsDisplayListSet;
      80             : class nsDisplayList;
      81             : class gfxSkipChars;
      82             : class gfxSkipCharsIterator;
      83             : class gfxContext;
      84             : class nsLineList_iterator;
      85             : class nsAbsoluteContainingBlock;
      86             : class nsIContent;
      87             : class nsContainerFrame;
      88             : class nsPlaceholderFrame;
      89             : class nsStyleChangeList;
      90             : 
      91             : struct nsPeekOffsetStruct;
      92             : struct nsPoint;
      93             : struct nsRect;
      94             : struct nsSize;
      95             : struct nsMargin;
      96             : struct CharacterDataChangeInfo;
      97             : 
      98             : namespace mozilla {
      99             : 
     100             : enum class CSSPseudoElementType : uint8_t;
     101             : class EventStates;
     102             : struct ReflowInput;
     103             : class ReflowOutput;
     104             : class ServoRestyleState;
     105             : class DisplayItemData;
     106             : class EffectSet;
     107             : 
     108             : namespace layers {
     109             : class Layer;
     110             : } // namespace layers
     111             : 
     112             : } // namespace mozilla
     113             : 
     114             : /**
     115             :  * Indication of how the frame can be split. This is used when doing runaround
     116             :  * of floats, and when pulling up child frames from a next-in-flow.
     117             :  *
     118             :  * The choices are splittable, not splittable at all, and splittable in
     119             :  * a non-rectangular fashion. This last type only applies to block-level
     120             :  * elements, and indicates whether splitting can be used when doing runaround.
     121             :  * If you can split across page boundaries, but you expect each continuing
     122             :  * frame to be the same width then return frSplittable and not
     123             :  * frSplittableNonRectangular.
     124             :  *
     125             :  * @see #GetSplittableType()
     126             :  */
     127             : typedef uint32_t nsSplittableType;
     128             : 
     129             : #define NS_FRAME_NOT_SPLITTABLE             0   // Note: not a bit!
     130             : #define NS_FRAME_SPLITTABLE                 0x1
     131             : #define NS_FRAME_SPLITTABLE_NON_RECTANGULAR 0x3
     132             : 
     133             : #define NS_FRAME_IS_SPLITTABLE(type)\
     134             :   (0 != ((type) & NS_FRAME_SPLITTABLE))
     135             : 
     136             : #define NS_FRAME_IS_NOT_SPLITTABLE(type)\
     137             :   (0 == ((type) & NS_FRAME_SPLITTABLE))
     138             : 
     139             : #define NS_INTRINSIC_WIDTH_UNKNOWN nscoord_MIN
     140             : 
     141             : //----------------------------------------------------------------------
     142             : 
     143             : #define NS_SUBTREE_DIRTY(_frame)  \
     144             :   (((_frame)->GetStateBits() &      \
     145             :     (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN)) != 0)
     146             : 
     147             : /**
     148             :  * Constant used to indicate an unconstrained size.
     149             :  *
     150             :  * @see #Reflow()
     151             :  */
     152             : #define NS_UNCONSTRAINEDSIZE NS_MAXSIZE
     153             : 
     154             : #define NS_INTRINSICSIZE    NS_UNCONSTRAINEDSIZE
     155             : #define NS_AUTOHEIGHT       NS_UNCONSTRAINEDSIZE
     156             : // +1 is to avoid clamped huge margin values being processed as auto margins
     157             : #define NS_AUTOMARGIN       (NS_UNCONSTRAINEDSIZE + 1)
     158             : #define NS_AUTOOFFSET       NS_UNCONSTRAINEDSIZE
     159             : // NOTE: there are assumptions all over that these have the same value, namely NS_UNCONSTRAINEDSIZE
     160             : //       if any are changed to be a value other than NS_UNCONSTRAINEDSIZE
     161             : //       at least update AdjustComputedHeight/Width and test ad nauseum
     162             : 
     163             : // 1 million CSS pixels less than our max app unit measure.
     164             : // For reflowing with an "infinite" available inline space per [css-sizing].
     165             : // (reflowing with an NS_UNCONSTRAINEDSIZE available inline size isn't allowed
     166             : //  and leads to assertions)
     167             : #define INFINITE_ISIZE_COORD nscoord(NS_MAXSIZE - (1000000*60))
     168             : 
     169             : //----------------------------------------------------------------------
     170             : 
     171             : namespace mozilla {
     172             : 
     173             : enum class LayoutFrameType : uint8_t {
     174             : #define FRAME_TYPE(ty_) ty_,
     175             : #include "mozilla/FrameTypeList.h"
     176             : #undef FRAME_TYPE
     177             : };
     178             : 
     179             : } // namespace mozilla
     180             : 
     181             : enum nsSelectionAmount {
     182             :   eSelectCharacter = 0, // a single Unicode character;
     183             :                         // do not use this (prefer Cluster) unless you
     184             :                         // are really sure it's what you want
     185             :   eSelectCluster   = 1, // a grapheme cluster: this is usually the right
     186             :                         // choice for movement or selection by "character"
     187             :                         // as perceived by the user
     188             :   eSelectWord      = 2,
     189             :   eSelectWordNoSpace = 3, // select a "word" without selecting the following
     190             :                           // space, no matter what the default platform
     191             :                           // behavior is
     192             :   eSelectLine      = 4, // previous drawn line in flow.
     193             :   // NOTE that selection code depends on the ordering of the above values,
     194             :   // allowing simple <= tests to check categories of caret movement.
     195             :   // Don't rearrange without checking the usage in nsSelection.cpp!
     196             : 
     197             :   eSelectBeginLine = 5,
     198             :   eSelectEndLine   = 6,
     199             :   eSelectNoAmount  = 7, // just bounce back current offset.
     200             :   eSelectParagraph = 8  // select a "paragraph"
     201             : };
     202             : 
     203             : enum nsSpread {
     204             :   eSpreadNone   = 0,
     205             :   eSpreadAcross = 1,
     206             :   eSpreadDown   = 2
     207             : };
     208             : 
     209             : // Carried out margin flags
     210             : #define NS_CARRIED_TOP_MARGIN_IS_AUTO    0x1
     211             : #define NS_CARRIED_BOTTOM_MARGIN_IS_AUTO 0x2
     212             : 
     213             : //----------------------------------------------------------------------
     214             : // Reflow status returned by the Reflow() methods.
     215             : class nsReflowStatus final {
     216             :   using StyleClear = mozilla::StyleClear;
     217             : 
     218             : public:
     219         998 :   nsReflowStatus()
     220         998 :     : mBreakType(StyleClear::None)
     221             :     , mInlineBreak(InlineBreak::None)
     222             :     , mCompletion(Completion::FullyComplete)
     223             :     , mNextInFlowNeedsReflow(false)
     224             :     , mTruncated(false)
     225         998 :     , mFirstLetterComplete(false)
     226         998 :   {}
     227             : 
     228             :   // Reset all the member variables.
     229         645 :   void Reset() {
     230         645 :     mBreakType = StyleClear::None;
     231         645 :     mInlineBreak = InlineBreak::None;
     232         645 :     mCompletion = Completion::FullyComplete;
     233         645 :     mNextInFlowNeedsReflow = false;
     234         645 :     mTruncated = false;
     235         645 :     mFirstLetterComplete = false;
     236         645 :   }
     237             : 
     238             :   // Return true if all member variables have their default values.
     239          70 :   bool IsEmpty() const {
     240         140 :     return (IsFullyComplete() &&
     241         140 :             !IsInlineBreak() &&
     242         140 :             !mNextInFlowNeedsReflow &&
     243         210 :             !mTruncated &&
     244         140 :             !mFirstLetterComplete);
     245             :   }
     246             : 
     247             :   // There are three possible completion statuses, represented by
     248             :   // mCompletion.
     249             :   //
     250             :   // Incomplete means the frame does *not* map all its content, and the
     251             :   // parent frame should create a continuing frame.
     252             :   //
     253             :   // OverflowIncomplete means that the frame has an overflow that is not
     254             :   // complete, but its own box is complete. (This happens when the content
     255             :   // overflows a fixed-height box.) The reflower should place and size the
     256             :   // frame and continue its reflow, but it needs to create an overflow
     257             :   // container as a continuation for this frame. See "Overflow containers"
     258             :   // documentation in nsContainerFrame.h for more information.
     259             :   //
     260             :   // FullyComplete means the frame is neither Incomplete nor
     261             :   // OverflowIncomplete. This is the default state for a nsReflowStatus.
     262             :   //
     263             :   enum class Completion : uint8_t {
     264             :     // The order of the enum values is important, which represents the
     265             :     // precedence when merging.
     266             :     FullyComplete,
     267             :     OverflowIncomplete,
     268             :     Incomplete,
     269             :   };
     270             : 
     271         568 :   bool IsIncomplete() const { return mCompletion == Completion::Incomplete; }
     272           0 :   bool IsOverflowIncomplete() const {
     273           0 :     return mCompletion == Completion::OverflowIncomplete;
     274             :   }
     275         973 :   bool IsFullyComplete() const {
     276         973 :     return mCompletion == Completion::FullyComplete;
     277             :   }
     278             :   // Just for convenience; not a distinct state.
     279         426 :   bool IsComplete() const { return !IsIncomplete(); }
     280             : 
     281           0 :   void SetIncomplete() {
     282           0 :     mCompletion = Completion::Incomplete;
     283           0 :   }
     284           0 :   void SetOverflowIncomplete() {
     285           0 :     mCompletion = Completion::OverflowIncomplete;
     286           0 :   }
     287             : 
     288             :   // mNextInFlowNeedsReflow bit flag means that the next-in-flow is dirty,
     289             :   // and also needs to be reflowed. This status only makes sense for a frame
     290             :   // that is not complete, i.e. you wouldn't set mNextInFlowNeedsReflow when
     291             :   // IsComplete() is true.
     292          75 :   bool NextInFlowNeedsReflow() const { return mNextInFlowNeedsReflow; }
     293           0 :   void SetNextInFlowNeedsReflow() { mNextInFlowNeedsReflow = true; }
     294             : 
     295             :   // mTruncated bit flag means that the part of the frame before the first
     296             :   // possible break point was unable to fit in the available space.
     297             :   // Therefore, the entire frame should be moved to the next continuation of
     298             :   // the parent frame. A frame that begins at the top of the page must never
     299             :   // be truncated. Doing so would likely cause an infinite loop.
     300           0 :   bool IsTruncated() const { return mTruncated; }
     301             :   void UpdateTruncated(const mozilla::ReflowInput& aReflowInput,
     302             :                        const mozilla::ReflowOutput& aMetrics);
     303             : 
     304             :   // Merge the frame completion status bits from aStatus into this.
     305         347 :   void MergeCompletionStatusFrom(const nsReflowStatus& aStatus)
     306             :   {
     307         347 :     if (mCompletion < aStatus.mCompletion) {
     308           0 :       mCompletion = aStatus.mCompletion;
     309             :     }
     310             : 
     311             :     // These asserts ensure that the mCompletion merging works as we expect.
     312             :     // (Incomplete beats OverflowIncomplete, which beats FullyComplete.)
     313             :     static_assert(Completion::Incomplete > Completion::OverflowIncomplete &&
     314             :                   Completion::OverflowIncomplete > Completion::FullyComplete,
     315             :                   "mCompletion merging won't work without this!");
     316             : 
     317         347 :     mNextInFlowNeedsReflow |= aStatus.mNextInFlowNeedsReflow;
     318         347 :     mTruncated |= aStatus.mTruncated;
     319         347 :   }
     320             : 
     321             :   // There are three possible inline-break statuses, represented by
     322             :   // mInlineBreak.
     323             :   //
     324             :   // "None" means no break is requested.
     325             :   // "Before" means the break should occur before the frame.
     326             :   // "After" means the break should occur after the frame.
     327             :   // (Here, "the frame" is the frame whose reflow results are being reported by
     328             :   // this nsReflowStatus.)
     329             :   //
     330             :   enum class InlineBreak : uint8_t {
     331             :     None,
     332             :     Before,
     333             :     After,
     334             :   };
     335             : 
     336         145 :   bool IsInlineBreak() const { return mInlineBreak != InlineBreak::None; }
     337         436 :   bool IsInlineBreakBefore() const {
     338         436 :     return mInlineBreak == InlineBreak::Before;
     339             :   }
     340           9 :   bool IsInlineBreakAfter() const {
     341           9 :     return mInlineBreak == InlineBreak::After;
     342             :   }
     343           9 :   StyleClear BreakType() const { return mBreakType; }
     344             : 
     345             :   // Set the inline line-break-before status, and reset other bit flags. The
     346             :   // break type is StyleClear::Line. Note that other frame completion status
     347             :   // isn't expected to matter after calling this method.
     348           0 :   void SetInlineLineBreakBeforeAndReset() {
     349           0 :     Reset();
     350           0 :     mBreakType = StyleClear::Line;
     351           0 :     mInlineBreak = InlineBreak::Before;
     352           0 :   }
     353             : 
     354             :   // Set the inline line-break-after status. The break type can be changed
     355             :   // via the optional aBreakType param.
     356           9 :   void SetInlineLineBreakAfter(StyleClear aBreakType = StyleClear::Line) {
     357           9 :     MOZ_ASSERT(aBreakType != StyleClear::None,
     358             :                "Break-after with StyleClear::None is meaningless!");
     359           9 :     mBreakType = aBreakType;
     360           9 :     mInlineBreak = InlineBreak::After;
     361           9 :   }
     362             : 
     363             :   // mFirstLetterComplete bit flag means the break was induced by
     364             :   // completion of a first-letter.
     365           0 :   bool FirstLetterComplete() const { return mFirstLetterComplete; }
     366           0 :   void SetFirstLetterComplete() { mFirstLetterComplete = true; }
     367             : 
     368             : private:
     369             :   StyleClear mBreakType;
     370             :   InlineBreak mInlineBreak;
     371             :   Completion mCompletion;
     372             :   bool mNextInFlowNeedsReflow : 1;
     373             :   bool mTruncated : 1;
     374             :   bool mFirstLetterComplete : 1;
     375             : };
     376             : 
     377             : #define NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aMetrics) \
     378             :   aStatus.UpdateTruncated(aReflowInput, aMetrics);
     379             : 
     380             : #ifdef DEBUG
     381             : // Convert nsReflowStatus to a human-readable string.
     382             : std::ostream&
     383             : operator<<(std::ostream& aStream, const nsReflowStatus& aStatus);
     384             : #endif
     385             : 
     386             : //----------------------------------------------------------------------
     387             : 
     388             : /**
     389             :  * DidReflow status values.
     390             :  */
     391             : enum class nsDidReflowStatus : uint32_t {
     392             :   NOT_FINISHED,
     393             :   FINISHED
     394             : };
     395             : 
     396             : /**
     397             :  * When there is no scrollable overflow rect, the visual overflow rect
     398             :  * may be stored as four 1-byte deltas each strictly LESS THAN 0xff, for
     399             :  * the four edges of the rectangle, or the four bytes may be read as a
     400             :  * single 32-bit "overflow-rect type" value including at least one 0xff
     401             :  * byte as an indicator that the value does NOT represent four deltas.
     402             :  * If all four deltas are zero, this means that no overflow rect has
     403             :  * actually been set (this is the initial state of newly-created frames).
     404             :  */
     405             : #define NS_FRAME_OVERFLOW_DELTA_MAX     0xfe // max delta we can store
     406             : 
     407             : #define NS_FRAME_OVERFLOW_NONE    0x00000000 // there are no overflow rects;
     408             :                                              // code relies on this being
     409             :                                              // the all-zero value
     410             : 
     411             : #define NS_FRAME_OVERFLOW_LARGE   0x000000ff // overflow is stored as a
     412             :                                              // separate rect property
     413             : 
     414             : /**
     415             :  * nsBidiLevel is the type of the level values in our Unicode Bidi
     416             :  * implementation.
     417             :  * It holds an embedding level and indicates the visual direction
     418             :  * by its bit 0 (even/odd value).<p>
     419             :  *
     420             :  * <li><code>aParaLevel</code> can be set to the
     421             :  * pseudo-level values <code>NSBIDI_DEFAULT_LTR</code>
     422             :  * and <code>NSBIDI_DEFAULT_RTL</code>.</li></ul>
     423             :  *
     424             :  * @see nsBidi::SetPara
     425             :  *
     426             :  * <p>The related constants are not real, valid level values.
     427             :  * <code>NSBIDI_DEFAULT_XXX</code> can be used to specify
     428             :  * a default for the paragraph level for
     429             :  * when the <code>SetPara</code> function
     430             :  * shall determine it but there is no
     431             :  * strongly typed character in the input.<p>
     432             :  *
     433             :  * Note that the value for <code>NSBIDI_DEFAULT_LTR</code> is even
     434             :  * and the one for <code>NSBIDI_DEFAULT_RTL</code> is odd,
     435             :  * just like with normal LTR and RTL level values -
     436             :  * these special values are designed that way. Also, the implementation
     437             :  * assumes that NSBIDI_MAX_EXPLICIT_LEVEL is odd.
     438             :  *
     439             :  * @see NSBIDI_DEFAULT_LTR
     440             :  * @see NSBIDI_DEFAULT_RTL
     441             :  * @see NSBIDI_LEVEL_OVERRIDE
     442             :  * @see NSBIDI_MAX_EXPLICIT_LEVEL
     443             :  */
     444             : typedef uint8_t nsBidiLevel;
     445             : 
     446             : /** Paragraph level setting.
     447             :  *  If there is no strong character, then set the paragraph level to 0 (left-to-right).
     448             :  */
     449             : #define NSBIDI_DEFAULT_LTR 0xfe
     450             : 
     451             : /** Paragraph level setting.
     452             :  *  If there is no strong character, then set the paragraph level to 1 (right-to-left).
     453             :  */
     454             : #define NSBIDI_DEFAULT_RTL 0xff
     455             : 
     456             : /**
     457             :  * Maximum explicit embedding level.
     458             :  * (The maximum resolved level can be up to <code>NSBIDI_MAX_EXPLICIT_LEVEL+1</code>).
     459             :  *
     460             :  */
     461             : #define NSBIDI_MAX_EXPLICIT_LEVEL 125
     462             : 
     463             : /** Bit flag for level input.
     464             :  *  Overrides directional properties.
     465             :  */
     466             : #define NSBIDI_LEVEL_OVERRIDE 0x80
     467             : 
     468             : /**
     469             :  * <code>nsBidiDirection</code> values indicate the text direction.
     470             :  */
     471             : enum nsBidiDirection {
     472             :   /** All left-to-right text This is a 0 value. */
     473             :   NSBIDI_LTR,
     474             :   /** All right-to-left text This is a 1 value. */
     475             :   NSBIDI_RTL,
     476             :   /** Mixed-directional text. */
     477             :   NSBIDI_MIXED
     478             : };
     479             : 
     480             : namespace mozilla {
     481             : 
     482             : // https://drafts.csswg.org/css-align-3/#baseline-sharing-group
     483             : enum BaselineSharingGroup
     484             : {
     485             :   // NOTE Used as an array index so must be 0 and 1.
     486             :   eFirst = 0,
     487             :   eLast = 1,
     488             : };
     489             : 
     490             : // Loosely: https://drafts.csswg.org/css-align-3/#shared-alignment-context
     491             : enum class AlignmentContext
     492             : {
     493             :   eInline,
     494             :   eTable,
     495             :   eFlexbox,
     496             :   eGrid,
     497             : };
     498             : 
     499             : /*
     500             :  * For replaced elements only. Gets the intrinsic dimensions of this element.
     501             :  * The dimensions may only be one of the following two types:
     502             :  *
     503             :  *   eStyleUnit_Coord   - a length in app units
     504             :  *   eStyleUnit_None    - the element has no intrinsic size in this dimension
     505             :  */
     506           5 : struct IntrinsicSize {
     507             :   nsStyleCoord width, height;
     508             : 
     509           5 :   IntrinsicSize()
     510           5 :     : width(eStyleUnit_None), height(eStyleUnit_None)
     511           5 :   {}
     512           0 :   IntrinsicSize(const IntrinsicSize& rhs)
     513           0 :     : width(rhs.width), height(rhs.height)
     514           0 :   {}
     515           0 :   IntrinsicSize& operator=(const IntrinsicSize& rhs) {
     516           0 :     width = rhs.width; height = rhs.height; return *this;
     517             :   }
     518           0 :   bool operator==(const IntrinsicSize& rhs) {
     519           0 :     return width == rhs.width && height == rhs.height;
     520             :   }
     521           0 :   bool operator!=(const IntrinsicSize& rhs) {
     522           0 :     return !(*this == rhs);
     523             :   }
     524             : };
     525             : 
     526             : // Pseudo bidi embedding level indicating nonexistence.
     527             : static const nsBidiLevel kBidiLevelNone = 0xff;
     528             : 
     529             : struct FrameBidiData
     530             : {
     531             :   nsBidiLevel baseLevel;
     532             :   nsBidiLevel embeddingLevel;
     533             :   // The embedding level of virtual bidi formatting character before
     534             :   // this frame if any. kBidiLevelNone is used to indicate nonexistence
     535             :   // or unnecessity of such virtual character.
     536             :   nsBidiLevel precedingControl;
     537             : };
     538             : 
     539             : } // namespace mozilla
     540             : 
     541             : /// Generic destructor for frame properties. Calls delete.
     542             : template<typename T>
     543         180 : static void DeleteValue(T* aPropertyValue)
     544             : {
     545         149 :   delete aPropertyValue;
     546         180 : }
     547             : 
     548             : /// Generic destructor for frame properties. Calls Release().
     549             : template<typename T>
     550           0 : static void ReleaseValue(T* aPropertyValue)
     551             : {
     552           0 :   aPropertyValue->Release();
     553           0 : }
     554             : 
     555             : //----------------------------------------------------------------------
     556             : 
     557             : /**
     558             :  * A frame in the layout model. This interface is supported by all frame
     559             :  * objects.
     560             :  *
     561             :  * Frames can have multiple child lists: the default child list
     562             :  * (referred to as the <i>principal</i> child list, and additional named
     563             :  * child lists. There is an ordering of frames within a child list, but
     564             :  * there is no order defined between frames in different child lists of
     565             :  * the same parent frame.
     566             :  *
     567             :  * Frames are NOT reference counted. Use the Destroy() member function
     568             :  * to destroy a frame. The lifetime of the frame hierarchy is bounded by the
     569             :  * lifetime of the presentation shell which owns the frames.
     570             :  *
     571             :  * nsIFrame is a private Gecko interface. If you are not Gecko then you
     572             :  * should not use it. If you're not in layout, then you won't be able to
     573             :  * link to many of the functions defined here. Too bad.
     574             :  *
     575             :  * If you're not in layout but you must call functions in here, at least
     576             :  * restrict yourself to calling virtual methods, which won't hurt you as badly.
     577             :  */
     578         126 : class nsIFrame : public nsQueryFrame
     579             : {
     580             : public:
     581             :   using AlignmentContext = mozilla::AlignmentContext;
     582             :   using BaselineSharingGroup = mozilla::BaselineSharingGroup;
     583             :   template <typename T> using Maybe = mozilla::Maybe<T>;
     584             :   using Nothing = mozilla::Nothing;
     585             :   using OnNonvisible = mozilla::OnNonvisible;
     586             :   template<typename T=void>
     587             :   using PropertyDescriptor = const mozilla::FramePropertyDescriptor<T>*;
     588             :   using ReflowInput = mozilla::ReflowInput;
     589             :   using ReflowOutput = mozilla::ReflowOutput;
     590             :   using Visibility = mozilla::Visibility;
     591             : 
     592             :   typedef mozilla::FrameProperties FrameProperties;
     593             :   typedef mozilla::layers::Layer Layer;
     594             :   typedef mozilla::layout::FrameChildList ChildList;
     595             :   typedef mozilla::layout::FrameChildListID ChildListID;
     596             :   typedef mozilla::layout::FrameChildListIDs ChildListIDs;
     597             :   typedef mozilla::layout::FrameChildListIterator ChildListIterator;
     598             :   typedef mozilla::layout::FrameChildListArrayIterator ChildListArrayIterator;
     599             :   typedef mozilla::gfx::DrawTarget DrawTarget;
     600             :   typedef mozilla::gfx::Matrix Matrix;
     601             :   typedef mozilla::gfx::Matrix4x4 Matrix4x4;
     602             :   typedef mozilla::Sides Sides;
     603             :   typedef mozilla::LogicalSides LogicalSides;
     604             :   typedef mozilla::SmallPointerArray<mozilla::DisplayItemData> DisplayItemArray;
     605             :   typedef nsQueryFrame::ClassID ClassID;
     606             : 
     607             :   NS_DECL_QUERYFRAME_TARGET(nsIFrame)
     608             : 
     609         666 :   explicit nsIFrame(ClassID aID)
     610         666 :     : mRect()
     611             :     , mContent(nullptr)
     612             :     , mStyleContext(nullptr)
     613             :     , mParent(nullptr)
     614             :     , mNextSibling(nullptr)
     615             :     , mPrevSibling(nullptr)
     616         666 :     , mState(NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY)
     617             :     , mClass(aID)
     618             :     , mMayHaveRoundedCorners(false)
     619             :     , mHasImageRequest(false)
     620        1332 :     , mHasFirstLetterChild(false)
     621             :   {
     622         666 :     mozilla::PodZero(&mOverflow);
     623         666 :   }
     624             : 
     625       70712 :   nsPresContext* PresContext() const {
     626       70712 :     return StyleContext()->PresContext();
     627             :   }
     628             : 
     629             :   /**
     630             :    * Called to initialize the frame. This is called immediately after creating
     631             :    * the frame.
     632             :    *
     633             :    * If the frame is a continuing frame, then aPrevInFlow indicates the previous
     634             :    * frame (the frame that was split).
     635             :    *
     636             :    * Each subclass that need a view should override this method and call
     637             :    * CreateView() after calling its base class Init().
     638             :    *
     639             :    * @param   aContent the content object associated with the frame
     640             :    * @param   aParent the parent frame
     641             :    * @param   aPrevInFlow the prev-in-flow frame
     642             :    */
     643             :   virtual void Init(nsIContent*       aContent,
     644             :                     nsContainerFrame* aParent,
     645             :                     nsIFrame*         aPrevInFlow) = 0;
     646             : 
     647             :   /**
     648             :    * Destroys this frame and each of its child frames (recursively calls
     649             :    * Destroy() for each child). If this frame is a first-continuation, this
     650             :    * also removes the frame from the primary frame map and clears undisplayed
     651             :    * content for its content node.
     652             :    * If the frame is a placeholder, it also ensures the out-of-flow frame's
     653             :    * removal and destruction.
     654             :    */
     655          27 :   void Destroy() { DestroyFrom(this); }
     656             : 
     657             :   /** Flags for PeekOffsetCharacter, PeekOffsetNoAmount, PeekOffsetWord return values.
     658             :     */
     659             :   enum FrameSearchResult {
     660             :     // Peek found a appropriate offset within frame.
     661             :     FOUND = 0x00,
     662             :     // try next frame for offset.
     663             :     CONTINUE = 0x1,
     664             :     // offset not found because the frame was empty of text.
     665             :     CONTINUE_EMPTY = 0x2 | CONTINUE,
     666             :     // offset not found because the frame didn't contain any text that could be selected.
     667             :     CONTINUE_UNSELECTABLE = 0x4 | CONTINUE,
     668             :   };
     669             : 
     670             :   /**
     671             :    * Options for PeekOffsetCharacter().
     672             :    */
     673             :   struct MOZ_STACK_CLASS PeekOffsetCharacterOptions
     674             :   {
     675             :     // Whether to restrict result to valid cursor locations (between grapheme
     676             :     // clusters) - if this is included, maintains "normal" behavior, otherwise,
     677             :     // used for selection by "code unit" (instead of "character")
     678             :     bool mRespectClusters;
     679             :     // Whether to check user-select style value - if this is included, checks
     680             :     // if user-select is all, then, it may return CONTINUE_UNSELECTABLE.
     681             :     bool mIgnoreUserStyleAll;
     682             : 
     683           0 :     PeekOffsetCharacterOptions()
     684           0 :       : mRespectClusters(true)
     685           0 :       , mIgnoreUserStyleAll(false)
     686             :     {
     687           0 :     }
     688             :   };
     689             : 
     690             : protected:
     691             :   /**
     692             :    * Return true if the frame is part of a Selection.
     693             :    * Helper method to implement the public IsSelected() API.
     694             :    */
     695             :   virtual bool IsFrameSelected() const;
     696             : 
     697             :   /**
     698             :    * Implements Destroy(). Do not call this directly except from within a
     699             :    * DestroyFrom() implementation.
     700             :    *
     701             :    * @note This will always be called, so it is not necessary to override
     702             :    *       Destroy() in subclasses of nsFrame, just DestroyFrom().
     703             :    *
     704             :    * @param  aDestructRoot is the root of the subtree being destroyed
     705             :    */
     706             :   virtual void DestroyFrom(nsIFrame* aDestructRoot) = 0;
     707             :   friend class nsFrameList; // needed to pass aDestructRoot through to children
     708             :   friend class nsLineBox;   // needed to pass aDestructRoot through to children
     709             :   friend class nsContainerFrame; // needed to pass aDestructRoot through to children
     710             :   friend class nsFrame; // need to assign mParent
     711             : public:
     712             : 
     713             :   /**
     714             :    * Get the content object associated with this frame. Does not add a reference.
     715             :    */
     716       93610 :   nsIContent* GetContent() const { return mContent; }
     717             : 
     718             :   /**
     719             :    * Get the frame that should be the parent for the frames of child elements
     720             :    * May return nullptr during reflow
     721             :    */
     722         424 :   virtual nsContainerFrame* GetContentInsertionFrame() { return nullptr; }
     723             : 
     724             :   /**
     725             :    * Move any frames on our overflow list to the end of our principal list.
     726             :    * @return true if there were any overflow frames
     727             :    */
     728           0 :   virtual bool DrainSelfOverflowList() { return false; }
     729             : 
     730             :   /**
     731             :    * Get the frame that should be scrolled if the content associated
     732             :    * with this frame is targeted for scrolling. For frames implementing
     733             :    * nsIScrollableFrame this will return the frame itself. For frames
     734             :    * like nsTextControlFrame that contain a scrollframe, will return
     735             :    * that scrollframe.
     736             :    */
     737         123 :   virtual nsIScrollableFrame* GetScrollTargetFrame() { return nullptr; }
     738             : 
     739             :   /**
     740             :    * Get the offsets of the frame. most will be 0,0
     741             :    *
     742             :    */
     743             :   virtual nsresult GetOffsets(int32_t &start, int32_t &end) const = 0;
     744             : 
     745             :   /**
     746             :    * Reset the offsets when splitting frames during Bidi reordering
     747             :    *
     748             :    */
     749           0 :   virtual void AdjustOffsetsForBidi(int32_t aStart, int32_t aEnd) {}
     750             : 
     751             :   /**
     752             :    * Get the style context associated with this frame.
     753             :    */
     754      114489 :   nsStyleContext* StyleContext() const { return mStyleContext; }
     755         677 :   void SetStyleContext(nsStyleContext* aContext)
     756             :   {
     757         677 :     if (aContext != mStyleContext) {
     758         677 :       nsStyleContext* oldStyleContext = mStyleContext;
     759         677 :       mStyleContext = aContext;
     760         677 :       aContext->AddRef();
     761             : #ifdef DEBUG
     762         677 :       aContext->FrameAddRef();
     763             : #endif
     764         677 :       DidSetStyleContext(oldStyleContext);
     765             : #ifdef DEBUG
     766         677 :       oldStyleContext->FrameRelease();
     767             : #endif
     768         677 :       oldStyleContext->Release();
     769             :     }
     770         677 :   }
     771             : 
     772             :   /**
     773             :    * SetStyleContextWithoutNotification is for changes to the style
     774             :    * context that should suppress style change processing, in other
     775             :    * words, those that aren't really changes.  This generally means only
     776             :    * changes that happen during frame construction.
     777             :    */
     778          78 :   void SetStyleContextWithoutNotification(nsStyleContext* aContext)
     779             :   {
     780          78 :     if (aContext != mStyleContext) {
     781             : #ifdef DEBUG
     782          68 :       mStyleContext->FrameRelease();
     783             : #endif
     784          68 :       mStyleContext->Release();
     785          68 :       mStyleContext = aContext;
     786          68 :       aContext->AddRef();
     787             : #ifdef DEBUG
     788          68 :       aContext->FrameAddRef();
     789             : #endif
     790             :     }
     791          78 :   }
     792             : 
     793             :   // Style post processing hook
     794             :   // Attention: the old style context is the one we're forgetting,
     795             :   // and hence possibly completely bogus for GetStyle* purposes.
     796             :   // Use PeekStyleData instead.
     797             :   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) = 0;
     798             : 
     799             :   /**
     800             :    * Define typesafe getter functions for each style struct by
     801             :    * preprocessing the list of style structs.  These functions are the
     802             :    * preferred way to get style data.  The macro creates functions like:
     803             :    *   const nsStyleBorder* StyleBorder();
     804             :    *   const nsStyleColor* StyleColor();
     805             :    *
     806             :    * Callers outside of libxul should use nsIDOMWindow::GetComputedStyle()
     807             :    * instead of these accessors.
     808             :    *
     809             :    * Callers can use Style*WithOptionalParam if they're in a function that
     810             :    * accepts an *optional* pointer the style struct.
     811             :    */
     812             :   #define STYLE_STRUCT(name_, checkdata_cb_)                                  \
     813             :     const nsStyle##name_ * Style##name_ () const MOZ_NONNULL_RETURN {         \
     814             :       NS_ASSERTION(mStyleContext, "No style context found!");                 \
     815             :       return mStyleContext->Style##name_ ();                                  \
     816             :     }                                                                         \
     817             :     const nsStyle##name_ * Style##name_##WithOptionalParam(                   \
     818             :                              const nsStyle##name_ * aStyleStruct) const       \
     819             :                              MOZ_NONNULL_RETURN {                             \
     820             :       if (aStyleStruct) {                                                     \
     821             :         MOZ_ASSERT(aStyleStruct == Style##name_());                           \
     822             :         return aStyleStruct;                                                  \
     823             :       }                                                                       \
     824             :       return Style##name_();                                                  \
     825             :     }
     826             :   #include "nsStyleStructList.h"
     827             :   #undef STYLE_STRUCT
     828             : 
     829             :   /** Also forward GetVisitedDependentColor to the style context */
     830             :   template<typename T, typename S>
     831          20 :   nscolor GetVisitedDependentColor(T S::* aField)
     832          20 :     { return mStyleContext->GetVisitedDependentColor(aField); }
     833             : 
     834             :   /**
     835             :    * These methods are to access any additional style contexts that
     836             :    * the frame may be holding. These are contexts that are children
     837             :    * of the frame's primary context and are NOT used as style contexts
     838             :    * for any child frames. These contexts also MUST NOT have any child
     839             :    * contexts whatsoever. If you need to insert style contexts into the
     840             :    * style tree, then you should create pseudo element frames to own them
     841             :    * The indicies must be consecutive and implementations MUST return an
     842             :    * NS_ERROR_INVALID_ARG if asked for an index that is out of range.
     843             :    */
     844             :   virtual nsStyleContext* GetAdditionalStyleContext(int32_t aIndex) const = 0;
     845             : 
     846             :   virtual void SetAdditionalStyleContext(int32_t aIndex,
     847             :                                          nsStyleContext* aStyleContext) = 0;
     848             : 
     849             :   /**
     850             :    * Accessor functions for geometric parent.
     851             :    */
     852      125183 :   nsContainerFrame* GetParent() const { return mParent; }
     853             : 
     854             :   /**
     855             :    * Gets the parent of a frame, using the parent of the placeholder for
     856             :    * out-of-flow frames.
     857             :    */
     858             :   inline nsContainerFrame* GetInFlowParent();
     859             : 
     860             :   /**
     861             :    * Gets the primary frame of the Content's flattened tree
     862             :    * parent, if one exists.
     863             :    */
     864             :   inline nsIFrame* GetFlattenedTreeParentPrimaryFrame() const;
     865             : 
     866             :   /**
     867             :    * Return the placeholder for this frame (which must be out-of-flow).
     868             :    * @note this will only return non-null if |this| is the first-in-flow
     869             :    * although we don't assert that here for legacy reasons.
     870             :    */
     871         220 :   inline nsPlaceholderFrame* GetPlaceholderFrame() const {
     872         220 :     MOZ_ASSERT(HasAnyStateBits(NS_FRAME_OUT_OF_FLOW));
     873         220 :     return GetProperty(PlaceholderFrameProperty());
     874             :   }
     875             : 
     876             :   /**
     877             :    * Set this frame's parent to aParent.
     878             :    * If the frame may have moved into or out of a scrollframe's
     879             :    * frame subtree, StickyScrollContainer::NotifyReparentedFrameAcrossScrollFrameBoundary
     880             :    * must also be called.
     881             :    */
     882             :   void SetParent(nsContainerFrame* aParent);
     883             : 
     884             :   /**
     885             :    * The frame's writing-mode, used for logical layout computations.
     886             :    * It's usually the 'writing-mode' computed value, but there are exceptions:
     887             :    *   * inner table frames copy the value from the table frame
     888             :    *     (@see nsTableRowGroupFrame::Init, nsTableRowFrame::Init etc)
     889             :    *   * the root element frame propagates its value to its ancestors
     890             :    *     (@see nsCanvasFrame::MaybePropagateRootElementWritingMode)
     891             :    *   * a scrolled frame propagates its value to its ancestor scroll frame
     892             :    *     (@see nsHTMLScrollFrame::ReloadChildFrames)
     893             :    */
     894        7772 :   mozilla::WritingMode GetWritingMode() const { return mWritingMode; }
     895             : 
     896             :   /**
     897             :    * Construct a writing mode for line layout in this frame.  This is
     898             :    * the writing mode of this frame, except that if this frame is styled with
     899             :    * unicode-bidi:plaintext, we reset the direction to the resolved paragraph
     900             :    * level of the given subframe (typically the first frame on the line),
     901             :    * because the container frame could be split by hard line breaks into
     902             :    * multiple paragraphs with different base direction.
     903             :    * @param aSelfWM the WM of 'this'
     904             :    */
     905             :   mozilla::WritingMode WritingModeForLine(mozilla::WritingMode aSelfWM,
     906             :                                           nsIFrame* aSubFrame) const;
     907             : 
     908             :   /**
     909             :    * Bounding rect of the frame.
     910             :    *
     911             :    * For frames that are laid out according to CSS box model rules the values
     912             :    * are in app units, and the origin is relative to the upper-left of the
     913             :    * geometric parent.  The size includes the content area, borders, and
     914             :    * padding.
     915             :    *
     916             :    * Frames that are laid out according to SVG's coordinate space based rules
     917             :    * (frames with the NS_FRAME_SVG_LAYOUT bit set, which *excludes*
     918             :    * nsSVGOuterSVGFrame) are different.  Many frames of this type do not set or
     919             :    * use mRect, in which case the frame rect is undefined.  The exceptions are:
     920             :    *
     921             :    *   - nsSVGInnerSVGFrame
     922             :    *   - SVGGeometryFrame (used for <path>, <circle>, etc.)
     923             :    *   - nsSVGImageFrame
     924             :    *   - nsSVGForeignObjectFrame
     925             :    *
     926             :    * For these frames the frame rect contains the frame's element's userspace
     927             :    * bounds including fill, stroke and markers, but converted to app units
     928             :    * rather than being in user units (CSS px).  In the SVG code "userspace" is
     929             :    * defined to be the coordinate system for the attributes that define an
     930             :    * element's geometry (such as the 'cx' attribute for <circle>).  For more
     931             :    * precise details see these frames' implementations of the ReflowSVG method
     932             :    * where mRect is set.
     933             :    *
     934             :    * Note: moving or sizing the frame does not affect the view's size or
     935             :    * position.
     936             :    */
     937        3239 :   nsRect GetRect() const { return mRect; }
     938       21929 :   nsPoint GetPosition() const { return mRect.TopLeft(); }
     939       18382 :   nsSize GetSize() const { return mRect.Size(); }
     940        1049 :   nsRect GetRectRelativeToSelf() const {
     941        1049 :     return nsRect(nsPoint(0, 0), mRect.Size());
     942             :   }
     943             :   /**
     944             :    * Dimensions and position in logical coordinates in the frame's writing mode
     945             :    *  or another writing mode
     946             :    */
     947           0 :   mozilla::LogicalRect GetLogicalRect(const nsSize& aContainerSize) const {
     948           0 :     return GetLogicalRect(GetWritingMode(), aContainerSize);
     949             :   }
     950           0 :   mozilla::LogicalPoint GetLogicalPosition(const nsSize& aContainerSize) const {
     951           0 :     return GetLogicalPosition(GetWritingMode(), aContainerSize);
     952             :   }
     953           4 :   mozilla::LogicalSize GetLogicalSize() const {
     954           4 :     return GetLogicalSize(GetWritingMode());
     955             :   }
     956           0 :   mozilla::LogicalRect GetLogicalRect(mozilla::WritingMode aWritingMode,
     957             :                                       const nsSize& aContainerSize) const {
     958           0 :     return mozilla::LogicalRect(aWritingMode, GetRect(), aContainerSize);
     959             :   }
     960           0 :   mozilla::LogicalPoint GetLogicalPosition(mozilla::WritingMode aWritingMode,
     961             :                                            const nsSize& aContainerSize) const {
     962           0 :     return GetLogicalRect(aWritingMode, aContainerSize).Origin(aWritingMode);
     963             :   }
     964        1652 :   mozilla::LogicalSize GetLogicalSize(mozilla::WritingMode aWritingMode) const {
     965        1652 :     return mozilla::LogicalSize(aWritingMode, GetSize());
     966             :   }
     967             :   nscoord IStart(const nsSize& aContainerSize) const {
     968             :     return IStart(GetWritingMode(), aContainerSize);
     969             :   }
     970             :   nscoord IStart(mozilla::WritingMode aWritingMode,
     971             :                  const nsSize& aContainerSize) const {
     972             :     return GetLogicalPosition(aWritingMode, aContainerSize).I(aWritingMode);
     973             :   }
     974             :   nscoord BStart(const nsSize& aContainerSize) const {
     975             :     return BStart(GetWritingMode(), aContainerSize);
     976             :   }
     977           0 :   nscoord BStart(mozilla::WritingMode aWritingMode,
     978             :                  const nsSize& aContainerSize) const {
     979           0 :     return GetLogicalPosition(aWritingMode, aContainerSize).B(aWritingMode);
     980             :   }
     981           0 :   nscoord ISize() const { return ISize(GetWritingMode()); }
     982        1017 :   nscoord ISize(mozilla::WritingMode aWritingMode) const {
     983        1017 :     return GetLogicalSize(aWritingMode).ISize(aWritingMode);
     984             :   }
     985           0 :   nscoord BSize() const { return BSize(GetWritingMode()); }
     986         341 :   nscoord BSize(mozilla::WritingMode aWritingMode) const {
     987         341 :     return GetLogicalSize(aWritingMode).BSize(aWritingMode);
     988             :   }
     989             :   nscoord ContentBSize() const { return ContentBSize(GetWritingMode()); }
     990           0 :   nscoord ContentBSize(mozilla::WritingMode aWritingMode) const {
     991           0 :     auto bp = GetLogicalUsedBorderAndPadding(aWritingMode);
     992           0 :     bp.ApplySkipSides(GetLogicalSkipSides());
     993           0 :     return std::max(0, BSize(aWritingMode) - bp.BStartEnd(aWritingMode));
     994             :   }
     995             : 
     996             :   /**
     997             :    * When we change the size of the frame's border-box rect, we may need to
     998             :    * reset the overflow rect if it was previously stored as deltas.
     999             :    * (If it is currently a "large" overflow and could be re-packed as deltas,
    1000             :    * we don't bother as the cost of the allocation has already been paid.)
    1001             :    */
    1002        6388 :   void SetRect(const nsRect& aRect) {
    1003       12076 :     if (mOverflow.mType != NS_FRAME_OVERFLOW_LARGE &&
    1004        5688 :         mOverflow.mType != NS_FRAME_OVERFLOW_NONE) {
    1005          18 :       nsOverflowAreas overflow = GetOverflowAreas();
    1006           9 :       mRect = aRect;
    1007          18 :       SetOverflowAreas(overflow);
    1008             :     } else {
    1009        6379 :       mRect = aRect;
    1010             :     }
    1011        6388 :   }
    1012             :   /**
    1013             :    * Set this frame's rect from a logical rect in its own writing direction
    1014             :    */
    1015           0 :   void SetRect(const mozilla::LogicalRect& aRect,
    1016             :                const nsSize& aContainerSize) {
    1017           0 :     SetRect(GetWritingMode(), aRect, aContainerSize);
    1018           0 :   }
    1019             :   /**
    1020             :    * Set this frame's rect from a logical rect in a different writing direction
    1021             :    * (GetPhysicalRect will assert if the writing mode doesn't match)
    1022             :    */
    1023         205 :   void SetRect(mozilla::WritingMode aWritingMode,
    1024             :                const mozilla::LogicalRect& aRect,
    1025             :                const nsSize& aContainerSize) {
    1026         205 :     SetRect(aRect.GetPhysicalRect(aWritingMode, aContainerSize));
    1027         205 :   }
    1028             : 
    1029             :   /**
    1030             :    * Set this frame's size from a logical size in its own writing direction.
    1031             :    * This leaves the frame's logical position unchanged, which means its
    1032             :    * physical position may change (for right-to-left modes).
    1033             :    */
    1034          71 :   void SetSize(const mozilla::LogicalSize& aSize) {
    1035          71 :     SetSize(GetWritingMode(), aSize);
    1036          71 :   }
    1037             :   /*
    1038             :    * Set this frame's size from a logical size in a different writing direction.
    1039             :    * This leaves the frame's logical position in the given mode unchanged,
    1040             :    * which means its physical position may change (for right-to-left modes).
    1041             :    */
    1042         333 :   void SetSize(mozilla::WritingMode aWritingMode,
    1043             :                const mozilla::LogicalSize& aSize)
    1044             :   {
    1045         666 :     if ((!aWritingMode.IsVertical() && !aWritingMode.IsBidiLTR()) ||
    1046         333 :         aWritingMode.IsVerticalRL()) {
    1047           0 :       nscoord oldWidth = mRect.width;
    1048           0 :       SetSize(aSize.GetPhysicalSize(aWritingMode));
    1049           0 :       mRect.x -= mRect.width - oldWidth;
    1050             :     } else {
    1051         333 :       SetSize(aSize.GetPhysicalSize(aWritingMode));
    1052             :     }
    1053         333 :   }
    1054             : 
    1055             :   /**
    1056             :    * Set this frame's physical size. This leaves the frame's physical position
    1057             :    * (topLeft) unchanged.
    1058             :    */
    1059        4070 :   void SetSize(const nsSize& aSize) {
    1060        4070 :     SetRect(nsRect(mRect.TopLeft(), aSize));
    1061        4070 :   }
    1062             : 
    1063         269 :   void SetPosition(const nsPoint& aPt) { mRect.MoveTo(aPt); }
    1064          45 :   void SetPosition(mozilla::WritingMode aWritingMode,
    1065             :                    const mozilla::LogicalPoint& aPt,
    1066             :                    const nsSize& aContainerSize) {
    1067             :     // We subtract mRect.Size() from the container size to account for
    1068             :     // the fact that logical origins in RTL coordinate systems are at
    1069             :     // the top right of the frame instead of the top left.
    1070          90 :     mRect.MoveTo(aPt.GetPhysicalPoint(aWritingMode,
    1071         135 :                                       aContainerSize - mRect.Size()));
    1072          45 :   }
    1073             : 
    1074             :   /**
    1075             :    * Move the frame, accounting for relative positioning. Use this when
    1076             :    * adjusting the frame's position by a known amount, to properly update its
    1077             :    * saved normal position (see GetNormalPosition below).
    1078             :    *
    1079             :    * This must be used only when moving a frame *after*
    1080             :    * ReflowInput::ApplyRelativePositioning is called.  When moving
    1081             :    * a frame during the reflow process prior to calling
    1082             :    * ReflowInput::ApplyRelativePositioning, the position should
    1083             :    * simply be adjusted directly (e.g., using SetPosition()).
    1084             :    */
    1085             :   void MovePositionBy(const nsPoint& aTranslation);
    1086             : 
    1087             :   /**
    1088             :    * As above, using a logical-point delta in a given writing mode.
    1089             :    */
    1090           0 :   void MovePositionBy(mozilla::WritingMode aWritingMode,
    1091             :                       const mozilla::LogicalPoint& aTranslation)
    1092             :   {
    1093             :     // The LogicalPoint represents a vector rather than a point within a
    1094             :     // rectangular coordinate space, so we use a null containerSize when
    1095             :     // converting logical to physical.
    1096           0 :     const nsSize nullContainerSize;
    1097           0 :     MovePositionBy(aTranslation.GetPhysicalPoint(aWritingMode,
    1098           0 :                                                  nullContainerSize));
    1099           0 :   }
    1100             : 
    1101             :   /**
    1102             :    * Return frame's rect without relative positioning
    1103             :    */
    1104             :   nsRect GetNormalRect() const;
    1105             : 
    1106             :   /**
    1107             :    * Return frame's position without relative positioning.
    1108             :    * If aHasProperty is provided, returns whether the normal position
    1109             :    * was stored in a frame property.
    1110             :    */
    1111             :   inline nsPoint GetNormalPosition(bool* aHasProperty = nullptr) const;
    1112             : 
    1113             :   mozilla::LogicalPoint
    1114           0 :   GetLogicalNormalPosition(mozilla::WritingMode aWritingMode,
    1115             :                            const nsSize& aContainerSize) const
    1116             :   {
    1117             :     // Subtract the size of this frame from the container size to get
    1118             :     // the correct position in rtl frames where the origin is on the
    1119             :     // right instead of the left
    1120             :     return mozilla::LogicalPoint(aWritingMode,
    1121           0 :                                  GetNormalPosition(),
    1122           0 :                                  aContainerSize - mRect.Size());
    1123             :   }
    1124             : 
    1125         806 :   virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild)
    1126         806 :   { return aChild->GetPosition(); }
    1127             : 
    1128             :   nsPoint GetPositionIgnoringScrolling();
    1129             : 
    1130             :   typedef AutoTArray<nsIContent*, 2> ContentArray;
    1131             :   static void DestroyContentArray(ContentArray* aArray);
    1132             : 
    1133             :   typedef mozilla::layers::WebRenderUserData WebRenderUserData;
    1134             :   typedef nsRefPtrHashtable<nsUint32HashKey, WebRenderUserData> WebRenderUserDataTable;
    1135             : 
    1136             : #define NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, dtor)             \
    1137             :   static const mozilla::FramePropertyDescriptor<type>* prop() {           \
    1138             :     /* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */    \
    1139             :     static const auto descriptor =                                        \
    1140             :       mozilla::FramePropertyDescriptor<type>::NewWithDestructor<dtor>();  \
    1141             :     return &descriptor;                                                   \
    1142             :   }
    1143             : 
    1144             : // Don't use this unless you really know what you're doing!
    1145             : #define NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(prop, type, dtor)    \
    1146             :   static const mozilla::FramePropertyDescriptor<type>* prop() {           \
    1147             :     /* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */    \
    1148             :     static const auto descriptor = mozilla::                              \
    1149             :       FramePropertyDescriptor<type>::NewWithDestructorWithFrame<dtor>();  \
    1150             :     return &descriptor;                                                   \
    1151             :   }
    1152             : 
    1153             : #define NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(prop, type)                \
    1154             :   static const mozilla::FramePropertyDescriptor<type>* prop() {           \
    1155             :     /* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */    \
    1156             :     static const auto descriptor =                                        \
    1157             :       mozilla::FramePropertyDescriptor<type>::NewWithoutDestructor();     \
    1158             :     return &descriptor;                                                   \
    1159             :   }
    1160             : 
    1161             : #define NS_DECLARE_FRAME_PROPERTY_DELETABLE(prop, type) \
    1162             :   NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, DeleteValue)
    1163             : 
    1164             : #define NS_DECLARE_FRAME_PROPERTY_RELEASABLE(prop, type) \
    1165             :   NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, ReleaseValue)
    1166             : 
    1167             : #define NS_DECLARE_FRAME_PROPERTY_WITH_DTOR_NEVER_CALLED(prop, type)  \
    1168             :   static void AssertOnDestroyingProperty##prop(type*) {               \
    1169             :     MOZ_ASSERT_UNREACHABLE("Frame property " #prop " should never "   \
    1170             :                            "be destroyed by the FrameProperties class");  \
    1171             :   }                                                                   \
    1172             :   NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type,                     \
    1173             :                                       AssertOnDestroyingProperty##prop)
    1174             : 
    1175             : #define NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(prop, type) \
    1176             :   NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(prop, mozilla::SmallValueHolder<type>)
    1177             : 
    1178           0 :   NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(IBSplitSibling, nsContainerFrame)
    1179           0 :   NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(IBSplitPrevSibling, nsContainerFrame)
    1180             : 
    1181          55 :   NS_DECLARE_FRAME_PROPERTY_DELETABLE(NormalPositionProperty, nsPoint)
    1182           0 :   NS_DECLARE_FRAME_PROPERTY_DELETABLE(ComputedOffsetProperty, nsMargin)
    1183             : 
    1184           0 :   NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutlineInnerRectProperty, nsRect)
    1185           6 :   NS_DECLARE_FRAME_PROPERTY_DELETABLE(PreEffectsBBoxProperty, nsRect)
    1186        1738 :   NS_DECLARE_FRAME_PROPERTY_DELETABLE(PreTransformOverflowAreasProperty,
    1187             :                                       nsOverflowAreas)
    1188             : 
    1189        1536 :   NS_DECLARE_FRAME_PROPERTY_DELETABLE(OverflowAreasProperty, nsOverflowAreas)
    1190             : 
    1191             :   // The initial overflow area passed to FinishAndStoreOverflow. This is only set
    1192             :   // on frames that Preserve3D() or HasPerspective() or IsTransformed(), and
    1193             :   // when at least one of the overflow areas differs from the frame bound rect.
    1194          95 :   NS_DECLARE_FRAME_PROPERTY_DELETABLE(InitialOverflowProperty, nsOverflowAreas)
    1195             : 
    1196             : #ifdef DEBUG
    1197             :   // InitialOverflowPropertyDebug is added to the frame to indicate that either
    1198             :   // the InitialOverflowProperty has been stored or the InitialOverflowProperty
    1199             :   // has been suppressed due to being set to the default value (frame bounds)
    1200        1710 :   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(DebugInitialOverflowPropertyApplied, bool)
    1201             : #endif
    1202             : 
    1203        1678 :   NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedMarginProperty, nsMargin)
    1204        2240 :   NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedPaddingProperty, nsMargin)
    1205        3212 :   NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedBorderProperty, nsMargin)
    1206             : 
    1207          75 :   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(LineBaselineOffset, nscoord)
    1208             : 
    1209             :   // Temporary override for a flex item's main-size property (either width
    1210             :   // or height), imposed by its flex container.
    1211           0 :   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(FlexItemMainSizeOverride, nscoord)
    1212             : 
    1213           0 :   NS_DECLARE_FRAME_PROPERTY_RELEASABLE(CachedBackgroundImageDT, DrawTarget)
    1214             : 
    1215           0 :   NS_DECLARE_FRAME_PROPERTY_DELETABLE(InvalidationRect, nsRect)
    1216             : 
    1217           0 :   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(RefusedAsyncAnimationProperty, bool)
    1218             : 
    1219           0 :   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(FragStretchBSizeProperty, nscoord)
    1220             : 
    1221             :   // The block-axis margin-box size associated with eBClampMarginBoxMinSize.
    1222           0 :   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BClampMarginBoxMinSizeProperty, nscoord)
    1223             : 
    1224         652 :   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(IBaselinePadProperty, nscoord)
    1225         652 :   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BBaselinePadProperty, nscoord)
    1226             : 
    1227          51 :   NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(GenConProperty, ContentArray,
    1228             :                                       DestroyContentArray)
    1229             : 
    1230           0 :   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BidiDataProperty, mozilla::FrameBidiData)
    1231             : 
    1232         439 :   NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(PlaceholderFrameProperty, nsPlaceholderFrame)
    1233           0 :   NS_DECLARE_FRAME_PROPERTY_DELETABLE(WebRenderUserDataProperty, WebRenderUserDataTable)
    1234             : 
    1235           0 :   mozilla::FrameBidiData GetBidiData() const
    1236             :   {
    1237             :     bool exists;
    1238           0 :     mozilla::FrameBidiData bidiData = GetProperty(BidiDataProperty(), &exists);
    1239           0 :     if (!exists) {
    1240           0 :       bidiData.precedingControl = mozilla::kBidiLevelNone;
    1241             :     }
    1242           0 :     return bidiData;
    1243             :   }
    1244             : 
    1245           0 :   nsBidiLevel GetBaseLevel() const
    1246             :   {
    1247           0 :     return GetBidiData().baseLevel;
    1248             :   }
    1249             : 
    1250           0 :   nsBidiLevel GetEmbeddingLevel() const
    1251             :   {
    1252           0 :     return GetBidiData().embeddingLevel;
    1253             :   }
    1254             : 
    1255             :   /**
    1256             :    * Return the distance between the border edge of the frame and the
    1257             :    * margin edge of the frame.  Like GetRect(), returns the dimensions
    1258             :    * as of the most recent reflow.
    1259             :    *
    1260             :    * This doesn't include any margin collapsing that may have occurred.
    1261             :    *
    1262             :    * It also treats 'auto' margins as zero, and treats any margins that
    1263             :    * should have been turned into 'auto' because of overconstraint as
    1264             :    * having their original values.
    1265             :    */
    1266             :   virtual nsMargin GetUsedMargin() const;
    1267             :   virtual mozilla::LogicalMargin
    1268         142 :   GetLogicalUsedMargin(mozilla::WritingMode aWritingMode) const {
    1269         142 :     return mozilla::LogicalMargin(aWritingMode, GetUsedMargin());
    1270             :   }
    1271             : 
    1272             :   /**
    1273             :    * Return the distance between the border edge of the frame (which is
    1274             :    * its rect) and the padding edge of the frame. Like GetRect(), returns
    1275             :    * the dimensions as of the most recent reflow.
    1276             :    *
    1277             :    * Note that this differs from StyleBorder()->GetComputedBorder() in
    1278             :    * that this describes a region of the frame's box, and
    1279             :    * StyleBorder()->GetComputedBorder() describes a border.  They differ
    1280             :    * for tables (particularly border-collapse tables) and themed
    1281             :    * elements.
    1282             :    */
    1283             :   virtual nsMargin GetUsedBorder() const;
    1284             :   virtual mozilla::LogicalMargin
    1285           0 :   GetLogicalUsedBorder(mozilla::WritingMode aWritingMode) const {
    1286           0 :     return mozilla::LogicalMargin(aWritingMode, GetUsedBorder());
    1287             :   }
    1288             : 
    1289             :   /**
    1290             :    * Return the distance between the padding edge of the frame and the
    1291             :    * content edge of the frame.  Like GetRect(), returns the dimensions
    1292             :    * as of the most recent reflow.
    1293             :    */
    1294             :   virtual nsMargin GetUsedPadding() const;
    1295             :   virtual mozilla::LogicalMargin
    1296           0 :   GetLogicalUsedPadding(mozilla::WritingMode aWritingMode) const {
    1297           0 :     return mozilla::LogicalMargin(aWritingMode, GetUsedPadding());
    1298             :   }
    1299             : 
    1300         536 :   nsMargin GetUsedBorderAndPadding() const {
    1301         536 :     return GetUsedBorder() + GetUsedPadding();
    1302             :   }
    1303             :   mozilla::LogicalMargin
    1304          77 :   GetLogicalUsedBorderAndPadding(mozilla::WritingMode aWritingMode) const {
    1305          77 :     return mozilla::LogicalMargin(aWritingMode, GetUsedBorderAndPadding());
    1306             :   }
    1307             : 
    1308             :   /**
    1309             :    * Like the frame's rect (see |GetRect|), which is the border rect,
    1310             :    * other rectangles of the frame, in app units, relative to the parent.
    1311             :    */
    1312             :   nsRect GetPaddingRect() const;
    1313             :   nsRect GetPaddingRectRelativeToSelf() const;
    1314             :   nsRect GetContentRect() const;
    1315             :   nsRect GetContentRectRelativeToSelf() const;
    1316             :   nsRect GetMarginRectRelativeToSelf() const;
    1317             : 
    1318             :   /**
    1319             :    * The area to paint box-shadows around.  The default is the border rect.
    1320             :    * (nsFieldSetFrame overrides this).
    1321             :    */
    1322          28 :   virtual nsRect VisualBorderRectRelativeToSelf() const {
    1323          28 :     return nsRect(0, 0, mRect.width, mRect.height);
    1324             :   }
    1325             : 
    1326             :   /**
    1327             :    * Get the size, in app units, of the border radii. It returns FALSE iff all
    1328             :    * returned radii == 0 (so no border radii), TRUE otherwise.
    1329             :    * For the aRadii indexes, use the enum HalfCorner constants in gfx/2d/Types.h
    1330             :    * If a side is skipped via aSkipSides, its corners are forced to 0.
    1331             :    *
    1332             :    * All corner radii are then adjusted so they do not require more
    1333             :    * space than aBorderArea, according to the algorithm in css3-background.
    1334             :    *
    1335             :    * aFrameSize is used as the basis for percentage widths and heights.
    1336             :    * aBorderArea is used for the adjustment of radii that might be too
    1337             :    * large.
    1338             :    * FIXME: In the long run, we can probably get away with only one of
    1339             :    * these, especially if we change the way we handle outline-radius (by
    1340             :    * removing it and inflating the border radius)
    1341             :    *
    1342             :    * Return whether any radii are nonzero.
    1343             :    */
    1344             :   static bool ComputeBorderRadii(const nsStyleCorners& aBorderRadius,
    1345             :                                  const nsSize& aFrameSize,
    1346             :                                  const nsSize& aBorderArea,
    1347             :                                  Sides aSkipSides,
    1348             :                                  nscoord aRadii[8]);
    1349             : 
    1350             :   /*
    1351             :    * Given a set of border radii for one box (e.g., border box), convert
    1352             :    * it to the equivalent set of radii for another box (e.g., in to
    1353             :    * padding box, out to outline box) by reducing radii or increasing
    1354             :    * nonzero radii as appropriate.
    1355             :    *
    1356             :    * Indices into aRadii are the enum HalfCorner constants in gfx/2d/Types.h
    1357             :    *
    1358             :    * Note that InsetBorderRadii is lossy, since it can turn nonzero
    1359             :    * radii into zero, and OutsetBorderRadii does not inflate zero radii.
    1360             :    * Therefore, callers should always inset or outset directly from the
    1361             :    * original value coming from style.
    1362             :    */
    1363             :   static void InsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets);
    1364             :   static void OutsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets);
    1365             : 
    1366             :   /**
    1367             :    * Fill in border radii for this frame.  Return whether any are nonzero.
    1368             :    * Indices into aRadii are the enum HalfCorner constants in gfx/2d/Types.h
    1369             :    * aSkipSides is a union of eSideBitsLeft/Right/Top/Bottom bits that says
    1370             :    * which side(s) to skip.
    1371             :    *
    1372             :    * Note: GetMarginBoxBorderRadii() and GetShapeBoxBorderRadii() work only
    1373             :    * on frames that establish block formatting contexts since they don't
    1374             :    * participate in margin-collapsing.
    1375             :    */
    1376             :   virtual bool GetBorderRadii(const nsSize& aFrameSize,
    1377             :                               const nsSize& aBorderArea,
    1378             :                               Sides aSkipSides,
    1379             :                               nscoord aRadii[8]) const;
    1380             :   bool GetBorderRadii(nscoord aRadii[8]) const;
    1381             :   bool GetMarginBoxBorderRadii(nscoord aRadii[8]) const;
    1382             :   bool GetPaddingBoxBorderRadii(nscoord aRadii[8]) const;
    1383             :   bool GetContentBoxBorderRadii(nscoord aRadii[8]) const;
    1384             :   bool GetShapeBoxBorderRadii(nscoord aRadii[8]) const;
    1385             : 
    1386             :   /**
    1387             :    * XXX: this method will likely be replaced by GetVerticalAlignBaseline
    1388             :    * Get the position of the frame's baseline, relative to the top of
    1389             :    * the frame (its top border edge).  Only valid when Reflow is not
    1390             :    * needed.
    1391             :    * @note You should only call this on frames with a WM that's parallel to aWM.
    1392             :    * @param aWM the writing-mode of the alignment context, with the ltr/rtl
    1393             :    * direction tweak done by nsIFrame::GetWritingMode(nsIFrame*) in inline
    1394             :    * contexts (see that method).
    1395             :    */
    1396             :   virtual nscoord GetLogicalBaseline(mozilla::WritingMode aWM) const = 0;
    1397             : 
    1398             :   /**
    1399             :    * Synthesize a first(last) inline-axis baseline from our margin-box.
    1400             :    * An alphabetical baseline is at the start(end) edge and a central baseline
    1401             :    * is at the center of our block-axis margin-box (aWM tells which to use).
    1402             :    * https://drafts.csswg.org/css-align-3/#synthesize-baselines
    1403             :    * @note You should only call this on frames with a WM that's parallel to aWM.
    1404             :    * @param aWM the writing-mode of the alignment context
    1405             :    * @return an offset from our border-box block-axis start(end) edge for
    1406             :    * a first(last) baseline respectively
    1407             :    * (implemented in nsIFrameInlines.h)
    1408             :    */
    1409             :   inline nscoord SynthesizeBaselineBOffsetFromMarginBox(
    1410             :                    mozilla::WritingMode aWM,
    1411             :                    BaselineSharingGroup aGroup) const;
    1412             : 
    1413             :   /**
    1414             :    * Synthesize a first(last) inline-axis baseline from our border-box.
    1415             :    * An alphabetical baseline is at the start(end) edge and a central baseline
    1416             :    * is at the center of our block-axis border-box (aWM tells which to use).
    1417             :    * https://drafts.csswg.org/css-align-3/#synthesize-baselines
    1418             :    * @note The returned value is only valid when reflow is not needed.
    1419             :    * @note You should only call this on frames with a WM that's parallel to aWM.
    1420             :    * @param aWM the writing-mode of the alignment context
    1421             :    * @return an offset from our border-box block-axis start(end) edge for
    1422             :    * a first(last) baseline respectively
    1423             :    * (implemented in nsIFrameInlines.h)
    1424             :    */
    1425             :   inline nscoord SynthesizeBaselineBOffsetFromBorderBox(
    1426             :                    mozilla::WritingMode aWM,
    1427             :                    BaselineSharingGroup aGroup) const;
    1428             : 
    1429             :   /**
    1430             :    * Return the position of the frame's inline-axis baseline, or synthesize one
    1431             :    * for the given alignment context. The returned baseline is the distance from
    1432             :    * the block-axis border-box start(end) edge for aBaselineGroup eFirst(eLast).
    1433             :    * @note The returned value is only valid when reflow is not needed.
    1434             :    * @note You should only call this on frames with a WM that's parallel to aWM.
    1435             :    * @param aWM the writing-mode of the alignment context
    1436             :    * @param aBaselineOffset out-param, only valid if the method returns true
    1437             :    * (implemented in nsIFrameInlines.h)
    1438             :    */
    1439             :   inline nscoord BaselineBOffset(mozilla::WritingMode aWM,
    1440             :                                  BaselineSharingGroup aBaselineGroup,
    1441             :                                  AlignmentContext     aAlignmentContext) const;
    1442             : 
    1443             :   /**
    1444             :    * XXX: this method is taking over the role that GetLogicalBaseline has.
    1445             :    * Return true if the frame has a CSS2 'vertical-align' baseline.
    1446             :    * If it has, then the returned baseline is the distance from the block-
    1447             :    * axis border-box start edge.
    1448             :    * @note This method should only be used in AlignmentContext::eInline contexts.
    1449             :    * @note The returned value is only valid when reflow is not needed.
    1450             :    * @note You should only call this on frames with a WM that's parallel to aWM.
    1451             :    * @param aWM the writing-mode of the alignment context
    1452             :    * @param aBaseline the baseline offset, only valid if the method returns true
    1453             :    */
    1454           0 :   virtual bool GetVerticalAlignBaseline(mozilla::WritingMode aWM,
    1455             :                                         nscoord* aBaseline) const {
    1456           0 :     return false;
    1457             :   }
    1458             : 
    1459             :   /**
    1460             :    * Return true if the frame has a first(last) inline-axis natural baseline per
    1461             :    * CSS Box Alignment.  If so, then the returned baseline is the distance from
    1462             :    * the block-axis border-box start(end) edge for aBaselineGroup eFirst(eLast).
    1463             :    * https://drafts.csswg.org/css-align-3/#natural-baseline
    1464             :    * @note The returned value is only valid when reflow is not needed.
    1465             :    * @note You should only call this on frames with a WM that's parallel to aWM.
    1466             :    * @param aWM the writing-mode of the alignment context
    1467             :    * @param aBaseline the baseline offset, only valid if the method returns true
    1468             :    */
    1469           0 :   virtual bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM,
    1470             :                                          BaselineSharingGroup aBaselineGroup,
    1471             :                                          nscoord*             aBaseline) const {
    1472           0 :     return false;
    1473             :   }
    1474             : 
    1475             :   /**
    1476             :    * Get the position of the baseline on which the caret needs to be placed,
    1477             :    * relative to the top of the frame.  This is mostly needed for frames
    1478             :    * which return a baseline from GetBaseline which is not useful for
    1479             :    * caret positioning.
    1480             :    */
    1481           0 :   virtual nscoord GetCaretBaseline() const {
    1482           0 :     return GetLogicalBaseline(GetWritingMode());
    1483             :   }
    1484             : 
    1485             :   ///////////////////////////////////////////////////////////////////////////////
    1486             :   // The public visibility API.
    1487             :   ///////////////////////////////////////////////////////////////////////////////
    1488             : 
    1489             :   /// @return true if we're tracking visibility for this frame.
    1490        1749 :   bool TrackingVisibility() const
    1491             :   {
    1492        1749 :     return bool(GetStateBits() & NS_FRAME_VISIBILITY_IS_TRACKED);
    1493             :   }
    1494             : 
    1495             :   /// @return the visibility state of this frame. See the Visibility enum
    1496             :   /// for the possible return values and their meanings.
    1497             :   Visibility GetVisibility() const;
    1498             : 
    1499             :   /// Update the visibility state of this frame synchronously.
    1500             :   /// XXX(seth): Avoid using this method; we should be relying on the refresh
    1501             :   /// driver for visibility updates. This method, which replaces
    1502             :   /// nsLayoutUtils::UpdateApproximateFrameVisibility(), exists purely as a
    1503             :   /// temporary measure to avoid changing behavior during the transition from
    1504             :   /// the old image visibility code.
    1505             :   void UpdateVisibilitySynchronously();
    1506             : 
    1507             :   // A frame property which stores the visibility state of this frame. Right
    1508             :   // now that consists of an approximate visibility counter represented as a
    1509             :   // uint32_t. When the visibility of this frame is not being tracked, this
    1510             :   // property is absent.
    1511           0 :   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(VisibilityStateProperty, uint32_t);
    1512             : 
    1513             : protected:
    1514             : 
    1515             :   /**
    1516             :    * Subclasses can call this method to enable visibility tracking for this frame.
    1517             :    *
    1518             :    * If visibility tracking was previously disabled, this will schedule an
    1519             :    * update an asynchronous update of visibility.
    1520             :    */
    1521             :   void EnableVisibilityTracking();
    1522             : 
    1523             :   /**
    1524             :    * Subclasses can call this method to disable visibility tracking for this frame.
    1525             :    *
    1526             :    * Note that if visibility tracking was previously enabled, disabling visibility
    1527             :    * tracking will cause a synchronous call to OnVisibilityChange().
    1528             :    */
    1529             :   void DisableVisibilityTracking();
    1530             : 
    1531             :   /**
    1532             :    * Called when a frame transitions between visibility states (for example,
    1533             :    * from nonvisible to visible, or from visible to nonvisible).
    1534             :    *
    1535             :    * @param aNewVisibility    The new visibility state.
    1536             :    * @param aNonvisibleAction A requested action if the frame has become
    1537             :    *                          nonvisible. If Nothing(), no action is
    1538             :    *                          requested. If DISCARD_IMAGES is specified, the
    1539             :    *                          frame is requested to ask any images it's
    1540             :    *                          associated with to discard their surfaces if
    1541             :    *                          possible.
    1542             :    *
    1543             :    * Subclasses which override this method should call their parent class's
    1544             :    * implementation.
    1545             :    */
    1546             :   virtual void OnVisibilityChange(Visibility aNewVisibility,
    1547             :                                   const Maybe<OnNonvisible>& aNonvisibleAction = Nothing());
    1548             : 
    1549             : public:
    1550             : 
    1551             :   ///////////////////////////////////////////////////////////////////////////////
    1552             :   // Internal implementation for the approximate frame visibility API.
    1553             :   ///////////////////////////////////////////////////////////////////////////////
    1554             : 
    1555             :   /**
    1556             :    * We track the approximate visibility of frames using a counter; if it's
    1557             :    * non-zero, then the frame is considered visible. Using a counter allows us
    1558             :    * to account for situations where the frame may be visible in more than one
    1559             :    * place (for example, via -moz-element), and it simplifies the
    1560             :    * implementation of our approximate visibility tracking algorithms.
    1561             :    *
    1562             :    * @param aNonvisibleAction A requested action if the frame has become
    1563             :    *                          nonvisible. If Nothing(), no action is
    1564             :    *                          requested. If DISCARD_IMAGES is specified, the
    1565             :    *                          frame is requested to ask any images it's
    1566             :    *                          associated with to discard their surfaces if
    1567             :    *                          possible.
    1568             :    */
    1569             :   void DecApproximateVisibleCount(const Maybe<OnNonvisible>& aNonvisibleAction = Nothing());
    1570             :   void IncApproximateVisibleCount();
    1571             : 
    1572             : 
    1573             :   /**
    1574             :    * Get the specified child list.
    1575             :    *
    1576             :    * @param   aListID identifies the requested child list.
    1577             :    * @return  the child list.  If the requested list is unsupported by this
    1578             :    *          frame type, an empty list will be returned.
    1579             :    */
    1580             :   virtual const nsFrameList& GetChildList(ChildListID aListID) const = 0;
    1581        6269 :   const nsFrameList& PrincipalChildList() const { return GetChildList(kPrincipalList); }
    1582             :   virtual void GetChildLists(nsTArray<ChildList>* aLists) const = 0;
    1583             : 
    1584             :   /**
    1585             :    * Gets the child lists for this frame, including
    1586             :    * ones belong to a child document.
    1587             :    */
    1588             :   void GetCrossDocChildLists(nsTArray<ChildList>* aLists);
    1589             : 
    1590             :   // The individual concrete child lists.
    1591             :   static const ChildListID kPrincipalList = mozilla::layout::kPrincipalList;
    1592             :   static const ChildListID kAbsoluteList = mozilla::layout::kAbsoluteList;
    1593             :   static const ChildListID kBulletList = mozilla::layout::kBulletList;
    1594             :   static const ChildListID kCaptionList = mozilla::layout::kCaptionList;
    1595             :   static const ChildListID kColGroupList = mozilla::layout::kColGroupList;
    1596             :   static const ChildListID kExcessOverflowContainersList = mozilla::layout::kExcessOverflowContainersList;
    1597             :   static const ChildListID kFixedList = mozilla::layout::kFixedList;
    1598             :   static const ChildListID kFloatList = mozilla::layout::kFloatList;
    1599             :   static const ChildListID kOverflowContainersList = mozilla::layout::kOverflowContainersList;
    1600             :   static const ChildListID kOverflowList = mozilla::layout::kOverflowList;
    1601             :   static const ChildListID kOverflowOutOfFlowList = mozilla::layout::kOverflowOutOfFlowList;
    1602             :   static const ChildListID kPopupList = mozilla::layout::kPopupList;
    1603             :   static const ChildListID kPushedFloatsList = mozilla::layout::kPushedFloatsList;
    1604             :   static const ChildListID kSelectPopupList = mozilla::layout::kSelectPopupList;
    1605             :   static const ChildListID kBackdropList = mozilla::layout::kBackdropList;
    1606             :   // A special alias for kPrincipalList that do not request reflow.
    1607             :   static const ChildListID kNoReflowPrincipalList = mozilla::layout::kNoReflowPrincipalList;
    1608             : 
    1609             :   /**
    1610             :    * Child frames are linked together in a doubly-linked list
    1611             :    */
    1612       25098 :   nsIFrame* GetNextSibling() const { return mNextSibling; }
    1613         528 :   void SetNextSibling(nsIFrame* aNextSibling) {
    1614         528 :     NS_ASSERTION(this != aNextSibling, "Creating a circular frame list, this is very bad.");
    1615         528 :     if (mNextSibling && mNextSibling->GetPrevSibling() == this) {
    1616          80 :       mNextSibling->mPrevSibling = nullptr;
    1617             :     }
    1618         528 :     mNextSibling = aNextSibling;
    1619         528 :     if (mNextSibling) {
    1620         278 :       mNextSibling->mPrevSibling = this;
    1621             :     }
    1622         528 :   }
    1623             : 
    1624         266 :   nsIFrame* GetPrevSibling() const { return mPrevSibling; }
    1625             : 
    1626             :   /**
    1627             :    * Builds the display lists for the content represented by this frame
    1628             :    * and its descendants. The background+borders of this element must
    1629             :    * be added first, before any other content.
    1630             :    *
    1631             :    * This should only be called by methods in nsFrame. Instead of calling this
    1632             :    * directly, call either BuildDisplayListForStackingContext or
    1633             :    * BuildDisplayListForChild.
    1634             :    *
    1635             :    * See nsDisplayList.h for more information about display lists.
    1636             :    *
    1637             :    * @param aDirtyRect content outside this rectangle can be ignored; the
    1638             :    * rectangle is in frame coordinates
    1639             :    */
    1640          13 :   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
    1641             :                                 const nsRect&           aDirtyRect,
    1642          13 :                                 const nsDisplayListSet& aLists) {}
    1643             :   /**
    1644             :    * Displays the caret onto the given display list builder. The caret is
    1645             :    * painted on top of the rest of the display list items.
    1646             :    *
    1647             :    * @param aDirtyRect is the dirty rectangle that we're repainting.
    1648             :    */
    1649             :   void DisplayCaret(nsDisplayListBuilder* aBuilder,
    1650             :                     const nsRect&         aDirtyRect,
    1651             :                     nsDisplayList*        aList);
    1652             : 
    1653             :   /**
    1654             :    * Get the preferred caret color at the offset.
    1655             :    *
    1656             :    * @param aOffset is offset of the content.
    1657             :    */
    1658             :   virtual nscolor GetCaretColorAt(int32_t aOffset);
    1659             : 
    1660             : 
    1661        1111 :   bool IsThemed(nsITheme::Transparency* aTransparencyState = nullptr) const {
    1662        1111 :     return IsThemed(StyleDisplay(), aTransparencyState);
    1663             :   }
    1664        7757 :   bool IsThemed(const nsStyleDisplay* aDisp,
    1665             :                   nsITheme::Transparency* aTransparencyState = nullptr) const {
    1666        7757 :     nsIFrame* mutable_this = const_cast<nsIFrame*>(this);
    1667        7757 :     if (!aDisp->mAppearance)
    1668        7260 :       return false;
    1669         497 :     nsPresContext* pc = PresContext();
    1670         497 :     nsITheme *theme = pc->GetTheme();
    1671         994 :     if(!theme ||
    1672         497 :        !theme->ThemeSupportsWidget(pc, mutable_this, aDisp->mAppearance))
    1673           0 :       return false;
    1674         497 :     if (aTransparencyState) {
    1675         101 :       *aTransparencyState =
    1676         101 :         theme->GetWidgetTransparency(mutable_this, aDisp->mAppearance);
    1677             :     }
    1678         497 :     return true;
    1679             :   }
    1680             : 
    1681             :   /**
    1682             :    * Builds a display list for the content represented by this frame,
    1683             :    * treating this frame as the root of a stacking context.
    1684             :    * @param aDirtyRect content outside this rectangle can be ignored; the
    1685             :    * rectangle is in frame coordinates
    1686             :    */
    1687             :   void BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
    1688             :                                           const nsRect&         aDirtyRect,
    1689             :                                           nsDisplayList*        aList);
    1690             : 
    1691             :   enum {
    1692             :     DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT = 0x01,
    1693             :     DISPLAY_CHILD_FORCE_STACKING_CONTEXT = 0x02,
    1694             :     DISPLAY_CHILD_INLINE = 0x04
    1695             :   };
    1696             :   /**
    1697             :    * Adjusts aDirtyRect for the child's offset, checks that the dirty rect
    1698             :    * actually intersects the child (or its descendants), calls BuildDisplayList
    1699             :    * on the child if necessary, and puts things in the right lists if the child
    1700             :    * is positioned.
    1701             :    *
    1702             :    * @param aFlags combination of DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT,
    1703             :    *    DISPLAY_CHILD_FORCE_STACKING_CONTEXT and DISPLAY_CHILD_INLINE
    1704             :    */
    1705             :   void BuildDisplayListForChild(nsDisplayListBuilder*   aBuilder,
    1706             :                                 nsIFrame*               aChild,
    1707             :                                 const nsRect&           aDirtyRect,
    1708             :                                 const nsDisplayListSet& aLists,
    1709             :                                 uint32_t                aFlags = 0);
    1710             : 
    1711           0 :   bool RefusedAsyncAnimation() const
    1712             :   {
    1713           0 :     return GetProperty(RefusedAsyncAnimationProperty());
    1714             :   }
    1715             : 
    1716             :   /**
    1717             :    * Returns true if this frame is transformed (e.g. has CSS or SVG transforms)
    1718             :    * or if its parent is an SVG frame that has children-only transforms (e.g.
    1719             :    * an SVG viewBox attribute) or if its transform-style is preserve-3d or
    1720             :    * the frame has transform animations.
    1721             :    *
    1722             :    * @param aStyleDisplay:  If the caller has this->StyleDisplay(), providing
    1723             :    *   it here will improve performance.
    1724             :    * @param aEffectSet: This function may need to look up EffectSet property.
    1725             :    *   If a caller already have one, pass it in can save property look up
    1726             :    *   time; otherwise, just left it as nullptr.
    1727             :    */
    1728             :   bool IsTransformed(const nsStyleDisplay* aStyleDisplay, mozilla::EffectSet* aEffectSet = nullptr) const;
    1729       28330 :   bool IsTransformed(mozilla::EffectSet* aEffectSet = nullptr) const {
    1730       28330 :     return IsTransformed(StyleDisplay(), aEffectSet);
    1731             :   }
    1732             : 
    1733             :   /**
    1734             :    * True if this frame has any animation of transform in effect.
    1735             :    *
    1736             :    * @param aEffectSet: This function may need to look up EffectSet property.
    1737             :    *   If a caller already have one, pass it in can save property look up
    1738             :    *   time; otherwise, just left it as nullptr.
    1739             :    */
    1740             :   bool HasAnimationOfTransform(mozilla::EffectSet* aEffectSet = nullptr) const;
    1741             : 
    1742             :   /**
    1743             :    * Returns true if the frame is translucent or the frame has opacity
    1744             :    * animations for the purposes of creating a stacking context.
    1745             :    *
    1746             :    * @param aEffectSet: This function may need to look up EffectSet property.
    1747             :    *   If a caller already have one, pass it in can save property look up
    1748             :    *   time; otherwise, just left it as nullptr.
    1749             :    */
    1750        1364 :   bool HasOpacity(mozilla::EffectSet* aEffectSet = nullptr) const
    1751             :   {
    1752        1364 :     return HasOpacityInternal(1.0f, aEffectSet);
    1753             :   }
    1754             :   /**
    1755             :    * Returns true if the frame is translucent for display purposes.
    1756             :    *
    1757             :    * @param aEffectSet: This function may need to look up EffectSet property.
    1758             :    *   If a caller already have one, pass it in can save property look up
    1759             :    *   time; otherwise, just left it as nullptr.
    1760             :    */
    1761         613 :   bool HasVisualOpacity(mozilla::EffectSet* aEffectSet = nullptr) const
    1762             :   {
    1763             :     // Treat an opacity value of 0.99 and above as opaque.  This is an
    1764             :     // optimization aimed at Web content which use opacity:0.99 as a hint for
    1765             :     // creating a stacking context only.
    1766         613 :     return HasOpacityInternal(0.99f, aEffectSet);
    1767             :   }
    1768             : 
    1769             :    /**
    1770             :    * Return true if this frame might be using a transform getter.
    1771             :    */
    1772           0 :   virtual bool HasTransformGetter() const { return false; }
    1773             : 
    1774             :   /**
    1775             :    * Returns true if this frame is an SVG frame that has SVG transforms applied
    1776             :    * to it, or if its parent frame is an SVG frame that has children-only
    1777             :    * transforms (e.g. an SVG viewBox attribute).
    1778             :    * If aOwnTransforms is non-null and the frame has its own SVG transforms,
    1779             :    * aOwnTransforms will be set to these transforms. If aFromParentTransforms
    1780             :    * is non-null and the frame has an SVG parent with children-only transforms,
    1781             :    * then aFromParentTransforms will be set to these transforms.
    1782             :    */
    1783             :   virtual bool IsSVGTransformed(Matrix *aOwnTransforms = nullptr,
    1784             :                                 Matrix *aFromParentTransforms = nullptr) const;
    1785             : 
    1786             :   /**
    1787             :    * Returns whether this frame will attempt to extend the 3d transforms of its
    1788             :    * children. This requires transform-style: preserve-3d, as well as no clipping
    1789             :    * or svg effects.
    1790             :    *
    1791             :    * @param aStyleDisplay:  If the caller has this->StyleDisplay(), providing
    1792             :    *   it here will improve performance.
    1793             :    *
    1794             :    * @param aEffectSet: This function may need to look up EffectSet property.
    1795             :    *   If a caller already have one, pass it in can save property look up
    1796             :    *   time; otherwise, just left it as nullptr.
    1797             :    */
    1798             :   bool Extend3DContext(const nsStyleDisplay* aStyleDisplay,
    1799             :                        mozilla::EffectSet* aEffectSet = nullptr) const;
    1800        4051 :   bool Extend3DContext(mozilla::EffectSet* aEffectSet = nullptr) const {
    1801        4051 :     return Extend3DContext(StyleDisplay(), aEffectSet);
    1802             :   }
    1803             : 
    1804             :   /**
    1805             :    * Returns whether this frame has a parent that Extend3DContext() and has
    1806             :    * its own transform (or hidden backface) to be combined with the parent's
    1807             :    * transform.
    1808             :    *
    1809             :    * @param aStyleDisplay:  If the caller has this->StyleDisplay(), providing
    1810             :    *   it here will improve performance.
    1811             :    * @param aEffectSet: This function may need to look up EffectSet property.
    1812             :    *   If a caller already have one, pass it in can save property look up
    1813             :    *   time; otherwise, just left it as nullptr.
    1814             :    */
    1815             :   bool Combines3DTransformWithAncestors(const nsStyleDisplay* aStyleDisplay,
    1816             :                                         mozilla::EffectSet* aEffectSet = nullptr) const;
    1817        1075 :   bool Combines3DTransformWithAncestors(mozilla::EffectSet* aEffectSet = nullptr) const {
    1818        1075 :     return Combines3DTransformWithAncestors(StyleDisplay(), aEffectSet);
    1819             :   }
    1820             : 
    1821             :   /**
    1822             :    * Returns whether this frame has a hidden backface and has a parent that
    1823             :    * Extend3DContext(). This is useful because in some cases the hidden
    1824             :    * backface can safely be ignored if it could not be visible anyway.
    1825             :    *
    1826             :    * @param aEffectSet: This function may need to look up EffectSet property.
    1827             :    *   If a caller already have one, pass it in can save property look up
    1828             :    *   time; otherwise, just left it as nullptr.
    1829             :    */
    1830             :   bool In3DContextAndBackfaceIsHidden(mozilla::EffectSet* aEffectSet = nullptr) const;
    1831             : 
    1832        2328 :   bool IsPreserve3DLeaf(const nsStyleDisplay* aStyleDisplay,
    1833             :                         mozilla::EffectSet* aEffectSet = nullptr) const {
    1834        2328 :     return Combines3DTransformWithAncestors(aStyleDisplay) &&
    1835        2328 :            !Extend3DContext(aStyleDisplay, aEffectSet);
    1836             :   }
    1837          24 :   bool IsPreserve3DLeaf(mozilla::EffectSet* aEffectSet = nullptr) const {
    1838          24 :     return IsPreserve3DLeaf(StyleDisplay(), aEffectSet);
    1839             :   }
    1840             : 
    1841             :   bool HasPerspective(const nsStyleDisplay* aStyleDisplay,
    1842             :                       mozilla::EffectSet* aEffectSet = nullptr) const;
    1843         952 :   bool HasPerspective(mozilla::EffectSet* aEffectSet = nullptr) const {
    1844         952 :     return HasPerspective(StyleDisplay(), aEffectSet);
    1845             :   }
    1846             : 
    1847        2596 :   bool ChildrenHavePerspective(const nsStyleDisplay* aStyleDisplay) const {
    1848        2596 :     MOZ_ASSERT(aStyleDisplay == StyleDisplay());
    1849        2596 :     return aStyleDisplay->HasPerspectiveStyle();
    1850             :   }
    1851         886 :   bool ChildrenHavePerspective() const {
    1852         886 :     return ChildrenHavePerspective(StyleDisplay());
    1853             :   }
    1854             : 
    1855             :   /**
    1856             :    * Includes the overflow area of all descendants that participate in the current
    1857             :    * 3d context into aOverflowAreas.
    1858             :    */
    1859             :   void ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas);
    1860             : 
    1861             :   void RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame,
    1862             :                                             mozilla::EffectSet* aEffectSet = nullptr);
    1863             : 
    1864             :   /**
    1865             :    * Returns the number of ancestors between this and the root of our frame tree
    1866             :    */
    1867             :   uint32_t GetDepthInFrameTree() const;
    1868             : 
    1869             :   /**
    1870             :    * Event handling of GUI events.
    1871             :    *
    1872             :    * @param   aEvent event structure describing the type of event and rge widget
    1873             :    *            where the event originated
    1874             :    *          The |point| member of this is in the coordinate system of the
    1875             :    *          view returned by GetOffsetFromView.
    1876             :    * @param   aEventStatus a return value indicating whether the event was handled
    1877             :    *            and whether default processing should be done
    1878             :    *
    1879             :    * XXX From a frame's perspective it's unclear what the effect of the event status
    1880             :    * is. Does it cause the event to continue propagating through the frame hierarchy
    1881             :    * or is it just returned to the widgets?
    1882             :    *
    1883             :    * @see     WidgetGUIEvent
    1884             :    * @see     nsEventStatus
    1885             :    */
    1886             :   virtual nsresult  HandleEvent(nsPresContext* aPresContext,
    1887             :                                 mozilla::WidgetGUIEvent* aEvent,
    1888             :                                 nsEventStatus* aEventStatus) = 0;
    1889             : 
    1890             :   virtual nsresult  GetContentForEvent(mozilla::WidgetEvent* aEvent,
    1891             :                                        nsIContent** aContent) = 0;
    1892             : 
    1893             :   // This structure keeps track of the content node and offsets associated with
    1894             :   // a point; there is a primary and a secondary offset associated with any
    1895             :   // point.  The primary and secondary offsets differ when the point is over a
    1896             :   // non-text object.  The primary offset is the expected position of the
    1897             :   // cursor calculated from a point; the secondary offset, when it is different,
    1898             :   // indicates that the point is in the boundaries of some selectable object.
    1899             :   // Note that the primary offset can be after the secondary offset; for places
    1900             :   // that need the beginning and end of the object, the StartOffset and
    1901             :   // EndOffset helpers can be used.
    1902           0 :   struct MOZ_STACK_CLASS ContentOffsets
    1903             :   {
    1904           0 :     ContentOffsets() : offset(0)
    1905             :                      , secondaryOffset(0)
    1906           0 :                      , associate(mozilla::CARET_ASSOCIATE_BEFORE) {}
    1907           0 :     bool IsNull() { return !content; }
    1908             :     // Helpers for places that need the ends of the offsets and expect them in
    1909             :     // numerical order, as opposed to wanting the primary and secondary offsets
    1910           0 :     int32_t StartOffset() { return std::min(offset, secondaryOffset); }
    1911           0 :     int32_t EndOffset() { return std::max(offset, secondaryOffset); }
    1912             : 
    1913             :     nsCOMPtr<nsIContent> content;
    1914             :     int32_t offset;
    1915             :     int32_t secondaryOffset;
    1916             :     // This value indicates whether the associated content is before or after
    1917             :     // the offset; the most visible use is to allow the caret to know which line
    1918             :     // to display on.
    1919             :     mozilla::CaretAssociationHint associate;
    1920             :   };
    1921             :   enum {
    1922             :     IGNORE_SELECTION_STYLE = 0x01,
    1923             :     // Treat visibility:hidden frames as non-selectable
    1924             :     SKIP_HIDDEN = 0x02
    1925             :   };
    1926             :   /**
    1927             :    * This function calculates the content offsets for selection relative to
    1928             :    * a point.  Note that this should generally only be callled on the event
    1929             :    * frame associated with an event because this function does not account
    1930             :    * for frame lists other than the primary one.
    1931             :    * @param aPoint point relative to this frame
    1932             :    */
    1933             :   ContentOffsets GetContentOffsetsFromPoint(nsPoint aPoint,
    1934             :                                             uint32_t aFlags = 0);
    1935             : 
    1936           0 :   virtual ContentOffsets GetContentOffsetsFromPointExternal(nsPoint aPoint,
    1937             :                                                             uint32_t aFlags = 0)
    1938           0 :   { return GetContentOffsetsFromPoint(aPoint, aFlags); }
    1939             : 
    1940             :   /**
    1941             :    * Ensure that aImage gets notifed when the underlying image request loads
    1942             :    * or animates.
    1943             :    */
    1944             :   void AssociateImage(const nsStyleImage& aImage, nsPresContext* aPresContext);
    1945             : 
    1946             :   /**
    1947             :    * This structure holds information about a cursor. mContainer represents a
    1948             :    * loaded image that should be preferred. If it is not possible to use it, or
    1949             :    * if it is null, mCursor should be used.
    1950             :    */
    1951           0 :   struct MOZ_STACK_CLASS Cursor {
    1952             :     nsCOMPtr<imgIContainer> mContainer;
    1953             :     int32_t                 mCursor;
    1954             :     bool                    mHaveHotspot;
    1955             :     bool                    mLoading;
    1956             :     float                   mHotspotX, mHotspotY;
    1957             :   };
    1958             :   /**
    1959             :    * Get the cursor for a given frame.
    1960             :    */
    1961             :   virtual nsresult  GetCursor(const nsPoint&  aPoint,
    1962             :                               Cursor&         aCursor) = 0;
    1963             : 
    1964             :   /**
    1965             :    * Get a point (in the frame's coordinate space) given an offset into
    1966             :    * the content. This point should be on the baseline of text with
    1967             :    * the correct horizontal offset
    1968             :    */
    1969             :   virtual nsresult  GetPointFromOffset(int32_t                  inOffset,
    1970             :                                        nsPoint*                 outPoint) = 0;
    1971             : 
    1972             :   /**
    1973             :    * Get a list of character rects in a given range.
    1974             :    * This is similar version of GetPointFromOffset.
    1975             :    */
    1976             :   virtual nsresult  GetCharacterRectsInRange(int32_t aInOffset,
    1977             :                                              int32_t aLength,
    1978             :                                              nsTArray<nsRect>& aRects) = 0;
    1979             : 
    1980             :   /**
    1981             :    * Get the child frame of this frame which contains the given
    1982             :    * content offset. outChildFrame may be this frame, or nullptr on return.
    1983             :    * outContentOffset returns the content offset relative to the start
    1984             :    * of the returned node. You can also pass a hint which tells the method
    1985             :    * to stick to the end of the first found frame or the beginning of the
    1986             :    * next in case the offset falls on a boundary.
    1987             :    */
    1988             :   virtual nsresult GetChildFrameContainingOffset(int32_t    inContentOffset,
    1989             :                                                  bool       inHint,//false stick left
    1990             :                                                  int32_t*   outFrameContentOffset,
    1991             :                                                  nsIFrame** outChildFrame) = 0;
    1992             : 
    1993             :  /**
    1994             :    * Get the current frame-state value for this frame. aResult is
    1995             :    * filled in with the state bits.
    1996             :    */
    1997      112151 :   nsFrameState GetStateBits() const { return mState; }
    1998             : 
    1999             :   /**
    2000             :    * Update the current frame-state value for this frame.
    2001             :    */
    2002        9103 :   void AddStateBits(nsFrameState aBits) { mState |= aBits; }
    2003        6049 :   void RemoveStateBits(nsFrameState aBits) { mState &= ~aBits; }
    2004           0 :   void AddOrRemoveStateBits(nsFrameState aBits, bool aVal) {
    2005           0 :     aVal ? AddStateBits(aBits) : RemoveStateBits(aBits);
    2006           0 :   }
    2007             : 
    2008             :   /**
    2009             :    * Checks if the current frame-state includes all of the listed bits
    2010             :    */
    2011        1791 :   bool HasAllStateBits(nsFrameState aBits) const
    2012             :   {
    2013        1791 :     return (mState & aBits) == aBits;
    2014             :   }
    2015             : 
    2016             :   /**
    2017             :    * Checks if the current frame-state includes any of the listed bits
    2018             :    */
    2019       19568 :   bool HasAnyStateBits(nsFrameState aBits) const
    2020             :   {
    2021       19568 :     return mState & aBits;
    2022             :   }
    2023             : 
    2024             :   /**
    2025             :    * This call is invoked on the primary frame for a character data content
    2026             :    * node, when it is changed in the content tree.
    2027             :    */
    2028             :   virtual nsresult  CharacterDataChanged(CharacterDataChangeInfo* aInfo) = 0;
    2029             : 
    2030             :   /**
    2031             :    * This call is invoked when the value of a content objects's attribute
    2032             :    * is changed.
    2033             :    * The first frame that maps that content is asked to deal
    2034             :    * with the change by doing whatever is appropriate.
    2035             :    *
    2036             :    * @param aNameSpaceID the namespace of the attribute
    2037             :    * @param aAttribute the atom name of the attribute
    2038             :    * @param aModType Whether or not the attribute was added, changed, or removed.
    2039             :    *   The constants are defined in nsIDOMMutationEvent.h.
    2040             :    */
    2041             :   virtual nsresult  AttributeChanged(int32_t         aNameSpaceID,
    2042             :                                      nsIAtom*        aAttribute,
    2043             :                                      int32_t         aModType) = 0;
    2044             : 
    2045             :   /**
    2046             :    * When the content states of a content object change, this method is invoked
    2047             :    * on the primary frame of that content object.
    2048             :    *
    2049             :    * @param aStates the changed states
    2050             :    */
    2051             :   virtual void ContentStatesChanged(mozilla::EventStates aStates);
    2052             : 
    2053             :   /**
    2054             :    * Return how your frame can be split.
    2055             :    */
    2056             :   virtual nsSplittableType GetSplittableType() const = 0;
    2057             : 
    2058             :   /**
    2059             :    * Continuation member functions
    2060             :    */
    2061             :   virtual nsIFrame* GetPrevContinuation() const = 0;
    2062             :   virtual void SetPrevContinuation(nsIFrame*) = 0;
    2063             :   virtual nsIFrame* GetNextContinuation() const = 0;
    2064             :   virtual void SetNextContinuation(nsIFrame*) = 0;
    2065          32 :   virtual nsIFrame* FirstContinuation() const {
    2066          32 :     return const_cast<nsIFrame*>(this);
    2067             :   }
    2068          13 :   virtual nsIFrame* LastContinuation() const {
    2069          13 :     return const_cast<nsIFrame*>(this);
    2070             :   }
    2071             : 
    2072             :   /**
    2073             :    * GetTailContinuation gets the last non-overflow-container continuation
    2074             :    * in the continuation chain, i.e. where the next sibling element
    2075             :    * should attach).
    2076             :    */
    2077             :   nsIFrame* GetTailContinuation();
    2078             : 
    2079             :   /**
    2080             :    * Flow member functions
    2081             :    */
    2082             :   virtual nsIFrame* GetPrevInFlowVirtual() const = 0;
    2083         408 :   nsIFrame* GetPrevInFlow() const { return GetPrevInFlowVirtual(); }
    2084             :   virtual void SetPrevInFlow(nsIFrame*) = 0;
    2085             : 
    2086             :   virtual nsIFrame* GetNextInFlowVirtual() const = 0;
    2087         515 :   nsIFrame* GetNextInFlow() const { return GetNextInFlowVirtual(); }
    2088             :   virtual void SetNextInFlow(nsIFrame*) = 0;
    2089             : 
    2090             :   /**
    2091             :    * Return the first frame in our current flow.
    2092             :    */
    2093           0 :   virtual nsIFrame* FirstInFlow() const {
    2094           0 :     return const_cast<nsIFrame*>(this);
    2095             :   }
    2096             : 
    2097             :   /**
    2098             :    * Return the last frame in our current flow.
    2099             :    */
    2100          21 :   virtual nsIFrame* LastInFlow() const {
    2101          21 :     return const_cast<nsIFrame*>(this);
    2102             :   }
    2103             : 
    2104             :   /**
    2105             :    * Note: "width" in the names and comments on the following methods
    2106             :    * means inline-size, which could be height in vertical layout
    2107             :    */
    2108             : 
    2109             :   /**
    2110             :    * Mark any stored intrinsic width information as dirty (requiring
    2111             :    * re-calculation).  Note that this should generally not be called
    2112             :    * directly; nsPresShell::FrameNeedsReflow will call it instead.
    2113             :    */
    2114             :   virtual void MarkIntrinsicISizesDirty() = 0;
    2115             : 
    2116             :   /**
    2117             :    * Get the min-content intrinsic inline size of the frame.  This must be
    2118             :    * less than or equal to the max-content intrinsic inline size.
    2119             :    *
    2120             :    * This is *not* affected by the CSS 'min-width', 'width', and
    2121             :    * 'max-width' properties on this frame, but it is affected by the
    2122             :    * values of those properties on this frame's descendants.  (It may be
    2123             :    * called during computation of the values of those properties, so it
    2124             :    * cannot depend on any values in the nsStylePosition for this frame.)
    2125             :    *
    2126             :    * The value returned should **NOT** include the space required for
    2127             :    * padding and border.
    2128             :    *
    2129             :    * Note that many frames will cache the result of this function call
    2130             :    * unless MarkIntrinsicISizesDirty is called.
    2131             :    *
    2132             :    * It is not acceptable for a frame to mark itself dirty when this
    2133             :    * method is called.
    2134             :    *
    2135             :    * This method must not return a negative value.
    2136             :    */
    2137             :   virtual nscoord GetMinISize(gfxContext *aRenderingContext) = 0;
    2138             : 
    2139             :   /**
    2140             :    * Get the max-content intrinsic inline size of the frame.  This must be
    2141             :    * greater than or equal to the min-content intrinsic inline size.
    2142             :    *
    2143             :    * Otherwise, all the comments for |GetMinISize| above apply.
    2144             :    */
    2145             :   virtual nscoord GetPrefISize(gfxContext *aRenderingContext) = 0;
    2146             : 
    2147             :   /**
    2148             :    * |InlineIntrinsicISize| represents the intrinsic width information
    2149             :    * in inline layout.  Code that determines the intrinsic width of a
    2150             :    * region of inline layout accumulates the result into this structure.
    2151             :    * This pattern is needed because we need to maintain state
    2152             :    * information about whitespace (for both collapsing and trimming).
    2153             :    */
    2154          67 :   struct InlineIntrinsicISizeData {
    2155          67 :     InlineIntrinsicISizeData()
    2156          67 :       : mLine(nullptr)
    2157             :       , mLineContainer(nullptr)
    2158             :       , mPrevLines(0)
    2159             :       , mCurrentLine(0)
    2160             :       , mTrailingWhitespace(0)
    2161          67 :       , mSkipWhitespace(true)
    2162          67 :     {}
    2163             : 
    2164             :     // The line. This may be null if the inlines are not associated with
    2165             :     // a block or if we just don't know the line.
    2166             :     const nsLineList_iterator* mLine;
    2167             : 
    2168             :     // The line container. Private, to ensure we always use SetLineContainer
    2169             :     // to update it (so that we have a chance to store the mLineContainerWM).
    2170             :     //
    2171             :     // Note that nsContainerFrame::DoInlineIntrinsicISize will clear the
    2172             :     // |mLine| and |mLineContainer| fields when following a next-in-flow link,
    2173             :     // so we must not assume these can always be dereferenced.
    2174             :   private:
    2175             :     nsIFrame* mLineContainer;
    2176             : 
    2177             :     // Setter and getter for the lineContainer field:
    2178             :   public:
    2179          67 :     void SetLineContainer(nsIFrame* aLineContainer)
    2180             :     {
    2181          67 :       mLineContainer = aLineContainer;
    2182          67 :       if (mLineContainer) {
    2183          67 :         mLineContainerWM = mLineContainer->GetWritingMode();
    2184             :       }
    2185          67 :     }
    2186         114 :     nsIFrame* LineContainer() const { return mLineContainer; }
    2187             : 
    2188             :     // The maximum intrinsic width for all previous lines.
    2189             :     nscoord mPrevLines;
    2190             : 
    2191             :     // The maximum intrinsic width for the current line.  At a line
    2192             :     // break (mandatory for preferred width; allowed for minimum width),
    2193             :     // the caller should call |Break()|.
    2194             :     nscoord mCurrentLine;
    2195             : 
    2196             :     // This contains the width of the trimmable whitespace at the end of
    2197             :     // |mCurrentLine|; it is zero if there is no such whitespace.
    2198             :     nscoord mTrailingWhitespace;
    2199             : 
    2200             :     // True if initial collapsable whitespace should be skipped.  This
    2201             :     // should be true at the beginning of a block, after hard breaks
    2202             :     // and when the last text ended with whitespace.
    2203             :     bool mSkipWhitespace;
    2204             : 
    2205             :     // Writing mode of the line container (stored here so that we don't
    2206             :     // lose track of it if the mLineContainer field is reset).
    2207             :     mozilla::WritingMode mLineContainerWM;
    2208             : 
    2209             :     // Floats encountered in the lines.
    2210             :     class FloatInfo {
    2211             :     public:
    2212           0 :       FloatInfo(const nsIFrame* aFrame, nscoord aWidth)
    2213           0 :         : mFrame(aFrame), mWidth(aWidth)
    2214           0 :       { }
    2215           0 :       const nsIFrame* Frame() const { return mFrame; }
    2216           0 :       nscoord         Width() const { return mWidth; }
    2217             : 
    2218             :     private:
    2219             :       const nsIFrame* mFrame;
    2220             :       nscoord         mWidth;
    2221             :     };
    2222             : 
    2223             :     nsTArray<FloatInfo> mFloats;
    2224             :   };
    2225             : 
    2226          35 :   struct InlineMinISizeData : public InlineIntrinsicISizeData {
    2227          35 :     InlineMinISizeData()
    2228          35 :       : mAtStartOfLine(true)
    2229          35 :     {}
    2230             : 
    2231             :     // The default implementation for nsIFrame::AddInlineMinISize.
    2232             :     void DefaultAddInlineMinISize(nsIFrame* aFrame,
    2233             :                                   nscoord   aISize,
    2234             :                                   bool      aAllowBreak = true);
    2235             : 
    2236             :     // We need to distinguish forced and optional breaks for cases where the
    2237             :     // current line total is negative.  When it is, we need to ignore
    2238             :     // optional breaks to prevent min-width from ending up bigger than
    2239             :     // pref-width.
    2240             :     void ForceBreak();
    2241             : 
    2242             :     // If the break here is actually taken, aHyphenWidth must be added to the
    2243             :     // width of the current line.
    2244             :     void OptionallyBreak(nscoord aHyphenWidth = 0);
    2245             : 
    2246             :     // Whether we're currently at the start of the line.  If we are, we
    2247             :     // can't break (for example, between the text-indent and the first
    2248             :     // word).
    2249             :     bool mAtStartOfLine;
    2250             :   };
    2251             : 
    2252          32 :   struct InlinePrefISizeData : public InlineIntrinsicISizeData {
    2253             :     typedef mozilla::StyleClear StyleClear;
    2254             : 
    2255          32 :     InlinePrefISizeData()
    2256          32 :       : mLineIsEmpty(true)
    2257          32 :     {}
    2258             : 
    2259             :     /**
    2260             :      * Finish the current line and start a new line.
    2261             :      *
    2262             :      * @param aBreakType controls whether isize of floats are considered
    2263             :      * and what floats are kept for the next line:
    2264             :      *  * |None| skips handling floats, which means no floats are
    2265             :      *    removed, and isizes of floats are not considered either.
    2266             :      *  * |Both| takes floats into consideration when computing isize
    2267             :      *    of the current line, and removes all floats after that.
    2268             :      *  * |Left| and |Right| do the same as |Both| except that they only
    2269             :      *    remove floats on the given side, and any floats on the other
    2270             :      *    side that are prior to a float on the given side that has a
    2271             :      *    'clear' property that clears them.
    2272             :      * All other values of StyleClear must be converted to the four
    2273             :      * physical values above for this function.
    2274             :      */
    2275             :     void ForceBreak(StyleClear aBreakType = StyleClear::Both);
    2276             : 
    2277             :     // The default implementation for nsIFrame::AddInlinePrefISize.
    2278             :     void DefaultAddInlinePrefISize(nscoord aISize);
    2279             : 
    2280             :     // True if the current line contains nothing other than placeholders.
    2281             :     bool mLineIsEmpty;
    2282             :   };
    2283             : 
    2284             :   /**
    2285             :    * Add the intrinsic minimum width of a frame in a way suitable for
    2286             :    * use in inline layout to an |InlineIntrinsicISizeData| object that
    2287             :    * represents the intrinsic width information of all the previous
    2288             :    * frames in the inline layout region.
    2289             :    *
    2290             :    * All *allowed* breakpoints within the frame determine what counts as
    2291             :    * a line for the |InlineIntrinsicISizeData|.  This means that
    2292             :    * |aData->mTrailingWhitespace| will always be zero (unlike for
    2293             :    * AddInlinePrefISize).
    2294             :    *
    2295             :    * All the comments for |GetMinISize| apply, except that this function
    2296             :    * is responsible for adding padding, border, and margin and for
    2297             :    * considering the effects of 'width', 'min-width', and 'max-width'.
    2298             :    *
    2299             :    * This may be called on any frame.  Frames that do not participate in
    2300             :    * line breaking can inherit the default implementation on nsFrame,
    2301             :    * which calls |GetMinISize|.
    2302             :    */
    2303             :   virtual void
    2304             :   AddInlineMinISize(gfxContext *aRenderingContext,
    2305             :                     InlineMinISizeData *aData) = 0;
    2306             : 
    2307             :   /**
    2308             :    * Add the intrinsic preferred width of a frame in a way suitable for
    2309             :    * use in inline layout to an |InlineIntrinsicISizeData| object that
    2310             :    * represents the intrinsic width information of all the previous
    2311             :    * frames in the inline layout region.
    2312             :    *
    2313             :    * All the comments for |AddInlineMinISize| and |GetPrefISize| apply,
    2314             :    * except that this fills in an |InlineIntrinsicISizeData| structure
    2315             :    * based on using all *mandatory* breakpoints within the frame.
    2316             :    */
    2317             :   virtual void
    2318             :   AddInlinePrefISize(gfxContext *aRenderingContext,
    2319             :                      InlinePrefISizeData *aData) = 0;
    2320             : 
    2321             :   /**
    2322             :    * Return the horizontal components of padding, border, and margin
    2323             :    * that contribute to the intrinsic width that applies to the parent.
    2324             :    */
    2325             :   struct IntrinsicISizeOffsetData {
    2326             :     nscoord hPadding, hBorder, hMargin;
    2327             :     float hPctPadding, hPctMargin;
    2328             : 
    2329          25 :     IntrinsicISizeOffsetData()
    2330          25 :       : hPadding(0), hBorder(0), hMargin(0)
    2331          25 :       , hPctPadding(0.0f), hPctMargin(0.0f)
    2332          25 :     {}
    2333             :   };
    2334             :   virtual IntrinsicISizeOffsetData IntrinsicISizeOffsets() = 0;
    2335             : 
    2336             :   /**
    2337             :    * Return the bsize components of padding, border, and margin
    2338             :    * that contribute to the intrinsic width that applies to the parent.
    2339             :    */
    2340             :   IntrinsicISizeOffsetData IntrinsicBSizeOffsets();
    2341             : 
    2342             :   virtual mozilla::IntrinsicSize GetIntrinsicSize() = 0;
    2343             : 
    2344             :   /**
    2345             :    * Get the intrinsic ratio of this element, or nsSize(0,0) if it has
    2346             :    * no intrinsic ratio.  The intrinsic ratio is the ratio of the
    2347             :    * height/width of a box with an intrinsic size or the intrinsic
    2348             :    * aspect ratio of a scalable vector image without an intrinsic size.
    2349             :    *
    2350             :    * Either one of the sides may be zero, indicating a zero or infinite
    2351             :    * ratio.
    2352             :    */
    2353             :   virtual nsSize GetIntrinsicRatio() = 0;
    2354             : 
    2355             :   /**
    2356             :    * Bit-flags to pass to ComputeSize in |aFlags| parameter.
    2357             :    */
    2358             :   enum ComputeSizeFlags {
    2359             :     eDefault =           0,
    2360             :     /**
    2361             :      * Set if the frame is in a context where non-replaced blocks should
    2362             :      * shrink-wrap (e.g., it's floating, absolutely positioned, or
    2363             :      * inline-block).
    2364             :      */
    2365             :     eShrinkWrap =        1 << 0,
    2366             :     /**
    2367             :      * Set if we'd like to compute our 'auto' bsize, regardless of our actual
    2368             :      * corresponding computed value. (e.g. to get an intrinsic height for flex
    2369             :      * items with "min-height: auto" to use during flexbox layout.)
    2370             :      */
    2371             :     eUseAutoBSize =      1 << 1,
    2372             :     /**
    2373             :      * Indicates that we should clamp the margin-box min-size to the given CB
    2374             :      * size.  This is used for implementing the grid area clamping here:
    2375             :      * https://drafts.csswg.org/css-grid/#min-size-auto
    2376             :      */
    2377             :     eIClampMarginBoxMinSize = 1 << 2, // clamp in our inline axis
    2378             :     eBClampMarginBoxMinSize = 1 << 3, // clamp in our block axis
    2379             :     /**
    2380             :      * The frame is stretching (per CSS Box Alignment) and doesn't have an
    2381             :      * Automatic Minimum Size in the indicated axis.
    2382             :      * (may be used for both flex/grid items, but currently only used for Grid)
    2383             :      * https://drafts.csswg.org/css-grid/#min-size-auto
    2384             :      * https://drafts.csswg.org/css-align-3/#valdef-justify-self-stretch
    2385             :      */
    2386             :     eIApplyAutoMinSize = 1 << 4, // only has an effect when eShrinkWrap is false
    2387             :   };
    2388             : 
    2389             :   /**
    2390             :    * Compute the size that a frame will occupy.  Called while
    2391             :    * constructing the ReflowInput to be used to Reflow the frame,
    2392             :    * in order to fill its mComputedWidth and mComputedHeight member
    2393             :    * variables.
    2394             :    *
    2395             :    * The |height| member of the return value may be
    2396             :    * NS_UNCONSTRAINEDSIZE, but the |width| member must not be.
    2397             :    *
    2398             :    * Note that the reason that border and padding need to be passed
    2399             :    * separately is so that the 'box-sizing' property can be handled.
    2400             :    * Thus aMargin includes absolute positioning offsets as well.
    2401             :    *
    2402             :    * @param aWritingMode  The writing mode to use for the returned size
    2403             :    *                      (need not match this frame's writing mode).
    2404             :    *                      This is also the writing mode of the passed-in
    2405             :    *                      LogicalSize parameters.
    2406             :    * @param aCBSize  The size of the element's containing block.  (Well,
    2407             :    *                 the |height| component isn't really.)
    2408             :    * @param aAvailableWidth  The available width for 'auto' widths.
    2409             :    *                         This is usually the same as aCBSize.width,
    2410             :    *                         but differs in cases such as block
    2411             :    *                         formatting context roots next to floats, or
    2412             :    *                         in some cases of float reflow in quirks
    2413             :    *                         mode.
    2414             :    * @param aMargin  The sum of the vertical / horizontal margins
    2415             :    *                 ***AND*** absolute positioning offsets (top, right,
    2416             :    *                 bottom, left) of the frame, including actual values
    2417             :    *                 resulting from percentages and from the
    2418             :    *                 "hypothetical box" for absolute positioning, but
    2419             :    *                 not including actual values resulting from 'auto'
    2420             :    *                 margins or ignored 'auto' values in absolute
    2421             :    *                 positioning.
    2422             :    * @param aBorder  The sum of the vertical / horizontal border widths
    2423             :    *                 of the frame.
    2424             :    * @param aPadding The sum of the vertical / horizontal margins of
    2425             :    *                 the frame, including actual values resulting from
    2426             :    *                 percentages.
    2427             :    * @param aFlags   Flags to further customize behavior (definitions above).
    2428             :    */
    2429             :   virtual mozilla::LogicalSize
    2430             :   ComputeSize(gfxContext *aRenderingContext,
    2431             :               mozilla::WritingMode aWritingMode,
    2432             :               const mozilla::LogicalSize& aCBSize,
    2433             :               nscoord aAvailableISize,
    2434             :               const mozilla::LogicalSize& aMargin,
    2435             :               const mozilla::LogicalSize& aBorder,
    2436             :               const mozilla::LogicalSize& aPadding,
    2437             :               ComputeSizeFlags aFlags) = 0;
    2438             : 
    2439             :   /**
    2440             :    * Compute a tight bounding rectangle for the frame. This is a rectangle
    2441             :    * that encloses the pixels that are actually drawn. We're allowed to be
    2442             :    * conservative and currently we don't try very hard. The rectangle is
    2443             :    * in appunits and relative to the origin of this frame.
    2444             :    *
    2445             :    * This probably only needs to include frame bounds, glyph bounds, and
    2446             :    * text decorations, but today it sometimes includes other things that
    2447             :    * contribute to visual overflow.
    2448             :    *
    2449             :    * @param aDrawTarget a draw target that can be used if we need
    2450             :    * to do measurement
    2451             :    */
    2452             :   virtual nsRect ComputeTightBounds(DrawTarget* aDrawTarget) const;
    2453             : 
    2454             :   /**
    2455             :    * This function is similar to GetPrefISize and ComputeTightBounds: it
    2456             :    * computes the left and right coordinates of a preferred tight bounding
    2457             :    * rectangle for the frame. This is a rectangle that would enclose the pixels
    2458             :    * that are drawn if we lay out the element without taking any optional line
    2459             :    * breaks. The rectangle is in appunits and relative to the origin of this
    2460             :    * frame. Currently, this function is only implemented for nsBlockFrame and
    2461             :    * nsTextFrame and is used to determine intrinsic widths of MathML token
    2462             :    * elements.
    2463             : 
    2464             :    * @param aContext a rendering context that can be used if we need
    2465             :    * to do measurement
    2466             :    * @param aX      computed left coordinate of the tight bounding rectangle
    2467             :    * @param aXMost  computed intrinsic width of the tight bounding rectangle
    2468             :    *
    2469             :    */
    2470             :   virtual nsresult GetPrefWidthTightBounds(gfxContext* aContext,
    2471             :                                            nscoord* aX,
    2472             :                                            nscoord* aXMost);
    2473             : 
    2474             :   /**
    2475             :    * The frame is given an available size and asked for its desired
    2476             :    * size.  This is the frame's opportunity to reflow its children.
    2477             :    *
    2478             :    * If the frame has the NS_FRAME_IS_DIRTY bit set then it is
    2479             :    * responsible for completely reflowing itself and all of its
    2480             :    * descendants.
    2481             :    *
    2482             :    * Otherwise, if the frame has the NS_FRAME_HAS_DIRTY_CHILDREN bit
    2483             :    * set, then it is responsible for reflowing at least those
    2484             :    * children that have NS_FRAME_HAS_DIRTY_CHILDREN or NS_FRAME_IS_DIRTY
    2485             :    * set.
    2486             :    *
    2487             :    * If a difference in available size from the previous reflow causes
    2488             :    * the frame's size to change, it should reflow descendants as needed.
    2489             :    *
    2490             :    * @param aReflowOutput <i>out</i> parameter where you should return the
    2491             :    *          desired size and ascent/descent info. You should include any
    2492             :    *          space you want for border/padding in the desired size you return.
    2493             :    *
    2494             :    *          It's okay to return a desired size that exceeds the avail
    2495             :    *          size if that's the smallest you can be, i.e. it's your
    2496             :    *          minimum size.
    2497             :    *
    2498             :    *          For an incremental reflow you are responsible for invalidating
    2499             :    *          any area within your frame that needs repainting (including
    2500             :    *          borders). If your new desired size is different than your current
    2501             :    *          size, then your parent frame is responsible for making sure that
    2502             :    *          the difference between the two rects is repainted
    2503             :    *
    2504             :    * @param aReflowInput information about your reflow including the reason
    2505             :    *          for the reflow and the available space in which to lay out. Each
    2506             :    *          dimension of the available space can either be constrained or
    2507             :    *          unconstrained (a value of NS_UNCONSTRAINEDSIZE).
    2508             :    *
    2509             :    *          Note that the available space can be negative. In this case you
    2510             :    *          still must return an accurate desired size. If you're a container
    2511             :    *          you must <b>always</b> reflow at least one frame regardless of the
    2512             :    *          available space
    2513             :    *
    2514             :    * @param aStatus a return value indicating whether the frame is complete
    2515             :    *          and whether the next-in-flow is dirty and needs to be reflowed
    2516             :    */
    2517             :   virtual void Reflow(nsPresContext*           aPresContext,
    2518             :                       ReflowOutput&     aReflowOutput,
    2519             :                       const ReflowInput& aReflowInput,
    2520             :                       nsReflowStatus&          aStatus) = 0;
    2521             : 
    2522             :   /**
    2523             :    * Post-reflow hook. After a frame is reflowed this method will be called
    2524             :    * informing the frame that this reflow process is complete, and telling the
    2525             :    * frame the status returned by the Reflow member function.
    2526             :    *
    2527             :    * This call may be invoked many times, while NS_FRAME_IN_REFLOW is set, before
    2528             :    * it is finally called once with a NS_FRAME_REFLOW_COMPLETE value. When called
    2529             :    * with a NS_FRAME_REFLOW_COMPLETE value the NS_FRAME_IN_REFLOW bit in the
    2530             :    * frame state will be cleared.
    2531             :    *
    2532             :    * XXX This doesn't make sense. If the frame is reflowed but not complete, then
    2533             :    * the status should have IsIncomplete() equal to true.
    2534             :    * XXX Don't we want the semantics to dictate that we only call this once for
    2535             :    * a given reflow?
    2536             :    */
    2537             :   virtual void DidReflow(nsPresContext*           aPresContext,
    2538             :                          const ReflowInput* aReflowInput,
    2539             :                          nsDidReflowStatus        aStatus) = 0;
    2540             : 
    2541             :   /**
    2542             :    * Updates the overflow areas of the frame. This can be called if an
    2543             :    * overflow area of the frame's children has changed without reflowing.
    2544             :    * @return true if either of the overflow areas for this frame have changed.
    2545             :    */
    2546             :   bool UpdateOverflow();
    2547             : 
    2548             :   /**
    2549             :    * Computes any overflow area created by the frame itself (outside of the
    2550             :    * frame bounds) and includes it into aOverflowAreas.
    2551             :    *
    2552             :    * Returns false if updating overflow isn't supported for this frame.
    2553             :    * If the frame requires a reflow instead, then it is responsible
    2554             :    * for scheduling one.
    2555             :    */
    2556             :   virtual bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) = 0;
    2557             : 
    2558             :   /**
    2559             :    * Computes any overflow area created by children of this frame and
    2560             :    * includes it into aOverflowAreas.
    2561             :    */
    2562             :   virtual void UnionChildOverflow(nsOverflowAreas& aOverflowAreas) = 0;
    2563             : 
    2564             :   /**
    2565             :    * Helper method used by block reflow to identify runs of text so
    2566             :    * that proper word-breaking can be done.
    2567             :    *
    2568             :    * @return
    2569             :    *    true if we can continue a "text run" through the frame. A
    2570             :    *    text run is text that should be treated contiguously for line
    2571             :    *    and word breaking.
    2572             :    */
    2573             :   virtual bool CanContinueTextRun() const = 0;
    2574             : 
    2575             :   /**
    2576             :    * Computes an approximation of the rendered text of the frame and its
    2577             :    * continuations. Returns nothing for non-text frames.
    2578             :    * The appended text will often not contain all the whitespace from source,
    2579             :    * depending on CSS white-space processing.
    2580             :    * if aEndOffset goes past end, use the text up to the string's end.
    2581             :    * Call this on the primary frame for a text node.
    2582             :    * aStartOffset and aEndOffset can be content offsets or offsets in the
    2583             :    * rendered text, depending on aOffsetType.
    2584             :    * Returns a string, as well as offsets identifying the start of the text
    2585             :    * within the rendered text for the whole node, and within the text content
    2586             :    * of the node.
    2587             :    */
    2588           0 :   struct RenderedText {
    2589             :     nsAutoString mString;
    2590             :     uint32_t mOffsetWithinNodeRenderedText;
    2591             :     int32_t mOffsetWithinNodeText;
    2592           0 :     RenderedText() : mOffsetWithinNodeRenderedText(0),
    2593           0 :         mOffsetWithinNodeText(0) {}
    2594             :   };
    2595             :   enum class TextOffsetType {
    2596             :     // Passed-in start and end offsets are within the content text.
    2597             :     OFFSETS_IN_CONTENT_TEXT,
    2598             :     // Passed-in start and end offsets are within the rendered text.
    2599             :     OFFSETS_IN_RENDERED_TEXT
    2600             :   };
    2601             :   enum class TrailingWhitespace {
    2602             :     TRIM_TRAILING_WHITESPACE,
    2603             :     // Spaces preceding a caret at the end of a line should not be trimmed
    2604             :     DONT_TRIM_TRAILING_WHITESPACE
    2605             :   };
    2606           0 :   virtual RenderedText GetRenderedText(uint32_t aStartOffset = 0,
    2607             :                                        uint32_t aEndOffset = UINT32_MAX,
    2608             :                                        TextOffsetType aOffsetType =
    2609             :                                            TextOffsetType::OFFSETS_IN_CONTENT_TEXT,
    2610             :                                        TrailingWhitespace aTrimTrailingWhitespace =
    2611             :                                            TrailingWhitespace::TRIM_TRAILING_WHITESPACE)
    2612           0 :   { return RenderedText(); }
    2613             : 
    2614             :   /**
    2615             :    * Returns true if the frame contains any non-collapsed characters.
    2616             :    * This method is only available for text frames, and it will return false
    2617             :    * for all other frame types.
    2618             :    */
    2619           0 :   virtual bool HasAnyNoncollapsedCharacters()
    2620           0 :   { return false; }
    2621             : 
    2622             :   /**
    2623             :    * Returns true if events of the given type targeted at this frame
    2624             :    * should only be dispatched to the system group.
    2625             :    */
    2626          10 :   virtual bool OnlySystemGroupDispatch(mozilla::EventMessage aMessage) const
    2627          10 :   { return false; }
    2628             : 
    2629             :   //
    2630             :   // Accessor functions to an associated view object:
    2631             :   //
    2632       28961 :   bool HasView() const { return !!(mState & NS_FRAME_HAS_VIEW); }
    2633             : protected:
    2634           0 :   virtual nsView* GetViewInternal() const
    2635             :   {
    2636           0 :     MOZ_ASSERT_UNREACHABLE("method should have been overridden by subclass");
    2637             :     return nullptr;
    2638             :   }
    2639           0 :   virtual void SetViewInternal(nsView* aView)
    2640             :   {
    2641           0 :     MOZ_ASSERT_UNREACHABLE("method should have been overridden by subclass");
    2642             :   }
    2643             : public:
    2644        6026 :   nsView* GetView() const
    2645             :   {
    2646        6026 :     if (MOZ_LIKELY(!HasView())) {
    2647        1473 :       return nullptr;
    2648             :     }
    2649        4553 :     nsView* view = GetViewInternal();
    2650        4553 :     MOZ_ASSERT(view, "GetViewInternal() should agree with HasView()");
    2651        4553 :     return view;
    2652             :   }
    2653             :   void SetView(nsView* aView);
    2654             : 
    2655             :   /**
    2656             :    * Find the closest view (on |this| or an ancestor).
    2657             :    * If aOffset is non-null, it will be set to the offset of |this|
    2658             :    * from the returned view.
    2659             :    */
    2660             :   nsView* GetClosestView(nsPoint* aOffset = nullptr) const;
    2661             : 
    2662             :   /**
    2663             :    * Find the closest ancestor (excluding |this| !) that has a view
    2664             :    */
    2665             :   nsIFrame* GetAncestorWithView() const;
    2666             : 
    2667             :   /**
    2668             :    * Sets the view's attributes from the frame style.
    2669             :    * Call this for nsChangeHint_SyncFrameView style changes or when the view
    2670             :    * has just been created.
    2671             :    * @param aView the frame's view or use GetView() if nullptr is given
    2672             :    */
    2673             :   void SyncFrameViewProperties(nsView* aView = nullptr);
    2674             : 
    2675             :   /**
    2676             :    * Get the offset between the coordinate systems of |this| and aOther.
    2677             :    * Adding the return value to a point in the coordinate system of |this|
    2678             :    * will transform the point to the coordinate system of aOther.
    2679             :    *
    2680             :    * aOther must be non-null.
    2681             :    *
    2682             :    * This function is fastest when aOther is an ancestor of |this|.
    2683             :    *
    2684             :    * This function _DOES NOT_ work across document boundaries.
    2685             :    * Use this function only when |this| and aOther are in the same document.
    2686             :    *
    2687             :    * NOTE: this actually returns the offset from aOther to |this|, but
    2688             :    * that offset is added to transform _coordinates_ from |this| to
    2689             :    * aOther.
    2690             :    */
    2691             :   nsPoint GetOffsetTo(const nsIFrame* aOther) const;
    2692             : 
    2693             :   /**
    2694             :    * Get the offset between the coordinate systems of |this| and aOther
    2695             :    * expressed in appunits per dev pixel of |this|' document. Adding the return
    2696             :    * value to a point that is relative to the origin of |this| will make the
    2697             :    * point relative to the origin of aOther but in the appunits per dev pixel
    2698             :    * ratio of |this|.
    2699             :    *
    2700             :    * aOther must be non-null.
    2701             :    *
    2702             :    * This function is fastest when aOther is an ancestor of |this|.
    2703             :    *
    2704             :    * This function works across document boundaries.
    2705             :    *
    2706             :    * Because this function may cross document boundaries that have different
    2707             :    * app units per dev pixel ratios it needs to be used very carefully.
    2708             :    *
    2709             :    * NOTE: this actually returns the offset from aOther to |this|, but
    2710             :    * that offset is added to transform _coordinates_ from |this| to
    2711             :    * aOther.
    2712             :    */
    2713             :   nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther) const;
    2714             : 
    2715             :   /**
    2716             :    * Like GetOffsetToCrossDoc, but the caller can specify which appunits
    2717             :    * to return the result in.
    2718             :    */
    2719             :   nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther, const int32_t aAPD) const;
    2720             : 
    2721             :   /**
    2722             :    * Get the rect of the frame relative to the top-left corner of the
    2723             :    * screen in CSS pixels.
    2724             :    * @return the CSS pixel rect of the frame relative to the top-left
    2725             :    *         corner of the screen.
    2726             :    */
    2727             :   mozilla::CSSIntRect GetScreenRect() const;
    2728             : 
    2729             :   /**
    2730             :    * Get the screen rect of the frame in app units.
    2731             :    * @return the app unit rect of the frame in screen coordinates.
    2732             :    */
    2733             :   nsRect GetScreenRectInAppUnits() const;
    2734             : 
    2735             :   /**
    2736             :    * Returns the offset from this frame to the closest geometric parent that
    2737             :    * has a view. Also returns the containing view or null in case of error
    2738             :    */
    2739             :   void GetOffsetFromView(nsPoint& aOffset, nsView** aView) const;
    2740             : 
    2741             :   /**
    2742             :    * Returns the nearest widget containing this frame. If this frame has a
    2743             :    * view and the view has a widget, then this frame's widget is
    2744             :    * returned, otherwise this frame's geometric parent is checked
    2745             :    * recursively upwards.
    2746             :    */
    2747             :   nsIWidget* GetNearestWidget() const;
    2748             : 
    2749             :   /**
    2750             :    * Same as GetNearestWidget() above but uses an outparam to return the offset
    2751             :    * of this frame to the returned widget expressed in appunits of |this| (the
    2752             :    * widget might be in a different document with a different zoom).
    2753             :    */
    2754             :   nsIWidget* GetNearestWidget(nsPoint& aOffset) const;
    2755             : 
    2756             :   /**
    2757             :    * Get the "type" of the frame.
    2758             :    *
    2759             :    * @see mozilla::LayoutFrameType
    2760             :    */
    2761       56692 :   mozilla::LayoutFrameType Type() const {
    2762       56692 :     MOZ_ASSERT(uint8_t(mClass) < mozilla::ArrayLength(sLayoutFrameTypes));
    2763       56692 :     return sLayoutFrameTypes[uint8_t(mClass)];
    2764             :   }
    2765             : 
    2766             : #define FRAME_TYPE(name_)                                                      \
    2767             :   bool Is##name_##Frame() const                                                \
    2768             :   {                                                                            \
    2769             :     return Type() == mozilla::LayoutFrameType::name_;                          \
    2770             :   }
    2771             : #include "mozilla/FrameTypeList.h"
    2772             : #undef FRAME_TYPE
    2773             : 
    2774             :   /**
    2775             :    * Returns a transformation matrix that converts points in this frame's
    2776             :    * coordinate space to points in some ancestor frame's coordinate space.
    2777             :    * The frame decides which ancestor it will use as a reference point.
    2778             :    * If this frame has no ancestor, aOutAncestor will be set to null.
    2779             :    *
    2780             :    * @param aStopAtAncestor don't look further than aStopAtAncestor. If null,
    2781             :    *   all ancestors (including across documents) will be traversed.
    2782             :    * @param aOutAncestor [out] The ancestor frame the frame has chosen.  If
    2783             :    *   this frame has no ancestor, *aOutAncestor will be set to null. If
    2784             :    * this frame is not a root frame, then *aOutAncestor will be in the same
    2785             :    * document as this frame. If this frame IsTransformed(), then *aOutAncestor
    2786             :    * will be the parent frame (if not preserve-3d) or the nearest non-transformed
    2787             :    * ancestor (if preserve-3d).
    2788             :    * @return A Matrix4x4 that converts points in this frame's coordinate space
    2789             :    *   into points in aOutAncestor's coordinate space.
    2790             :    */
    2791             :   Matrix4x4 GetTransformMatrix(const nsIFrame* aStopAtAncestor,
    2792             :                                nsIFrame **aOutAncestor,
    2793             :                                bool aInCSSUnits = false);
    2794             : 
    2795             :   /**
    2796             :    * Bit-flags to pass to IsFrameOfType()
    2797             :    */
    2798             :   enum {
    2799             :     eMathML =                           1 << 0,
    2800             :     eSVG =                              1 << 1,
    2801             :     eSVGForeignObject =                 1 << 2,
    2802             :     eSVGContainer =                     1 << 3,
    2803             :     eSVGGeometry =                      1 << 4,
    2804             :     eSVGPaintServer =                   1 << 5,
    2805             :     eBidiInlineContainer =              1 << 6,
    2806             :     // the frame is for a replaced element, such as an image
    2807             :     eReplaced =                         1 << 7,
    2808             :     // Frame that contains a block but looks like a replaced element
    2809             :     // from the outside
    2810             :     eReplacedContainsBlock =            1 << 8,
    2811             :     // A frame that participates in inline reflow, i.e., one that
    2812             :     // requires ReflowInput::mLineLayout.
    2813             :     eLineParticipant =                  1 << 9,
    2814             :     eXULBox =                           1 << 10,
    2815             :     eCanContainOverflowContainers =     1 << 11,
    2816             :     eBlockFrame =                       1 << 12,
    2817             :     eTablePart =                        1 << 13,
    2818             :     // If this bit is set, the frame doesn't allow ignorable whitespace as
    2819             :     // children. For example, the whitespace between <table>\n<tr>\n<td>
    2820             :     // will be excluded during the construction of children.
    2821             :     eExcludesIgnorableWhitespace =      1 << 14,
    2822             :     eSupportsCSSTransforms =            1 << 15,
    2823             : 
    2824             :     // A replaced element that has replaced-element sizing
    2825             :     // characteristics (i.e., like images or iframes), as opposed to
    2826             :     // inline-block sizing characteristics (like form controls).
    2827             :     eReplacedSizing =                   1 << 16,
    2828             : 
    2829             :     // These are to allow nsFrame::Init to assert that IsFrameOfType
    2830             :     // implementations all call the base class method.  They are only
    2831             :     // meaningful in DEBUG builds.
    2832             :     eDEBUGAllFrames =                   1 << 30,
    2833             :     eDEBUGNoFrames =                    1 << 31
    2834             :   };
    2835             : 
    2836             :   /**
    2837             :    * API for doing a quick check if a frame is of a given
    2838             :    * type. Returns true if the frame matches ALL flags passed in.
    2839             :    *
    2840             :    * Implementations should always override with inline virtual
    2841             :    * functions that call the base class's IsFrameOfType method.
    2842             :    */
    2843       35207 :   virtual bool IsFrameOfType(uint32_t aFlags) const
    2844             :   {
    2845             : #ifdef DEBUG
    2846       35207 :     return !(aFlags & ~(nsIFrame::eDEBUGAllFrames | nsIFrame::eSupportsCSSTransforms));
    2847             : #else
    2848             :     return !(aFlags & ~nsIFrame::eSupportsCSSTransforms);
    2849             : #endif
    2850             :   }
    2851             : 
    2852             :   /**
    2853             :    * Returns true if the frame is a block wrapper.
    2854             :    */
    2855             :   bool IsBlockWrapper() const;
    2856             : 
    2857             :   /**
    2858             :    * Get this frame's CSS containing block.
    2859             :    *
    2860             :    * The algorithm is defined in
    2861             :    * http://www.w3.org/TR/CSS2/visudet.html#containing-block-details.
    2862             :    *
    2863             :    * NOTE: This is guaranteed to return a non-null pointer when invoked on any
    2864             :    * frame other than the root frame.
    2865             :    *
    2866             :    * Requires SKIP_SCROLLED_FRAME to get behaviour matching the spec, otherwise
    2867             :    * it can return anonymous inner scrolled frames. Bug 1204044 is filed for
    2868             :    * investigating whether any of the callers actually require the default
    2869             :    * behaviour.
    2870             :    */
    2871             :   enum {
    2872             :     // If the containing block is an anonymous scrolled frame, then skip over
    2873             :     // this and return the outer scroll frame.
    2874             :     SKIP_SCROLLED_FRAME = 0x01
    2875             :   };
    2876             :   nsIFrame* GetContainingBlock(uint32_t aFlags,
    2877             :                                const nsStyleDisplay* aStyleDisplay) const;
    2878         279 :   nsIFrame* GetContainingBlock(uint32_t aFlags = 0) const {
    2879         279 :     return GetContainingBlock(aFlags, StyleDisplay());
    2880             :   }
    2881             : 
    2882             :   /**
    2883             :    * Is this frame a containing block for floating elements?
    2884             :    * Note that very few frames are, so default to false.
    2885             :    */
    2886         247 :   virtual bool IsFloatContainingBlock() const { return false; }
    2887             : 
    2888             :   /**
    2889             :    * Is this a leaf frame?  Frames that want the frame constructor to be able
    2890             :    * to construct kids for them should return false, all others should return
    2891             :    * true.  Note that returning true here does not mean that the frame _can't_
    2892             :    * have kids.  It could still have kids created via
    2893             :    * nsIAnonymousContentCreator.  Returning true indicates that "normal"
    2894             :    * (non-anonymous, XBL-bound, CSS generated content, etc) children should not
    2895             :    * be constructed.
    2896             :    */
    2897         563 :   bool IsLeaf() const
    2898             :   {
    2899         563 :     MOZ_ASSERT(uint8_t(mClass) < mozilla::ArrayLength(sFrameClassBits));
    2900         563 :     FrameClassBits bits = sFrameClassBits[uint8_t(mClass)];
    2901         563 :     if (MOZ_UNLIKELY(bits & eFrameClassBitsDynamicLeaf)) {
    2902          88 :       return IsLeafDynamic();
    2903             :     }
    2904         475 :     return bits & eFrameClassBitsLeaf;
    2905             :   }
    2906             : 
    2907             :   /**
    2908             :    * Marks all display items created by this frame as needing a repaint,
    2909             :    * and calls SchedulePaint() if requested and one is not already pending.
    2910             :    *
    2911             :    * This includes all display items created by this frame, including
    2912             :    * container types.
    2913             :    *
    2914             :    * @param aDisplayItemKey If specified, only issues an invalidate
    2915             :    * if this frame painted a display item of that type during the
    2916             :    * previous paint. SVG rendering observers are always notified.
    2917             :    */
    2918             :   virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0);
    2919             : 
    2920             :   /**
    2921             :    * Same as InvalidateFrame(), but only mark a fixed rect as needing
    2922             :    * repainting.
    2923             :    *
    2924             :    * @param aRect The rect to invalidate, relative to the TopLeft of the
    2925             :    * frame's border box.
    2926             :    * @param aDisplayItemKey If specified, only issues an invalidate
    2927             :    * if this frame painted a display item of that type during the
    2928             :    * previous paint. SVG rendering observers are always notified.
    2929             :    */
    2930             :   virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0);
    2931             : 
    2932             :   /**
    2933             :    * Calls InvalidateFrame() on all frames descendant frames (including
    2934             :    * this one).
    2935             :    *
    2936             :    * This function doesn't walk through placeholder frames to invalidate
    2937             :    * the out-of-flow frames.
    2938             :    *
    2939             :    * @param aDisplayItemKey If specified, only issues an invalidate
    2940             :    * if this frame painted a display item of that type during the
    2941             :    * previous paint. SVG rendering observers are always notified.
    2942             :    */
    2943             :   void InvalidateFrameSubtree(uint32_t aDisplayItemKey = 0);
    2944             : 
    2945             :   /**
    2946             :    * Called when a frame is about to be removed and needs to be invalidated.
    2947             :    * Normally does nothing since DLBI handles removed frames.
    2948             :    */
    2949          27 :   virtual void InvalidateFrameForRemoval() {}
    2950             : 
    2951             :   /**
    2952             :    * When HasUserData(frame->LayerIsPrerenderedDataKey()), then the
    2953             :    * entire overflow area of this frame has been rendered in its
    2954             :    * layer(s).
    2955             :    */
    2956          24 :   static void* LayerIsPrerenderedDataKey() {
    2957          24 :     return &sLayerIsPrerenderedDataKey;
    2958             :   }
    2959             :   static uint8_t sLayerIsPrerenderedDataKey;
    2960             : 
    2961             :    /**
    2962             :    * Try to update this frame's transform without invalidating any
    2963             :    * content.  Return true iff successful.  If unsuccessful, the
    2964             :    * caller is responsible for scheduling an invalidating paint.
    2965             :    *
    2966             :    * If the result is true, aLayerResult will be filled in with the
    2967             :    * transform layer for the frame.
    2968             :    */
    2969             :   bool TryUpdateTransformOnly(Layer** aLayerResult);
    2970             : 
    2971             :   /**
    2972             :    * Checks if a frame has had InvalidateFrame() called on it since the
    2973             :    * last paint.
    2974             :    *
    2975             :    * If true, then the invalid rect is returned in aRect, with an
    2976             :    * empty rect meaning all pixels drawn by this frame should be
    2977             :    * invalidated.
    2978             :    * If false, aRect is left unchanged.
    2979             :    */
    2980             :   bool IsInvalid(nsRect& aRect);
    2981             : 
    2982             :   /**
    2983             :    * Check if any frame within the frame subtree (including this frame)
    2984             :    * returns true for IsInvalid().
    2985             :    */
    2986          67 :   bool HasInvalidFrameInSubtree()
    2987             :   {
    2988          67 :     return HasAnyStateBits(NS_FRAME_NEEDS_PAINT | NS_FRAME_DESCENDANT_NEEDS_PAINT);
    2989             :   }
    2990             : 
    2991             :   /**
    2992             :    * Removes the invalid state from the current frame and all
    2993             :    * descendant frames.
    2994             :    */
    2995             :   void ClearInvalidationStateBits();
    2996             : 
    2997             :   /**
    2998             :    * Ensures that the refresh driver is running, and schedules a view
    2999             :    * manager flush on the next tick.
    3000             :    *
    3001             :    * The view manager flush will update the layer tree, repaint any
    3002             :    * invalid areas in the layer tree and schedule a layer tree
    3003             :    * composite operation to display the layer tree.
    3004             :    *
    3005             :    * In general it is not necessary for frames to call this when they change.
    3006             :    * For example, changes that result in a reflow will have this called for
    3007             :    * them by PresContext::DoReflow when the reflow begins. Style changes that
    3008             :    * do not trigger a reflow should have this called for them by
    3009             :    * DoApplyRenderingChangeToTree.
    3010             :    *
    3011             :    * @param aType PAINT_COMPOSITE_ONLY : No changes have been made
    3012             :    * that require a layer tree update, so only schedule a layer
    3013             :    * tree composite.
    3014             :    * PAINT_DELAYED_COMPRESS : Schedule a paint to be executed after a delay, and
    3015             :    * put FrameLayerBuilder in 'compressed' mode that avoids short cut optimizations.
    3016             :    */
    3017             :   enum PaintType {
    3018             :     PAINT_DEFAULT = 0,
    3019             :     PAINT_COMPOSITE_ONLY,
    3020             :     PAINT_DELAYED_COMPRESS
    3021             :   };
    3022             :   void SchedulePaint(PaintType aType = PAINT_DEFAULT);
    3023             : 
    3024             :   /**
    3025             :    * Checks if the layer tree includes a dedicated layer for this
    3026             :    * frame/display item key pair, and invalidates at least aDamageRect
    3027             :    * area within that layer.
    3028             :    *
    3029             :    * If no layer is found, calls InvalidateFrame() instead.
    3030             :    *
    3031             :    * @param aDamageRect Area of the layer to invalidate.
    3032             :    * @param aFrameDamageRect If no layer is found, the area of the frame to
    3033             :    *                         invalidate. If null, the entire frame will be
    3034             :    *                         invalidated.
    3035             :    * @param aDisplayItemKey Display item type.
    3036             :    * @param aFlags UPDATE_IS_ASYNC : Will skip the invalidation
    3037             :    * if the found layer is being composited by a remote
    3038             :    * compositor.
    3039             :    * @return Layer, if found, nullptr otherwise.
    3040             :    */
    3041             :   enum {
    3042             :     UPDATE_IS_ASYNC = 1 << 0
    3043             :   };
    3044             :   Layer* InvalidateLayer(uint32_t aDisplayItemKey,
    3045             :                          const nsIntRect* aDamageRect = nullptr,
    3046             :                          const nsRect* aFrameDamageRect = nullptr,
    3047             :                          uint32_t aFlags = 0);
    3048             : 
    3049             :   /**
    3050             :    * Returns a rect that encompasses everything that might be painted by
    3051             :    * this frame.  This includes this frame, all its descendant frames, this
    3052             :    * frame's outline, and descendant frames' outline, but does not include
    3053             :    * areas clipped out by the CSS "overflow" and "clip" properties.
    3054             :    *
    3055             :    * HasOverflowRects() (below) will return true when this overflow
    3056             :    * rect has been explicitly set, even if it matches mRect.
    3057             :    * XXX Note: because of a space optimization using the formula above,
    3058             :    * during reflow this function does not give accurate data if
    3059             :    * FinishAndStoreOverflow has been called but mRect hasn't yet been
    3060             :    * updated yet.  FIXME: This actually isn't true, but it should be.
    3061             :    *
    3062             :    * The visual overflow rect should NEVER be used for things that
    3063             :    * affect layout.  The scrollable overflow rect is permitted to affect
    3064             :    * layout.
    3065             :    *
    3066             :    * @return the rect relative to this frame's origin, but after
    3067             :    * CSS transforms have been applied (i.e. not really this frame's coordinate
    3068             :    * system, and may not contain the frame's border-box, e.g. if there
    3069             :    * is a CSS transform scaling it down)
    3070             :    */
    3071        4177 :   nsRect GetVisualOverflowRect() const {
    3072        4177 :     return GetOverflowRect(eVisualOverflow);
    3073             :   }
    3074             : 
    3075             :   /**
    3076             :    * Returns a rect that encompasses the area of this frame that the
    3077             :    * user should be able to scroll to reach.  This is similar to
    3078             :    * GetVisualOverflowRect, but does not include outline or shadows, and
    3079             :    * may in the future include more margins than visual overflow does.
    3080             :    * It does not include areas clipped out by the CSS "overflow" and
    3081             :    * "clip" properties.
    3082             :    *
    3083             :    * HasOverflowRects() (below) will return true when this overflow
    3084             :    * rect has been explicitly set, even if it matches mRect.
    3085             :    * XXX Note: because of a space optimization using the formula above,
    3086             :    * during reflow this function does not give accurate data if
    3087             :    * FinishAndStoreOverflow has been called but mRect hasn't yet been
    3088             :    * updated yet.
    3089             :    *
    3090             :    * @return the rect relative to this frame's origin, but after
    3091             :    * CSS transforms have been applied (i.e. not really this frame's coordinate
    3092             :    * system, and may not contain the frame's border-box, e.g. if there
    3093             :    * is a CSS transform scaling it down)
    3094             :    */
    3095        1895 :   nsRect GetScrollableOverflowRect() const {
    3096        1895 :     return GetOverflowRect(eScrollableOverflow);
    3097             :   }
    3098             : 
    3099             :   nsRect GetOverflowRect(nsOverflowType aType) const;
    3100             : 
    3101             :   nsOverflowAreas GetOverflowAreas() const;
    3102             : 
    3103             :   /**
    3104             :    * Same as GetOverflowAreas, except in this frame's coordinate
    3105             :    * system (before transforms are applied).
    3106             :    *
    3107             :    * @return the overflow areas relative to this frame, before any CSS transforms have
    3108             :    * been applied, i.e. in this frame's coordinate system
    3109             :    */
    3110             :   nsOverflowAreas GetOverflowAreasRelativeToSelf() const;
    3111             : 
    3112             :   /**
    3113             :    * Same as GetScrollableOverflowRect, except relative to the parent
    3114             :    * frame.
    3115             :    *
    3116             :    * @return the rect relative to the parent frame, in the parent frame's
    3117             :    * coordinate system
    3118             :    */
    3119             :   nsRect GetScrollableOverflowRectRelativeToParent() const;
    3120             : 
    3121             :   /**
    3122             :    * Same as GetScrollableOverflowRect, except in this frame's coordinate
    3123             :    * system (before transforms are applied).
    3124             :    *
    3125             :    * @return the rect relative to this frame, before any CSS transforms have
    3126             :    * been applied, i.e. in this frame's coordinate system
    3127             :    */
    3128             :   nsRect GetScrollableOverflowRectRelativeToSelf() const;
    3129             : 
    3130             :   /**
    3131             :    * Like GetVisualOverflowRect, except in this frame's
    3132             :    * coordinate system (before transforms are applied).
    3133             :    *
    3134             :    * @return the rect relative to this frame, before any CSS transforms have
    3135             :    * been applied, i.e. in this frame's coordinate system
    3136             :    */
    3137             :   nsRect GetVisualOverflowRectRelativeToSelf() const;
    3138             : 
    3139             :   /**
    3140             :    * Same as GetVisualOverflowRect, except relative to the parent
    3141             :    * frame.
    3142             :    *
    3143             :    * @return the rect relative to the parent frame, in the parent frame's
    3144             :    * coordinate system
    3145             :    */
    3146             :   nsRect GetVisualOverflowRectRelativeToParent() const;
    3147             : 
    3148             :   /**
    3149             :    * Returns this frame's visual overflow rect as it would be before taking
    3150             :    * account of SVG effects or transforms. The rect returned is relative to
    3151             :    * this frame.
    3152             :    */
    3153             :   nsRect GetPreEffectsVisualOverflowRect() const;
    3154             : 
    3155             :   /**
    3156             :    * Store the overflow area in the frame's mOverflow.mVisualDeltas
    3157             :    * fields or as a frame property in the frame manager so that it can
    3158             :    * be retrieved later without reflowing the frame. Returns true if either of
    3159             :    * the overflow areas changed.
    3160             :    */
    3161             :   bool FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
    3162             :                               nsSize aNewSize, nsSize* aOldSize = nullptr,
    3163             :                               const nsStyleDisplay* aStyleDisplay = nullptr);
    3164             : 
    3165         463 :   bool FinishAndStoreOverflow(ReflowOutput* aMetrics,
    3166             :                               const nsStyleDisplay* aStyleDisplay = nullptr) {
    3167        1389 :     return FinishAndStoreOverflow(aMetrics->mOverflowAreas,
    3168         926 :                                   nsSize(aMetrics->Width(), aMetrics->Height()),
    3169         926 :                                   nullptr, aStyleDisplay);
    3170             :   }
    3171             : 
    3172             :   /**
    3173             :    * Returns whether the frame has an overflow rect that is different from
    3174             :    * its border-box.
    3175             :    */
    3176          10 :   bool HasOverflowAreas() const {
    3177          10 :     return mOverflow.mType != NS_FRAME_OVERFLOW_NONE;
    3178             :   }
    3179             : 
    3180             :   /**
    3181             :    * Removes any stored overflow rects (visual and scrollable) from the frame.
    3182             :    * Returns true if the overflow changed.
    3183             :    */
    3184             :   bool ClearOverflowRects();
    3185             : 
    3186             :   /**
    3187             :    * Determine whether borders, padding, margins etc should NOT be applied
    3188             :    * on certain sides of the frame.
    3189             :    * @see mozilla::Sides in gfx/2d/BaseMargin.h
    3190             :    * @see mozilla::LogicalSides in layout/generic/WritingModes.h
    3191             :    *
    3192             :    * @note (See also bug 743402, comment 11) GetSkipSides() checks to see
    3193             :    *       if this frame has a previous or next continuation to determine
    3194             :    *       if a side should be skipped.
    3195             :    *       Unfortunately, this only works after reflow has been completed. In
    3196             :    *       lieu of this, during reflow, an ReflowInput parameter can be
    3197             :    *       passed in, indicating that it should be used to determine if sides
    3198             :    *       should be skipped during reflow.
    3199             :    */
    3200             :   Sides GetSkipSides(const ReflowInput* aReflowInput = nullptr) const;
    3201             :   virtual LogicalSides
    3202         494 :   GetLogicalSkipSides(const ReflowInput* aReflowInput = nullptr) const {
    3203         494 :     return LogicalSides();
    3204             :   }
    3205             : 
    3206             :   /**
    3207             :    * @returns true if this frame is selected.
    3208             :    */
    3209             :   bool IsSelected() const;
    3210             : 
    3211             :   /**
    3212             :    *  called to discover where this frame, or a parent frame has user-select style
    3213             :    *  applied, which affects that way that it is selected.
    3214             :    *
    3215             :    *  @param aSelectStyle  out param. Returns the type of selection style found
    3216             :    *                        (using values defined in nsStyleConsts.h).
    3217             :    *
    3218             :    *  @return Whether the frame can be selected (i.e. is not affected by
    3219             :    *          user-select: none)
    3220             :    */
    3221             :   bool IsSelectable(mozilla::StyleUserSelect* aSelectStyle) const;
    3222             : 
    3223             :   /**
    3224             :    *  Called to retrieve the SelectionController associated with the frame.
    3225             :    *  @param aSelCon will contain the selection controller associated with
    3226             :    *  the frame.
    3227             :    */
    3228             :   virtual nsresult  GetSelectionController(nsPresContext *aPresContext, nsISelectionController **aSelCon) = 0;
    3229             : 
    3230             :   /**
    3231             :    *  Call to get nsFrameSelection for this frame.
    3232             :    */
    3233             :   already_AddRefed<nsFrameSelection> GetFrameSelection();
    3234             : 
    3235             :   /**
    3236             :    * GetConstFrameSelection returns an object which methods are safe to use for
    3237             :    * example in nsIFrame code.
    3238             :    */
    3239             :   const nsFrameSelection* GetConstFrameSelection() const;
    3240             : 
    3241             :   /**
    3242             :    *  called to find the previous/next character, word, or line  returns the actual
    3243             :    *  nsIFrame and the frame offset.  THIS DOES NOT CHANGE SELECTION STATE
    3244             :    *  uses frame's begin selection state to start. if no selection on this frame will
    3245             :    *  return NS_ERROR_FAILURE
    3246             :    *  @param aPOS is defined in nsFrameSelection
    3247             :    */
    3248             :   virtual nsresult PeekOffset(nsPeekOffsetStruct *aPos);
    3249             : 
    3250             :   /**
    3251             :    *  called to find the previous/next non-anonymous selectable leaf frame.
    3252             :    *  @param aDirection [in] the direction to move in (eDirPrevious or eDirNext)
    3253             :    *  @param aVisual [in] whether bidi caret behavior is visual (true) or logical (false)
    3254             :    *  @param aJumpLines [in] whether to allow jumping across line boundaries
    3255             :    *  @param aScrollViewStop [in] whether to stop when reaching a scroll frame boundary
    3256             :    *  @param aOutFrame [out] the previous/next selectable leaf frame
    3257             :    *  @param aOutOffset [out] 0 indicates that we arrived at the beginning of the output frame;
    3258             :    *                          -1 indicates that we arrived at its end.
    3259             :    *  @param aOutJumpedLine [out] whether this frame and the returned frame are on different lines
    3260             :    *  @param aOutMovedOverNonSelectableText [out] whether we jumped over a non-selectable
    3261             :    *                                              frame during the search
    3262             :    */
    3263             :   nsresult GetFrameFromDirection(nsDirection aDirection, bool aVisual,
    3264             :                                  bool aJumpLines, bool aScrollViewStop,
    3265             :                                  nsIFrame** aOutFrame, int32_t* aOutOffset,
    3266             :                                  bool* aOutJumpedLine, bool* aOutMovedOverNonSelectableText);
    3267             : 
    3268             :   /**
    3269             :    *  called to see if the children of the frame are visible from indexstart to index end.
    3270             :    *  this does not change any state. returns true only if the indexes are valid and any of
    3271             :    *  the children are visible.  for textframes this index is the character index.
    3272             :    *  if aStart = aEnd result will be false
    3273             :    *  @param aStart start index of first child from 0-N (number of children)
    3274             :    *  @param aEnd   end index of last child from 0-N
    3275             :    *  @param aRecurse should this frame talk to siblings to get to the contents other children?
    3276             :    *  @param aFinished did this frame have the aEndIndex? or is there more work to do
    3277             :    *  @param _retval  return value true or false. false = range is not rendered.
    3278             :    */
    3279             :   virtual nsresult CheckVisibility(nsPresContext* aContext, int32_t aStartIndex, int32_t aEndIndex, bool aRecurse, bool *aFinished, bool *_retval)=0;
    3280             : 
    3281             :   /**
    3282             :    * Called to tell a frame that one of its child frames is dirty (i.e.,
    3283             :    * has the NS_FRAME_IS_DIRTY *or* NS_FRAME_HAS_DIRTY_CHILDREN bit
    3284             :    * set).  This should always set the NS_FRAME_HAS_DIRTY_CHILDREN on
    3285             :    * the frame, and may do other work.
    3286             :    */
    3287             :   virtual void ChildIsDirty(nsIFrame* aChild) = 0;
    3288             : 
    3289             :   /**
    3290             :    * Called to retrieve this frame's accessible.
    3291             :    * If this frame implements Accessibility return a valid accessible
    3292             :    * If not return NS_ERROR_NOT_IMPLEMENTED.
    3293             :    * Note: Accessible must be refcountable. Do not implement directly on your frame
    3294             :    * Use a mediatior of some kind.
    3295             :    */
    3296             : #ifdef ACCESSIBILITY
    3297             :   virtual mozilla::a11y::AccType AccessibleType() = 0;
    3298             : #endif
    3299             : 
    3300             :   /**
    3301             :    * Get the frame whose style context should be the parent of this
    3302             :    * frame's style context (i.e., provide the parent style context).
    3303             :    * This frame must either be an ancestor of this frame or a child.  If
    3304             :    * this returns a child frame, then the child frame must be sure to
    3305             :    * return a grandparent or higher!  Furthermore, if a child frame is
    3306             :    * returned it must have the same GetContent() as this frame.
    3307             :    *
    3308             :    * @param aProviderFrame (out) the frame associated with the returned value
    3309             :    *     or nullptr if the style context is for display:contents content.
    3310             :    * @return The style context that should be the parent of this frame's
    3311             :    *         style context.  Null is permitted, and means that this frame's
    3312             :    *         style context should be the root of the style context tree.
    3313             :    */
    3314             :   virtual nsStyleContext* GetParentStyleContext(nsIFrame** aProviderFrame) const = 0;
    3315             : 
    3316             :   /**
    3317             :    * Called by ServoRestyleManager to update the style contexts of anonymous
    3318             :    * boxes directly associtated with this frame.
    3319             :    *
    3320             :    * The passed-in ServoRestyleState can be used to create new style contexts
    3321             :    * as needed, as well as posting changes to the change list.
    3322             :    *
    3323             :    * It's guaranteed to already have a change in it for this frame and this
    3324             :    * frame's content.
    3325             :    *
    3326             :    * This function will be called after this frame's style context has already
    3327             :    * been updated.  This function will only be called on frames which have the
    3328             :    * NS_FRAME_OWNS_ANON_BOXES bit set.
    3329             :    */
    3330           0 :   void UpdateStyleOfOwnedAnonBoxes(mozilla::ServoRestyleState& aRestyleState)
    3331             :   {
    3332           0 :     if (GetStateBits() & NS_FRAME_OWNS_ANON_BOXES) {
    3333           0 :       DoUpdateStyleOfOwnedAnonBoxes(aRestyleState);
    3334             :     }
    3335           0 :   }
    3336             : 
    3337             : protected:
    3338             :   // This does the actual work of UpdateStyleOfOwnedAnonBoxes.  It calls
    3339             :   // AppendDirectlyOwnedAnonBoxes to find all of the anonymous boxes
    3340             :   // owned by this frame, and then updates styles on each of them.
    3341             :   void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoRestyleState& aRestyleState);
    3342             : 
    3343             :   // A helper for DoUpdateStyleOfOwnedAnonBoxes for the specific case
    3344             :   // of the owned anon box being a child of this frame.
    3345             :   void UpdateStyleOfChildAnonBox(nsIFrame* aChildFrame,
    3346             :                                  mozilla::ServoRestyleState& aRestyleState);
    3347             : 
    3348             : public:
    3349             :   // A helper both for UpdateStyleOfChildAnonBox, and to update frame-backed
    3350             :   // pseudo-elements in ServoRestyleManager.
    3351             :   //
    3352             :   // This gets a style context that will be the new style context for
    3353             :   // `aChildFrame`, and takes care of updating it, calling CalcStyleDifference,
    3354             :   // and adding to the change list as appropriate.
    3355             :   //
    3356             :   // If aContinuationStyleContext is not Nothing, it should be used for
    3357             :   // continuations instead of aNewStyleContext.  In either case, changehints are
    3358             :   // only computed based on aNewStyleContext.
    3359             :   //
    3360             :   // Returns the generated change hint for the frame.
    3361             :   static nsChangeHint UpdateStyleOfOwnedChildFrame(
    3362             :     nsIFrame* aChildFrame,
    3363             :     nsStyleContext* aNewStyleContext,
    3364             :     mozilla::ServoRestyleState& aRestyleState,
    3365             :     const Maybe<nsStyleContext*>& aContinuationStyleContext = Nothing());
    3366             : 
    3367             :   struct OwnedAnonBox
    3368             :   {
    3369             :     typedef void (*UpdateStyleFn)(nsIFrame* aOwningFrame,
    3370             :                                   nsIFrame* aAnonBox,
    3371             :                                   mozilla::ServoRestyleState& aRestyleState);
    3372             : 
    3373           0 :     explicit OwnedAnonBox(nsIFrame* aAnonBoxFrame,
    3374             :                           UpdateStyleFn aUpdateStyleFn = nullptr)
    3375           0 :       : mAnonBoxFrame(aAnonBoxFrame)
    3376           0 :       , mUpdateStyleFn(aUpdateStyleFn)
    3377           0 :     {}
    3378             : 
    3379             :     nsIFrame* mAnonBoxFrame;
    3380             :     UpdateStyleFn mUpdateStyleFn;
    3381             :   };
    3382             : 
    3383             :   /**
    3384             :    * Appends information about all of the anonymous boxes owned by this frame,
    3385             :    * including other anonymous boxes owned by those which this frame owns
    3386             :    * directly.
    3387             :    */
    3388           0 :   void AppendOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) {
    3389           0 :     if (GetStateBits() & NS_FRAME_OWNS_ANON_BOXES) {
    3390           0 :       if (IsInlineFrame()) {
    3391             :         // See comment in nsIFrame::DoUpdateStyleOfOwnedAnonBoxes for why
    3392             :         // we skip nsInlineFrames.
    3393           0 :         return;
    3394             :       }
    3395           0 :       DoAppendOwnedAnonBoxes(aResult);
    3396             :     }
    3397             :   }
    3398             : 
    3399             : protected:
    3400             :   // This does the actual work of AppendOwnedAnonBoxes.
    3401             :   void DoAppendOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult);
    3402             : 
    3403             : public:
    3404             :   /**
    3405             :    * Hook subclasses can override to return their owned anonymous boxes.
    3406             :    *
    3407             :    * This function only appends anonymous boxes that are directly owned by
    3408             :    * this frame, i.e. direct children or (for certain frames) a wrapper
    3409             :    * parent, unlike AppendOwnedAnonBoxes, which will append all anonymous
    3410             :    * boxes transitively owned by this frame.
    3411             :    */
    3412             :   virtual void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult);
    3413             : 
    3414             :   /**
    3415             :    * Determines whether a frame is visible for painting;
    3416             :    * taking into account whether it is painting a selection or printing.
    3417             :    */
    3418             :   bool IsVisibleForPainting(nsDisplayListBuilder* aBuilder);
    3419             :   /**
    3420             :    * Determines whether a frame is visible for painting or collapsed;
    3421             :    * taking into account whether it is painting a selection or printing,
    3422             :    */
    3423             :   bool IsVisibleOrCollapsedForPainting(nsDisplayListBuilder* aBuilder);
    3424             :   /**
    3425             :    * As above, but slower because we have to recompute some stuff that
    3426             :    * aBuilder already has.
    3427             :    */
    3428             :   bool IsVisibleForPainting();
    3429             :   /**
    3430             :    * Check whether this frame is visible in the current selection. Returns
    3431             :    * true if there is no current selection.
    3432             :    */
    3433             :   bool IsVisibleInSelection(nsDisplayListBuilder* aBuilder);
    3434             : 
    3435             :   /**
    3436             :    * Overridable function to determine whether this frame should be considered
    3437             :    * "in" the given non-null aSelection for visibility purposes.
    3438             :    */
    3439             :   virtual bool IsVisibleInSelection(nsISelection* aSelection);
    3440             : 
    3441             :   /**
    3442             :    * Determines whether this frame is a pseudo stacking context, looking
    3443             :    * only as style --- i.e., assuming that it's in-flow and not a replaced
    3444             :    * element and not an SVG element.
    3445             :    * XXX maybe check IsTransformed()?
    3446             :    */
    3447             :   bool IsPseudoStackingContextFromStyle();
    3448             : 
    3449         386 :   virtual bool HonorPrintBackgroundSettings() { return true; }
    3450             : 
    3451             :   /**
    3452             :    * Determine whether the frame is logically empty, which is roughly
    3453             :    * whether the layout would be the same whether or not the frame is
    3454             :    * present.  Placeholder frames should return true.  Block frames
    3455             :    * should be considered empty whenever margins collapse through them,
    3456             :    * even though those margins are relevant.  Text frames containing
    3457             :    * only whitespace that does not contribute to the height of the line
    3458             :    * should return true.
    3459             :    */
    3460             :   virtual bool IsEmpty() = 0;
    3461             :   /**
    3462             :    * Return the same as IsEmpty(). This may only be called after the frame
    3463             :    * has been reflowed and before any further style or content changes.
    3464             :    */
    3465             :   virtual bool CachedIsEmpty();
    3466             :   /**
    3467             :    * Determine whether the frame is logically empty, assuming that all
    3468             :    * its children are empty.
    3469             :    */
    3470             :   virtual bool IsSelfEmpty() = 0;
    3471             : 
    3472             :   /**
    3473             :    * IsGeneratedContentFrame returns whether a frame corresponds to
    3474             :    * generated content
    3475             :    *
    3476             :    * @return whether the frame correspods to generated content
    3477             :    */
    3478         666 :   bool IsGeneratedContentFrame() const {
    3479         666 :     return (mState & NS_FRAME_GENERATED_CONTENT) != 0;
    3480             :   }
    3481             : 
    3482             :   /**
    3483             :    * IsPseudoFrame returns whether a frame is a pseudo frame (eg an
    3484             :    * anonymous table-row frame created for a CSS table-cell without an
    3485             :    * enclosing table-row.
    3486             :    *
    3487             :    * @param aParentContent the content node corresponding to the parent frame
    3488             :    * @return whether the frame is a pseudo frame
    3489             :    */
    3490           0 :   bool IsPseudoFrame(const nsIContent* aParentContent) {
    3491           0 :     return mContent == aParentContent;
    3492             :   }
    3493             : 
    3494             :   /**
    3495             :    * Support for reading and writing properties on the frame.
    3496             :    * These call through to the frame's FrameProperties object, if it
    3497             :    * exists, but avoid creating it if no property is ever set.
    3498             :    */
    3499             :   template<typename T>
    3500             :   FrameProperties::PropertyType<T>
    3501       10004 :   GetProperty(FrameProperties::Descriptor<T> aProperty,
    3502             :               bool* aFoundResult = nullptr) const
    3503             :   {
    3504       10004 :     return mProperties.Get(aProperty, aFoundResult);
    3505             :   }
    3506             : 
    3507             :   template<typename T>
    3508           0 :   bool HasProperty(FrameProperties::Descriptor<T> aProperty) const
    3509             :   {
    3510           0 :     return mProperties.Has(aProperty);
    3511             :   }
    3512             : 
    3513             :   // Add a property, or update an existing property for the given descriptor.
    3514             :   template<typename T>
    3515         469 :   void SetProperty(FrameProperties::Descriptor<T> aProperty,
    3516             :                    FrameProperties::PropertyType<T> aValue)
    3517             :   {
    3518         469 :     mProperties.Set(aProperty, aValue, this);
    3519         469 :   }
    3520             : 
    3521             :   // Unconditionally add a property; use ONLY if the descriptor is known
    3522             :   // to NOT already be present.
    3523             :   template<typename T>
    3524         126 :   void AddProperty(FrameProperties::Descriptor<T> aProperty,
    3525             :                    FrameProperties::PropertyType<T> aValue)
    3526             :   {
    3527         126 :     mProperties.Add(aProperty, aValue);
    3528         126 :   }
    3529             : 
    3530             :   template<typename T>
    3531             :   FrameProperties::PropertyType<T>
    3532         108 :   RemoveProperty(FrameProperties::Descriptor<T> aProperty,
    3533             :                  bool* aFoundResult = nullptr)
    3534             :   {
    3535         108 :     return mProperties.Remove(aProperty, aFoundResult);
    3536             :   }
    3537             : 
    3538             :   template<typename T>
    3539       12412 :   void DeleteProperty(FrameProperties::Descriptor<T> aProperty)
    3540             :   {
    3541       12412 :     mProperties.Delete(aProperty, this);
    3542       12412 :   }
    3543             : 
    3544         252 :   void DeleteAllProperties()
    3545             :   {
    3546         252 :     mProperties.DeleteAll(this);
    3547         252 :   }
    3548             : 
    3549             :   // Reports size of the FrameProperties for this frame and its descendants
    3550             :   size_t SizeOfFramePropertiesForTree(mozilla::MallocSizeOf aMallocSizeOf) const;
    3551             : 
    3552             :   /**
    3553             :    * Return true if and only if this frame obeys visibility:hidden.
    3554             :    * if it does not, then nsContainerFrame will hide its view even though
    3555             :    * this means children can't be made visible again.
    3556             :    */
    3557          31 :   virtual bool SupportsVisibilityHidden() { return true; }
    3558             : 
    3559             :   /**
    3560             :    * Returns the clip rect set via the 'clip' property, if the 'clip' property
    3561             :    * applies to this frame; otherwise returns Nothing(). The 'clip' property
    3562             :    * applies to HTML frames if they are absolutely positioned. The 'clip'
    3563             :    * property applies to SVG frames regardless of the value of the 'position'
    3564             :    * property.
    3565             :    *
    3566             :    * The coordinates of the returned rectangle are relative to this frame's
    3567             :    * origin.
    3568             :    */
    3569             :   Maybe<nsRect> GetClipPropClipRect(const nsStyleDisplay* aDisp,
    3570             :                                     const nsStyleEffects* aEffects,
    3571             :                                     const nsSize& aSize) const;
    3572             : 
    3573             :   /**
    3574             :    * Check if this frame is focusable and in the current tab order.
    3575             :    * Tabbable is indicated by a nonnegative tabindex & is a subset of focusable.
    3576             :    * For example, only the selected radio button in a group is in the
    3577             :    * tab order, unless the radio group has no selection in which case
    3578             :    * all of the visible, non-disabled radio buttons in the group are
    3579             :    * in the tab order. On the other hand, all of the visible, non-disabled
    3580             :    * radio buttons are always focusable via clicking or script.
    3581             :    * Also, depending on the pref accessibility.tabfocus some widgets may be
    3582             :    * focusable but removed from the tab order. This is the default on
    3583             :    * Mac OS X, where fewer items are focusable.
    3584             :    * @param  [in, optional] aTabIndex the computed tab index
    3585             :    *         < 0 if not tabbable
    3586             :    *         == 0 if in normal tab order
    3587             :    *         > 0 can be tabbed to in the order specified by this value
    3588             :    * @param  [in, optional] aWithMouse, is this focus query for mouse clicking
    3589             :    * @return whether the frame is focusable via mouse, kbd or script.
    3590             :    */
    3591             :   virtual bool IsFocusable(int32_t *aTabIndex = nullptr, bool aWithMouse = false);
    3592             : 
    3593             :   // BOX LAYOUT METHODS
    3594             :   // These methods have been migrated from nsIBox and are in the process of
    3595             :   // being refactored. DO NOT USE OUTSIDE OF XUL.
    3596       19655 :   bool IsXULBoxFrame() const
    3597             :   {
    3598       19655 :     return IsFrameOfType(nsIFrame::eXULBox);
    3599             :   }
    3600             : 
    3601             :   enum Halignment {
    3602             :     hAlign_Left,
    3603             :     hAlign_Right,
    3604             :     hAlign_Center
    3605             :   };
    3606             : 
    3607             :   enum Valignment {
    3608             :     vAlign_Top,
    3609             :     vAlign_Middle,
    3610             :     vAlign_BaseLine,
    3611             :     vAlign_Bottom
    3612             :   };
    3613             : 
    3614             :   /**
    3615             :    * This calculates the minimum size required for a box based on its state
    3616             :    * @param[in] aBoxLayoutState The desired state to calculate for
    3617             :    * @return The minimum size
    3618             :    */
    3619             :   virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) = 0;
    3620             : 
    3621             :   /**
    3622             :    * This calculates the preferred size of a box based on its state
    3623             :    * @param[in] aBoxLayoutState The desired state to calculate for
    3624             :    * @return The preferred size
    3625             :    */
    3626             :   virtual nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) = 0;
    3627             : 
    3628             :   /**
    3629             :    * This calculates the maximum size for a box based on its state
    3630             :    * @param[in] aBoxLayoutState The desired state to calculate for
    3631             :    * @return The maximum size
    3632             :    */
    3633             :   virtual nsSize GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState) = 0;
    3634             : 
    3635             :   /**
    3636             :    * This returns the minimum size for the scroll area if this frame is
    3637             :    * being scrolled. Usually it's (0,0).
    3638             :    */
    3639             :   virtual nsSize GetXULMinSizeForScrollArea(nsBoxLayoutState& aBoxLayoutState) = 0;
    3640             : 
    3641             :   // Implemented in nsBox, used in nsBoxFrame
    3642             :   uint32_t GetXULOrdinal();
    3643             : 
    3644             :   virtual nscoord GetXULFlex() = 0;
    3645             :   virtual nscoord GetXULBoxAscent(nsBoxLayoutState& aBoxLayoutState) = 0;
    3646             :   virtual bool IsXULCollapsed() = 0;
    3647             :   // This does not alter the overflow area. If the caller is changing
    3648             :   // the box size, the caller is responsible for updating the overflow
    3649             :   // area. It's enough to just call XULLayout or SyncLayout on the
    3650             :   // box. You can pass true to aRemoveOverflowArea as a
    3651             :   // convenience.
    3652             :   virtual void SetXULBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRect,
    3653             :                             bool aRemoveOverflowAreas = false) = 0;
    3654             :   nsresult XULLayout(nsBoxLayoutState& aBoxLayoutState);
    3655             :   // Box methods.  Note that these do NOT just get the CSS border, padding,
    3656             :   // etc.  They also talk to nsITheme.
    3657             :   virtual nsresult GetXULBorderAndPadding(nsMargin& aBorderAndPadding);
    3658             :   virtual nsresult GetXULBorder(nsMargin& aBorder)=0;
    3659             :   virtual nsresult GetXULPadding(nsMargin& aBorderAndPadding)=0;
    3660             :   virtual nsresult GetXULMargin(nsMargin& aMargin)=0;
    3661           0 :   virtual void SetXULLayoutManager(nsBoxLayout* aLayout) { }
    3662           0 :   virtual nsBoxLayout* GetXULLayoutManager() { return nullptr; }
    3663             :   nsresult GetXULClientRect(nsRect& aContentRect);
    3664             : 
    3665        2906 :   virtual uint32_t GetXULLayoutFlags()
    3666        2906 :   { return 0; }
    3667             : 
    3668             :   // For nsSprocketLayout
    3669             :   virtual Valignment GetXULVAlign() const = 0;
    3670             :   virtual Halignment GetXULHAlign() const = 0;
    3671             : 
    3672        5117 :   bool IsXULHorizontal() const { return (mState & NS_STATE_IS_HORIZONTAL) != 0; }
    3673           0 :   bool IsXULNormalDirection() const { return (mState & NS_STATE_IS_DIRECTION_NORMAL) != 0; }
    3674             : 
    3675             :   nsresult XULRedraw(nsBoxLayoutState& aState);
    3676             :   virtual nsresult XULRelayoutChildAtOrdinal(nsIFrame* aChild)=0;
    3677             : 
    3678             : #ifdef DEBUG_LAYOUT
    3679             :   virtual nsresult SetXULDebug(nsBoxLayoutState& aState, bool aDebug)=0;
    3680             :   virtual nsresult GetXULDebug(bool& aDebug)=0;
    3681             : 
    3682             :   virtual nsresult XULDumpBox(FILE* out)=0;
    3683             : #endif
    3684             : 
    3685             :   static bool AddXULPrefSize(nsIFrame* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet);
    3686             :   static bool AddXULMinSize(nsBoxLayoutState& aState, nsIFrame* aBox,
    3687             :                             nsSize& aSize, bool& aWidth, bool& aHeightSet);
    3688             :   static bool AddXULMaxSize(nsIFrame* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet);
    3689             :   static bool AddXULFlex(nsIFrame* aBox, nscoord& aFlex);
    3690             : 
    3691             :   // END OF BOX LAYOUT METHODS
    3692             :   // The above methods have been migrated from nsIBox and are in the process of
    3693             :   // being refactored. DO NOT USE OUTSIDE OF XUL.
    3694             : 
    3695             :   /**
    3696             :    * @return true if this text frame ends with a newline character.  It
    3697             :    * should return false if this is not a text frame.
    3698             :    */
    3699             :   virtual bool HasSignificantTerminalNewline() const;
    3700             : 
    3701             :   struct CaretPosition {
    3702             :     CaretPosition();
    3703             :     ~CaretPosition();
    3704             : 
    3705             :     nsCOMPtr<nsIContent> mResultContent;
    3706             :     int32_t              mContentOffset;
    3707             :   };
    3708             : 
    3709             :   /**
    3710             :    * gets the first or last possible caret position within the frame
    3711             :    *
    3712             :    * @param  [in] aStart
    3713             :    *         true  for getting the first possible caret position
    3714             :    *         false for getting the last possible caret position
    3715             :    * @return The caret position in a CaretPosition.
    3716             :    *         the returned value is a 'best effort' in case errors
    3717             :    *         are encountered rummaging through the frame.
    3718             :    */
    3719             :   CaretPosition GetExtremeCaretPosition(bool aStart);
    3720             : 
    3721             :   /**
    3722             :    * Get a line iterator for this frame, if supported.
    3723             :    *
    3724             :    * @return nullptr if no line iterator is supported.
    3725             :    * @note dispose the line iterator using nsILineIterator::DisposeLineIterator
    3726             :    */
    3727             :   virtual nsILineIterator* GetLineIterator() = 0;
    3728             : 
    3729             :   /**
    3730             :    * If this frame is a next-in-flow, and its prev-in-flow has something on its
    3731             :    * overflow list, pull those frames into the child list of this one.
    3732             :    */
    3733           0 :   virtual void PullOverflowsFromPrevInFlow() {}
    3734             : 
    3735             :   /**
    3736             :    * Clear the list of child PresShells generated during the last paint
    3737             :    * so that we can begin generating a new one.
    3738             :    */
    3739          26 :   void ClearPresShellsFromLastPaint() {
    3740          26 :     PaintedPresShellList()->Clear();
    3741          26 :   }
    3742             : 
    3743             :   /**
    3744             :    * Flag a child PresShell as painted so that it will get its paint count
    3745             :    * incremented during empty transactions.
    3746             :    */
    3747          26 :   void AddPaintedPresShell(nsIPresShell* shell) {
    3748          26 :     PaintedPresShellList()->AppendElement(do_GetWeakReference(shell));
    3749          26 :   }
    3750             : 
    3751             :   /**
    3752             :    * Increment the paint count of all child PresShells that were painted during
    3753             :    * the last repaint.
    3754             :    */
    3755           1 :   void UpdatePaintCountForPaintedPresShells() {
    3756           2 :     for (nsWeakPtr& item : *PaintedPresShellList()) {
    3757           2 :       nsCOMPtr<nsIPresShell> shell = do_QueryReferent(item);
    3758           1 :       if (shell) {
    3759           1 :         shell->IncrementPaintCount();
    3760             :       }
    3761             :     }
    3762           1 :   }
    3763             : 
    3764             :   /**
    3765             :    * @return true if we painted @aShell during the last repaint.
    3766             :    */
    3767           5 :   bool DidPaintPresShell(nsIPresShell* aShell)
    3768             :   {
    3769           5 :     for (nsWeakPtr& item : *PaintedPresShellList()) {
    3770           4 :       nsCOMPtr<nsIPresShell> shell = do_QueryReferent(item);
    3771           4 :       if (shell == aShell) {
    3772           4 :         return true;
    3773             :       }
    3774             :     }
    3775           1 :     return false;
    3776             :   }
    3777             : 
    3778             :   /**
    3779             :    * Accessors for the absolute containing block.
    3780             :    */
    3781       11973 :   bool IsAbsoluteContainer() const { return !!(mState & NS_FRAME_HAS_ABSPOS_CHILDREN); }
    3782             :   bool HasAbsolutelyPositionedChildren() const;
    3783             :   nsAbsoluteContainingBlock* GetAbsoluteContainingBlock() const;
    3784             :   void MarkAsAbsoluteContainingBlock();
    3785             :   void MarkAsNotAbsoluteContainingBlock();
    3786             :   // Child frame types override this function to select their own child list name
    3787         467 :   virtual mozilla::layout::FrameChildListID GetAbsoluteListID() const { return kAbsoluteList; }
    3788             : 
    3789             :   // Checks if we (or any of our descendents) have NS_FRAME_PAINTED_THEBES set, and
    3790             :   // clears this bit if so.
    3791             :   bool CheckAndClearPaintedState();
    3792             : 
    3793             :   // CSS visibility just doesn't cut it because it doesn't inherit through
    3794             :   // documents. Also if this frame is in a hidden card of a deck then it isn't
    3795             :   // visible either and that isn't expressed using CSS visibility. Also if it
    3796             :   // is in a hidden view (there are a few cases left and they are hopefully
    3797             :   // going away soon).
    3798             :   // If the VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY flag is passed then we
    3799             :   // ignore the chrome/content boundary, otherwise we stop looking when we
    3800             :   // reach it.
    3801             :   enum {
    3802             :     VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY = 0x01
    3803             :   };
    3804             :   bool IsVisibleConsideringAncestors(uint32_t aFlags = 0) const;
    3805             : 
    3806             :   struct FrameWithDistance
    3807             :   {
    3808             :     nsIFrame* mFrame;
    3809             :     nscoord mXDistance;
    3810             :     nscoord mYDistance;
    3811             :   };
    3812             : 
    3813             :   /**
    3814             :    * Finds a frame that is closer to a specified point than a current
    3815             :    * distance.  Distance is measured as for text selection -- a closer x
    3816             :    * distance beats a closer y distance.
    3817             :    *
    3818             :    * Normally, this function will only check the distance between this
    3819             :    * frame's rectangle and the specified point.  SVGTextFrame overrides
    3820             :    * this so that it can manage all of its descendant frames and take
    3821             :    * into account any SVG text layout.
    3822             :    *
    3823             :    * If aPoint is closer to this frame's rectangle than aCurrentBestFrame
    3824             :    * indicates, then aCurrentBestFrame is updated with the distance between
    3825             :    * aPoint and this frame's rectangle, and with a pointer to this frame.
    3826             :    * If aPoint is not closer, then aCurrentBestFrame is left unchanged.
    3827             :    *
    3828             :    * @param aPoint The point to check for its distance to this frame.
    3829             :    * @param aCurrentBestFrame Pointer to a struct that will be updated with
    3830             :    *   a pointer to this frame and its distance to aPoint, if this frame
    3831             :    *   is indeed closer than the current distance in aCurrentBestFrame.
    3832             :    */
    3833             :   virtual void FindCloserFrameForSelection(nsPoint aPoint,
    3834             :                                            FrameWithDistance* aCurrentBestFrame);
    3835             : 
    3836             :   /**
    3837             :    * Is this a flex item? (i.e. a non-abs-pos child of a flex container)
    3838             :    */
    3839             :   inline bool IsFlexItem() const;
    3840             :   /**
    3841             :    * Is this a flex or grid item? (i.e. a non-abs-pos child of a flex/grid container)
    3842             :    */
    3843             :   inline bool IsFlexOrGridItem() const;
    3844             :   inline bool IsFlexOrGridContainer() const;
    3845             : 
    3846             :   /**
    3847             :    * @return true if this frame is used as a table caption.
    3848             :    */
    3849             :   inline bool IsTableCaption() const;
    3850             : 
    3851             :   inline bool IsBlockInside() const;
    3852             :   inline bool IsBlockOutside() const;
    3853             :   inline bool IsInlineOutside() const;
    3854             :   inline mozilla::StyleDisplay GetDisplay() const;
    3855             :   inline bool IsFloating() const;
    3856             :   inline bool IsAbsPosContainingBlock() const;
    3857             :   inline bool IsFixedPosContainingBlock() const;
    3858             :   inline bool IsRelativelyPositioned() const;
    3859             :   inline bool IsAbsolutelyPositioned(const nsStyleDisplay* aStyleDisplay = nullptr) const;
    3860             : 
    3861             :   /**
    3862             :    * Returns the vertical-align value to be used for layout, if it is one
    3863             :    * of the enumerated values.  If this is an SVG text frame, it returns a value
    3864             :    * that corresponds to the value of dominant-baseline.  If the
    3865             :    * vertical-align property has length or percentage value, this returns
    3866             :    * eInvalidVerticalAlign.
    3867             :    */
    3868             :   uint8_t VerticalAlignEnum() const;
    3869             :   enum { eInvalidVerticalAlign = 0xFF };
    3870             : 
    3871             :   void CreateOwnLayerIfNeeded(nsDisplayListBuilder* aBuilder, nsDisplayList* aList);
    3872             : 
    3873             :   /**
    3874             :    * Adds the NS_FRAME_IN_POPUP state bit to aFrame, and
    3875             :    * all descendant frames (including cross-doc ones).
    3876             :    */
    3877             :   static void AddInPopupStateBitToDescendants(nsIFrame* aFrame);
    3878             :   /**
    3879             :    * Removes the NS_FRAME_IN_POPUP state bit from aFrame and
    3880             :    * all descendant frames (including cross-doc ones), unless
    3881             :    * the frame is a popup itself.
    3882             :    */
    3883             :   static void RemoveInPopupStateBitFromDescendants(nsIFrame* aFrame);
    3884             : 
    3885             :   /**
    3886             :    * Sorts the given nsFrameList, so that for every two adjacent frames in the
    3887             :    * list, the former is less than or equal to the latter, according to the
    3888             :    * templated IsLessThanOrEqual method.
    3889             :    *
    3890             :    * Note: this method uses a stable merge-sort algorithm.
    3891             :    */
    3892             :   template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
    3893             :   static void SortFrameList(nsFrameList& aFrameList);
    3894             : 
    3895             :   /**
    3896             :    * Returns true if the given frame list is already sorted, according to the
    3897             :    * templated IsLessThanOrEqual function.
    3898             :    */
    3899             :   template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
    3900             :   static bool IsFrameListSorted(nsFrameList& aFrameList);
    3901             : 
    3902             :   /**
    3903             :    * Return true if aFrame is in an {ib} split and is NOT one of the
    3904             :    * continuations of the first inline in it.
    3905             :    */
    3906          27 :   bool FrameIsNonFirstInIBSplit() const {
    3907          27 :     return (GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) &&
    3908          27 :       FirstContinuation()->GetProperty(nsIFrame::IBSplitPrevSibling());
    3909             :   }
    3910             : 
    3911             :   /**
    3912             :    * Return true if aFrame is in an {ib} split and is NOT one of the
    3913             :    * continuations of the last inline in it.
    3914             :    */
    3915          75 :   bool FrameIsNonLastInIBSplit() const {
    3916          75 :     return (GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) &&
    3917          75 :       FirstContinuation()->GetProperty(nsIFrame::IBSplitSibling());
    3918             :   }
    3919             : 
    3920             :   /**
    3921             :    * Return whether this is a frame whose width is used when computing
    3922             :    * the font size inflation of its descendants.
    3923             :    */
    3924         642 :   bool IsContainerForFontSizeInflation() const {
    3925         642 :     return GetStateBits() & NS_FRAME_FONT_INFLATION_CONTAINER;
    3926             :   }
    3927             : 
    3928             :   /**
    3929             :    * Return whether this frame keeps track of overflow areas. (Frames for
    3930             :    * non-display SVG elements -- e.g. <clipPath> -- do not maintain overflow
    3931             :    * areas, because they're never painted.)
    3932             :    */
    3933        1791 :   bool FrameMaintainsOverflow() const {
    3934        1791 :     return !HasAllStateBits(NS_FRAME_SVG_LAYOUT | NS_FRAME_IS_NONDISPLAY);
    3935             :   }
    3936             : 
    3937             :   /**
    3938             :    * Returns the content node within the anonymous content that this frame
    3939             :    * generated and which corresponds to the specified pseudo-element type,
    3940             :    * or nullptr if there is no such anonymous content.
    3941             :    */
    3942             :   virtual mozilla::dom::Element*
    3943             :   GetPseudoElement(mozilla::CSSPseudoElementType aType);
    3944             : 
    3945             :   /*
    3946             :    * @param aStyleDisplay:  If the caller has this->StyleDisplay(), providing
    3947             :    *   it here will improve performance.
    3948             :    */
    3949        2017 :   bool BackfaceIsHidden(const nsStyleDisplay* aStyleDisplay) const {
    3950        2017 :     MOZ_ASSERT(aStyleDisplay == StyleDisplay());
    3951        2017 :     return aStyleDisplay->BackfaceIsHidden();
    3952             :   }
    3953          76 :   bool BackfaceIsHidden() const {
    3954          76 :     return StyleDisplay()->BackfaceIsHidden();
    3955             :   }
    3956             : 
    3957             :   /**
    3958             :    * Returns true if the frame is scrolled out of view.
    3959             :    */
    3960             :   bool IsScrolledOutOfView();
    3961             : 
    3962             :   /**
    3963             :    * Computes a 2D matrix from the -moz-window-transform and
    3964             :    * -moz-window-transform-origin properties on aFrame.
    3965             :    * Values that don't result in a 2D matrix will be ignored and an identity
    3966             :    * matrix will be returned instead.
    3967             :    */
    3968             :   Matrix ComputeWidgetTransform();
    3969             : 
    3970             :   /**
    3971             :    * Applies the values from the -moz-window-* properties to the widget.
    3972             :    */
    3973             :   virtual void UpdateWidgetProperties();
    3974             : 
    3975             :   /**
    3976             :    * @return true iff this frame has one or more associated image requests.
    3977             :    * @see mozilla::css::ImageLoader.
    3978             :    */
    3979         128 :   bool HasImageRequest() const { return mHasImageRequest; }
    3980             : 
    3981             :   /**
    3982             :    * Update this frame's image request state.
    3983             :    */
    3984          12 :   void SetHasImageRequest(bool aHasRequest) { mHasImageRequest = aHasRequest; }
    3985             : 
    3986             :   /**
    3987             :    * Whether this frame has a first-letter child.  If it does, the frame is
    3988             :    * actually an nsContainerFrame and the first-letter frame can be gotten by
    3989             :    * walking up to the nearest ancestor blockframe and getting its first
    3990             :    * continuation's nsContainerFrame::FirstLetterProperty() property.  This will
    3991             :    * only return true for the first continuation of the first-letter's parent.
    3992             :    */
    3993           0 :   bool HasFirstLetterChild() const { return mHasFirstLetterChild; }
    3994             : 
    3995             :   /**
    3996             :    * If this returns true, the frame it's called on should get the
    3997             :    * NS_FRAME_HAS_DIRTY_CHILDREN bit set on it by the caller; either directly
    3998             :    * if it's already in reflow, or via calling FrameNeedsReflow() to schedule a
    3999             :    * reflow.
    4000             :    */
    4001           0 :   virtual bool RenumberFrameAndDescendants(int32_t* aOrdinal,
    4002             :                                            int32_t aDepth,
    4003             :                                            int32_t aIncrement,
    4004           0 :                                            bool aForCounting) { return false; }
    4005             : 
    4006             :   /**
    4007             :    * Helper function - computes the content-box inline size for aCoord.
    4008             :    */
    4009             :   nscoord ComputeISizeValue(gfxContext*         aRenderingContext,
    4010             :                             nscoord             aContainingBlockISize,
    4011             :                             nscoord             aContentEdgeToBoxSizing,
    4012             :                             nscoord             aBoxSizingToMarginEdge,
    4013             :                             const nsStyleCoord& aCoord,
    4014             :                             ComputeSizeFlags    aFlags = eDefault);
    4015             : 
    4016       10667 :   DisplayItemArray& DisplayItemData() { return mDisplayItemData; }
    4017             : 
    4018             : protected:
    4019             : 
    4020             :   /**
    4021             :    * Reparent this frame's view if it has one.
    4022             :    */
    4023             :   void ReparentFrameViewTo(nsViewManager* aViewManager,
    4024             :                            nsView*        aNewParentView,
    4025             :                            nsView*        aOldParentView);
    4026             : 
    4027             :   /**
    4028             :    * To be overridden by frame classes that have a varying IsLeaf() state and
    4029             :    * is indicating that with DynamicLeaf in nsFrameIdList.h.
    4030             :    * @see IsLeaf()
    4031             :    */
    4032           0 :   virtual bool IsLeafDynamic() const { return false; }
    4033             : 
    4034             :   // Members
    4035             :   nsRect           mRect;
    4036             :   nsIContent*      mContent;
    4037             :   nsStyleContext*  mStyleContext;
    4038             : private:
    4039             :   nsContainerFrame* mParent;
    4040             :   nsIFrame*        mNextSibling;  // doubly-linked list of frames
    4041             :   nsIFrame*        mPrevSibling;  // Do not touch outside SetNextSibling!
    4042             :   DisplayItemArray mDisplayItemData;
    4043             : 
    4044             :   void MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect);
    4045             : 
    4046           0 :   static void DestroyPaintedPresShellList(nsTArray<nsWeakPtr>* list) {
    4047           0 :     list->Clear();
    4048           0 :     delete list;
    4049           0 :   }
    4050             : 
    4051             :   // Stores weak references to all the PresShells that were painted during
    4052             :   // the last paint event so that we can increment their paint count during
    4053             :   // empty transactions
    4054          60 :   NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(PaintedPresShellsProperty,
    4055             :                                       nsTArray<nsWeakPtr>,
    4056             :                                       DestroyPaintedPresShellList)
    4057             : 
    4058          58 :   nsTArray<nsWeakPtr>* PaintedPresShellList() {
    4059          58 :     nsTArray<nsWeakPtr>* list = GetProperty(PaintedPresShellsProperty());
    4060             : 
    4061          58 :     if (!list) {
    4062           2 :       list = new nsTArray<nsWeakPtr>();
    4063           2 :       SetProperty(PaintedPresShellsProperty(), list);
    4064             :     }
    4065             : 
    4066          58 :     return list;
    4067             :   }
    4068             : 
    4069             : protected:
    4070             :   /**
    4071             :    * Copies aRootElemWM to mWritingMode on 'this' and all its ancestors.
    4072             :    */
    4073             :   inline void PropagateRootElementWritingMode(mozilla::WritingMode aRootElemWM);
    4074             : 
    4075         591 :   void MarkInReflow() {
    4076             : #ifdef DEBUG_dbaron_off
    4077             :     // bug 81268
    4078             :     NS_ASSERTION(!(mState & NS_FRAME_IN_REFLOW), "frame is already in reflow");
    4079             : #endif
    4080         591 :     mState |= NS_FRAME_IN_REFLOW;
    4081         591 :   }
    4082             : 
    4083             :   nsFrameState     mState;
    4084             : 
    4085             :   /**
    4086             :    * List of properties attached to the frame.
    4087             :    */
    4088             :   FrameProperties  mProperties;
    4089             : 
    4090             :   // When there is an overflow area only slightly larger than mRect,
    4091             :   // we store a set of four 1-byte deltas from the edges of mRect
    4092             :   // rather than allocating a whole separate rectangle property.
    4093             :   // Note that these are unsigned values, all measured "outwards"
    4094             :   // from the edges of mRect, so /mLeft/ and /mTop/ are reversed from
    4095             :   // our normal coordinate system.
    4096             :   // If mOverflow.mType == NS_FRAME_OVERFLOW_LARGE, then the
    4097             :   // delta values are not meaningful and the overflow area is stored
    4098             :   // as a separate rect property.
    4099             :   struct VisualDeltas {
    4100             :     uint8_t mLeft;
    4101             :     uint8_t mTop;
    4102             :     uint8_t mRight;
    4103             :     uint8_t mBottom;
    4104          11 :     bool operator==(const VisualDeltas& aOther) const
    4105             :     {
    4106          29 :       return mLeft == aOther.mLeft && mTop == aOther.mTop &&
    4107          27 :              mRight == aOther.mRight && mBottom == aOther.mBottom;
    4108             :     }
    4109          11 :     bool operator!=(const VisualDeltas& aOther) const
    4110             :     {
    4111          11 :       return !(*this == aOther);
    4112             :     }
    4113             :   };
    4114             :   union {
    4115             :     uint32_t     mType;
    4116             :     VisualDeltas mVisualDeltas;
    4117             :   } mOverflow;
    4118             : 
    4119             :   /** @see GetWritingMode() */
    4120             :   mozilla::WritingMode mWritingMode;
    4121             : 
    4122             :   /** The ClassID of the concrete class of this instance. */
    4123             :   ClassID mClass; // 1 byte
    4124             : 
    4125             :   bool mMayHaveRoundedCorners : 1;
    4126             : 
    4127             :   /**
    4128             :    * True iff this frame has one or more associated image requests.
    4129             :    * @see mozilla::css::ImageLoader.
    4130             :    */
    4131             :   bool mHasImageRequest : 1;
    4132             : 
    4133             :   /**
    4134             :    * True if this frame has a continuation that has a first-letter frame, or its
    4135             :    * placeholder, as a child.  In that case this frame has a blockframe ancestor
    4136             :    * that has the first-letter frame hanging off it in the
    4137             :    * nsContainerFrame::FirstLetterProperty() property.
    4138             :    */
    4139             :   bool mHasFirstLetterChild : 1;
    4140             : 
    4141             :   // There is a 13-bit gap left here.
    4142             : 
    4143             :   // Helpers
    4144             :   /**
    4145             :    * Can we stop inside this frame when we're skipping non-rendered whitespace?
    4146             :    * @param  aForward [in] Are we moving forward (or backward) in content order.
    4147             :    * @param  aOffset [in/out] At what offset into the frame to start looking.
    4148             :    *         on output - what offset was reached (whether or not we found a place to stop).
    4149             :    * @return STOP: An appropriate offset was found within this frame,
    4150             :    *         and is given by aOffset.
    4151             :    *         CONTINUE: Not found within this frame, need to try the next frame.
    4152             :    *         see enum FrameSearchResult for more details.
    4153             :    */
    4154             :   virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) = 0;
    4155             : 
    4156             :   /**
    4157             :    * Search the frame for the next character
    4158             :    * @param  aForward [in] Are we moving forward (or backward) in content order.
    4159             :    * @param  aOffset [in/out] At what offset into the frame to start looking.
    4160             :    *         on output - what offset was reached (whether or not we found a place to stop).
    4161             :    * @param  aOptions [in] Options, see the comment in
    4162             :    *         PeekOffsetCharacterOptions for the detail.
    4163             :    * @return STOP: An appropriate offset was found within this frame,
    4164             :    *         and is given by aOffset.
    4165             :    *         CONTINUE: Not found within this frame, need to try the next frame.
    4166             :    *         see enum FrameSearchResult for more details.
    4167             :    */
    4168             :   virtual FrameSearchResult
    4169             :   PeekOffsetCharacter(bool aForward, int32_t* aOffset,
    4170             :                       PeekOffsetCharacterOptions aOptions =
    4171             :                         PeekOffsetCharacterOptions()) = 0;
    4172             :   static_assert(sizeof(PeekOffsetCharacterOptions) <= sizeof(intptr_t),
    4173             :                 "aOptions should be changed to const reference");
    4174             : 
    4175             :   /**
    4176             :    * Search the frame for the next word boundary
    4177             :    * @param  aForward [in] Are we moving forward (or backward) in content order.
    4178             :    * @param  aWordSelectEatSpace [in] true: look for non-whitespace following
    4179             :    *         whitespace (in the direction of movement).
    4180             :    *         false: look for whitespace following non-whitespace (in the
    4181             :    *         direction  of movement).
    4182             :    * @param  aIsKeyboardSelect [in] Was the action initiated by a keyboard operation?
    4183             :    *         If true, punctuation immediately following a word is considered part
    4184             :    *         of that word. Otherwise, a sequence of punctuation is always considered
    4185             :    *         as a word on its own.
    4186             :    * @param  aOffset [in/out] At what offset into the frame to start looking.
    4187             :    *         on output - what offset was reached (whether or not we found a place to stop).
    4188             :    * @param  aState [in/out] the state that is carried from frame to frame
    4189             :    * @return true: An appropriate offset was found within this frame,
    4190             :    *         and is given by aOffset.
    4191             :    *         false: Not found within this frame, need to try the next frame.
    4192             :    */
    4193           0 :   struct PeekWordState {
    4194             :     // true when we're still at the start of the search, i.e., we can't return
    4195             :     // this point as a valid offset!
    4196             :     bool mAtStart;
    4197             :     // true when we've encountered at least one character of the pre-boundary type
    4198             :     // (whitespace if aWordSelectEatSpace is true, non-whitespace otherwise)
    4199             :     bool mSawBeforeType;
    4200             :     // true when the last character encountered was punctuation
    4201             :     bool mLastCharWasPunctuation;
    4202             :     // true when the last character encountered was whitespace
    4203             :     bool mLastCharWasWhitespace;
    4204             :     // true when we've seen non-punctuation since the last whitespace
    4205             :     bool mSeenNonPunctuationSinceWhitespace;
    4206             :     // text that's *before* the current frame when aForward is true, *after*
    4207             :     // the current frame when aForward is false. Only includes the text
    4208             :     // on the current line.
    4209             :     nsAutoString mContext;
    4210             : 
    4211           0 :     PeekWordState() : mAtStart(true), mSawBeforeType(false),
    4212             :         mLastCharWasPunctuation(false), mLastCharWasWhitespace(false),
    4213           0 :         mSeenNonPunctuationSinceWhitespace(false) {}
    4214           0 :     void SetSawBeforeType() { mSawBeforeType = true; }
    4215           0 :     void Update(bool aAfterPunctuation, bool aAfterWhitespace) {
    4216           0 :       mLastCharWasPunctuation = aAfterPunctuation;
    4217           0 :       mLastCharWasWhitespace = aAfterWhitespace;
    4218           0 :       if (aAfterWhitespace) {
    4219           0 :         mSeenNonPunctuationSinceWhitespace = false;
    4220           0 :       } else if (!aAfterPunctuation) {
    4221           0 :         mSeenNonPunctuationSinceWhitespace = true;
    4222             :       }
    4223           0 :       mAtStart = false;
    4224           0 :     }
    4225             :   };
    4226             :   virtual FrameSearchResult PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
    4227             :                                 int32_t* aOffset, PeekWordState* aState) = 0;
    4228             : 
    4229             :   /**
    4230             :    * Search for the first paragraph boundary before or after the given position
    4231             :    * @param  aPos See description in nsFrameSelection.h. The following fields are
    4232             :    *              used by this method:
    4233             :    *              Input: mDirection
    4234             :    *              Output: mResultContent, mContentOffset
    4235             :    */
    4236             :   nsresult PeekOffsetParagraph(nsPeekOffsetStruct *aPos);
    4237             : 
    4238             : private:
    4239             :   // Get a pointer to the overflow areas property attached to the frame.
    4240        1444 :   nsOverflowAreas* GetOverflowAreasProperty() const {
    4241        1444 :     MOZ_ASSERT(mOverflow.mType == NS_FRAME_OVERFLOW_LARGE);
    4242        1444 :     nsOverflowAreas* overflow = GetProperty(OverflowAreasProperty());
    4243        1444 :     MOZ_ASSERT(overflow);
    4244        1444 :     return overflow;
    4245             :   }
    4246             : 
    4247        1268 :   nsRect GetVisualOverflowFromDeltas() const {
    4248        1268 :     MOZ_ASSERT(mOverflow.mType != NS_FRAME_OVERFLOW_LARGE,
    4249             :                "should not be called when overflow is in a property");
    4250             :     // Calculate the rect using deltas from the frame's border rect.
    4251             :     // Note that the mOverflow.mDeltas fields are unsigned, but we will often
    4252             :     // need to return negative values for the left and top, so take care
    4253             :     // to cast away the unsigned-ness.
    4254        1268 :     return nsRect(-(int32_t)mOverflow.mVisualDeltas.mLeft,
    4255        1268 :                   -(int32_t)mOverflow.mVisualDeltas.mTop,
    4256        1268 :                   mRect.width + mOverflow.mVisualDeltas.mRight +
    4257        1268 :                                 mOverflow.mVisualDeltas.mLeft,
    4258        1268 :                   mRect.height + mOverflow.mVisualDeltas.mBottom +
    4259        5072 :                                  mOverflow.mVisualDeltas.mTop);
    4260             :   }
    4261             :   /**
    4262             :    * Returns true if any overflow changed.
    4263             :    */
    4264             :   bool SetOverflowAreas(const nsOverflowAreas& aOverflowAreas);
    4265             : 
    4266             :   // Helper-functions for SortFrameList():
    4267             :   template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
    4268             :   static nsIFrame* SortedMerge(nsIFrame *aLeft, nsIFrame *aRight);
    4269             : 
    4270             :   template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
    4271             :   static nsIFrame* MergeSort(nsIFrame *aSource);
    4272             : 
    4273             :   bool HasOpacityInternal(float aThreshold,
    4274             :                           mozilla::EffectSet* aEffectSet = nullptr) const;
    4275             : 
    4276             :   // Maps mClass to LayoutFrameType.
    4277             :   static const mozilla::LayoutFrameType sLayoutFrameTypes[
    4278             : #define FRAME_ID(...) 1 +
    4279             : #define ABSTRACT_FRAME_ID(...)
    4280             : #include "nsFrameIdList.h"
    4281             : #undef FRAME_ID
    4282             : #undef ABSTRACT_FRAME_ID
    4283             :   0];
    4284             : 
    4285             :   enum FrameClassBits {
    4286             :     eFrameClassBitsNone        = 0x0,
    4287             :     eFrameClassBitsLeaf        = 0x1,
    4288             :     eFrameClassBitsDynamicLeaf = 0x2,
    4289             :   };
    4290             :   // Maps mClass to IsLeaf() flags.
    4291             :   static const FrameClassBits sFrameClassBits[
    4292             : #define FRAME_ID(...) 1 +
    4293             : #define ABSTRACT_FRAME_ID(...)
    4294             : #include "nsFrameIdList.h"
    4295             : #undef FRAME_ID
    4296             : #undef ABSTRACT_FRAME_ID
    4297             :   0];
    4298             : 
    4299             : #ifdef DEBUG_FRAME_DUMP
    4300             : public:
    4301           0 :   static void IndentBy(FILE* out, int32_t aIndent) {
    4302           0 :     while (--aIndent >= 0) fputs("  ", out);
    4303           0 :   }
    4304           0 :   void ListTag(FILE* out) const {
    4305           0 :     ListTag(out, this);
    4306           0 :   }
    4307           0 :   static void ListTag(FILE* out, const nsIFrame* aFrame) {
    4308           0 :     nsAutoCString t;
    4309           0 :     ListTag(t, aFrame);
    4310           0 :     fputs(t.get(), out);
    4311           0 :   }
    4312             :   static void ListTag(FILE* out, const nsFrameList& aFrameList) {
    4313             :     for (nsIFrame* frame : aFrameList) {
    4314             :       ListTag(out, frame);
    4315             :     }
    4316             :   }
    4317             :   void ListTag(nsACString& aTo) const;
    4318           0 :   nsAutoCString ListTag() const {
    4319           0 :     nsAutoCString tag;
    4320           0 :     ListTag(tag);
    4321           0 :     return tag;
    4322             :   }
    4323             :   static void ListTag(nsACString& aTo, const nsIFrame* aFrame);
    4324             :   void ListGeneric(nsACString& aTo, const char* aPrefix = "", uint32_t aFlags = 0) const;
    4325             :   enum {
    4326             :     TRAVERSE_SUBDOCUMENT_FRAMES = 0x01
    4327             :   };
    4328             :   virtual void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const;
    4329             :   /**
    4330             :    * lists the frames beginning from the root frame
    4331             :    * - calls root frame's List(...)
    4332             :    */
    4333             :   static void RootFrameList(nsPresContext* aPresContext,
    4334             :                             FILE* out = stderr, const char* aPrefix = "");
    4335             :   virtual void DumpFrameTree() const;
    4336             :   void DumpFrameTreeLimited() const;
    4337             : 
    4338             :   virtual nsresult  GetFrameName(nsAString& aResult) const = 0;
    4339             : #endif
    4340             : 
    4341             : #ifdef DEBUG
    4342             : public:
    4343             :   virtual nsFrameState  GetDebugStateBits() const = 0;
    4344             :   virtual nsresult  DumpRegressionData(nsPresContext* aPresContext,
    4345             :                                        FILE* out, int32_t aIndent) = 0;
    4346             : #endif
    4347             : };
    4348             : 
    4349             : //----------------------------------------------------------------------
    4350             : 
    4351             : /**
    4352             :  * AutoWeakFrame can be used to keep a reference to a nsIFrame in a safe way.
    4353             :  * Whenever an nsIFrame object is deleted, the AutoWeakFrames pointing
    4354             :  * to it will be cleared.  AutoWeakFrame is for variables on the stack or
    4355             :  * in static storage only, there is also a WeakFrame below for heap uses.
    4356             :  *
    4357             :  * Create AutoWeakFrame object when it is sure that nsIFrame object
    4358             :  * is alive and after some operations which may destroy the nsIFrame
    4359             :  * (for example any DOM modifications) use IsAlive() or GetFrame() methods to
    4360             :  * check whether it is safe to continue to use the nsIFrame object.
    4361             :  *
    4362             :  * @note The usage of this class should be kept to a minimum.
    4363             :  */
    4364             : class WeakFrame;
    4365             : class MOZ_NONHEAP_CLASS AutoWeakFrame
    4366             : {
    4367             : public:
    4368          13 :   explicit AutoWeakFrame()
    4369          13 :     : mPrev(nullptr), mFrame(nullptr) {}
    4370             : 
    4371           0 :   AutoWeakFrame(const AutoWeakFrame& aOther)
    4372           0 :     : mPrev(nullptr), mFrame(nullptr)
    4373             :   {
    4374           0 :     Init(aOther.GetFrame());
    4375           0 :   }
    4376             : 
    4377             :   MOZ_IMPLICIT AutoWeakFrame(const WeakFrame& aOther);
    4378             : 
    4379         131 :   MOZ_IMPLICIT AutoWeakFrame(nsIFrame* aFrame)
    4380         131 :     : mPrev(nullptr), mFrame(nullptr)
    4381             :   {
    4382         131 :     Init(aFrame);
    4383         131 :   }
    4384             : 
    4385             :   AutoWeakFrame& operator=(AutoWeakFrame& aOther) {
    4386             :     Init(aOther.GetFrame());
    4387             :     return *this;
    4388             :   }
    4389             : 
    4390           4 :   AutoWeakFrame& operator=(nsIFrame* aFrame) {
    4391           4 :     Init(aFrame);
    4392           4 :     return *this;
    4393             :   }
    4394             : 
    4395           0 :   nsIFrame* operator->()
    4396             :   {
    4397           0 :     return mFrame;
    4398             :   }
    4399             : 
    4400          14 :   operator nsIFrame*()
    4401             :   {
    4402          14 :     return mFrame;
    4403             :   }
    4404             : 
    4405         263 :   void Clear(nsIPresShell* aShell) {
    4406         263 :     if (aShell) {
    4407         118 :       aShell->RemoveAutoWeakFrame(this);
    4408             :     }
    4409         263 :     mFrame = nullptr;
    4410         263 :     mPrev = nullptr;
    4411         263 :   }
    4412             : 
    4413         104 :   bool IsAlive() { return !!mFrame; }
    4414             : 
    4415         236 :   nsIFrame* GetFrame() const { return mFrame; }
    4416             : 
    4417         118 :   AutoWeakFrame* GetPreviousWeakFrame() { return mPrev; }
    4418             : 
    4419         118 :   void SetPreviousWeakFrame(AutoWeakFrame* aPrev) { mPrev = aPrev; }
    4420             : 
    4421         124 :   ~AutoWeakFrame()
    4422         124 :   {
    4423         124 :     Clear(mFrame ? mFrame->PresContext()->GetPresShell() : nullptr);
    4424         124 :   }
    4425             : private:
    4426             :   // Not available for the heap!
    4427             :   void* operator new(size_t) = delete;
    4428             :   void* operator new[](size_t) = delete;
    4429             :   void operator delete(void*) = delete;
    4430             :   void operator delete[](void*) = delete;
    4431             : 
    4432             :   void Init(nsIFrame* aFrame);
    4433             : 
    4434             :   AutoWeakFrame*  mPrev;
    4435             :   nsIFrame*       mFrame;
    4436             : };
    4437             : 
    4438             : /**
    4439             :  * @see AutoWeakFrame
    4440             :  */
    4441             : class MOZ_HEAP_CLASS WeakFrame
    4442             : {
    4443             : public:
    4444          10 :   WeakFrame() : mFrame(nullptr) {}
    4445             : 
    4446             :   WeakFrame(const WeakFrame& aOther) : mFrame(nullptr)
    4447             :   {
    4448             :     Init(aOther.GetFrame());
    4449             :   }
    4450             : 
    4451             :   MOZ_IMPLICIT WeakFrame(const AutoWeakFrame& aOther) : mFrame(nullptr)
    4452             :   {
    4453             :     Init(aOther.GetFrame());
    4454             :   }
    4455             : 
    4456          48 :   MOZ_IMPLICIT WeakFrame(nsIFrame* aFrame) : mFrame(nullptr)
    4457             :   {
    4458          48 :     Init(aFrame);
    4459          48 :   }
    4460             : 
    4461          21 :   ~WeakFrame()
    4462          21 :   {
    4463          21 :     Clear(mFrame ? mFrame->PresContext()->GetPresShell() : nullptr);
    4464          21 :   }
    4465             : 
    4466           0 :   WeakFrame& operator=(WeakFrame& aOther) {
    4467           0 :     Init(aOther.GetFrame());
    4468           0 :     return *this;
    4469             :   }
    4470             : 
    4471         222 :   WeakFrame& operator=(nsIFrame* aFrame) {
    4472         222 :     Init(aFrame);
    4473         222 :     return *this;
    4474             :   }
    4475             : 
    4476           6 :   nsIFrame* operator->() { return mFrame; }
    4477         427 :   operator nsIFrame*() { return mFrame; }
    4478             : 
    4479         291 :   void Clear(nsIPresShell* aShell) {
    4480         291 :     if (aShell) {
    4481          41 :       aShell->RemoveWeakFrame(this);
    4482             :     }
    4483         291 :     mFrame = nullptr;
    4484         291 :   }
    4485             : 
    4486          31 :   bool IsAlive() { return !!mFrame; }
    4487         108 :   nsIFrame* GetFrame() const { return mFrame; }
    4488             : 
    4489             : private:
    4490             :   void Init(nsIFrame* aFrame);
    4491             : 
    4492             :   nsIFrame* mFrame;
    4493             : };
    4494             : 
    4495             : inline bool
    4496           0 : nsFrameList::ContinueRemoveFrame(nsIFrame* aFrame)
    4497             : {
    4498           0 :   MOZ_ASSERT(!aFrame->GetPrevSibling() || !aFrame->GetNextSibling(),
    4499             :              "Forgot to call StartRemoveFrame?");
    4500           0 :   if (aFrame == mLastChild) {
    4501           0 :     MOZ_ASSERT(!aFrame->GetNextSibling(), "broken frame list");
    4502           0 :     nsIFrame* prevSibling = aFrame->GetPrevSibling();
    4503           0 :     if (!prevSibling) {
    4504           0 :       MOZ_ASSERT(aFrame == mFirstChild, "broken frame list");
    4505           0 :       mFirstChild = mLastChild = nullptr;
    4506           0 :       return true;
    4507             :     }
    4508           0 :     MOZ_ASSERT(prevSibling->GetNextSibling() == aFrame, "Broken frame linkage");
    4509           0 :     prevSibling->SetNextSibling(nullptr);
    4510           0 :     mLastChild = prevSibling;
    4511           0 :     return true;
    4512             :   }
    4513           0 :   if (aFrame == mFirstChild) {
    4514           0 :     MOZ_ASSERT(!aFrame->GetPrevSibling(), "broken frame list");
    4515           0 :     mFirstChild = aFrame->GetNextSibling();
    4516           0 :     aFrame->SetNextSibling(nullptr);
    4517           0 :     MOZ_ASSERT(mFirstChild, "broken frame list");
    4518           0 :     return true;
    4519             :   }
    4520           0 :   return false;
    4521             : }
    4522             : 
    4523             : inline bool
    4524           0 : nsFrameList::StartRemoveFrame(nsIFrame* aFrame)
    4525             : {
    4526           0 :   if (aFrame->GetPrevSibling() && aFrame->GetNextSibling()) {
    4527           0 :     UnhookFrameFromSiblings(aFrame);
    4528           0 :     return true;
    4529             :   }
    4530           0 :   return ContinueRemoveFrame(aFrame);
    4531             : }
    4532             : 
    4533             : inline void
    4534        7027 : nsFrameList::Enumerator::Next()
    4535             : {
    4536        7027 :   NS_ASSERTION(!AtEnd(), "Should have checked AtEnd()!");
    4537        7027 :   mFrame = mFrame->GetNextSibling();
    4538        7027 : }
    4539             : 
    4540             : inline
    4541           0 : nsFrameList::FrameLinkEnumerator::
    4542           0 : FrameLinkEnumerator(const nsFrameList& aList, nsIFrame* aPrevFrame)
    4543           0 :   : Enumerator(aList)
    4544             : {
    4545           0 :   mPrev = aPrevFrame;
    4546           0 :   mFrame = aPrevFrame ? aPrevFrame->GetNextSibling() : aList.FirstChild();
    4547           0 : }
    4548             : 
    4549             : inline void
    4550           0 : nsFrameList::FrameLinkEnumerator::Next()
    4551             : {
    4552           0 :   mPrev = mFrame;
    4553           0 :   Enumerator::Next();
    4554           0 : }
    4555             : 
    4556             : // Operators of nsFrameList::Iterator
    4557             : // ---------------------------------------------------
    4558             : 
    4559             : inline nsFrameList::Iterator&
    4560        3086 : nsFrameList::Iterator::operator++()
    4561             : {
    4562        3086 :   mCurrent = mCurrent->GetNextSibling();
    4563        3086 :   return *this;
    4564             : }
    4565             : 
    4566             : inline nsFrameList::Iterator&
    4567           0 : nsFrameList::Iterator::operator--()
    4568             : {
    4569           0 :   if (!mCurrent) {
    4570           0 :     mCurrent = mList.LastChild();
    4571             :   } else {
    4572           0 :     mCurrent = mCurrent->GetPrevSibling();
    4573             :   }
    4574           0 :   return *this;
    4575             : }
    4576             : 
    4577             : // Helper-functions for nsIFrame::SortFrameList()
    4578             : // ---------------------------------------------------
    4579             : 
    4580             : template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
    4581             : /* static */ nsIFrame*
    4582           0 : nsIFrame::SortedMerge(nsIFrame *aLeft, nsIFrame *aRight)
    4583             : {
    4584           0 :   NS_PRECONDITION(aLeft && aRight, "SortedMerge must have non-empty lists");
    4585             : 
    4586             :   nsIFrame *result;
    4587             :   // Unroll first iteration to avoid null-check 'result' inside the loop.
    4588           0 :   if (IsLessThanOrEqual(aLeft, aRight)) {
    4589           0 :     result = aLeft;
    4590           0 :     aLeft = aLeft->GetNextSibling();
    4591           0 :     if (!aLeft) {
    4592           0 :       result->SetNextSibling(aRight);
    4593           0 :       return result;
    4594             :     }
    4595             :   }
    4596             :   else {
    4597           0 :     result = aRight;
    4598           0 :     aRight = aRight->GetNextSibling();
    4599           0 :     if (!aRight) {
    4600           0 :       result->SetNextSibling(aLeft);
    4601           0 :       return result;
    4602             :     }
    4603             :   }
    4604             : 
    4605           0 :   nsIFrame *last = result;
    4606             :   for (;;) {
    4607           0 :     if (IsLessThanOrEqual(aLeft, aRight)) {
    4608           0 :       last->SetNextSibling(aLeft);
    4609           0 :       last = aLeft;
    4610           0 :       aLeft = aLeft->GetNextSibling();
    4611           0 :       if (!aLeft) {
    4612           0 :         last->SetNextSibling(aRight);
    4613           0 :         return result;
    4614             :       }
    4615             :     }
    4616             :     else {
    4617           0 :       last->SetNextSibling(aRight);
    4618           0 :       last = aRight;
    4619           0 :       aRight = aRight->GetNextSibling();
    4620           0 :       if (!aRight) {
    4621           0 :         last->SetNextSibling(aLeft);
    4622           0 :         return result;
    4623             :       }
    4624             :     }
    4625             :   }
    4626             : }
    4627             : 
    4628             : template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
    4629             : /* static */ nsIFrame*
    4630           0 : nsIFrame::MergeSort(nsIFrame *aSource)
    4631             : {
    4632           0 :   NS_PRECONDITION(aSource, "MergeSort null arg");
    4633             : 
    4634           0 :   nsIFrame *sorted[32] = { nullptr };
    4635           0 :   nsIFrame **fill = &sorted[0];
    4636             :   nsIFrame **left;
    4637           0 :   nsIFrame *rest = aSource;
    4638             : 
    4639           0 :   do {
    4640           0 :     nsIFrame *current = rest;
    4641           0 :     rest = rest->GetNextSibling();
    4642           0 :     current->SetNextSibling(nullptr);
    4643             : 
    4644             :     // Merge it with sorted[0] if present; then merge the result with sorted[1] etc.
    4645             :     // sorted[0] is a list of length 1 (or nullptr).
    4646             :     // sorted[1] is a list of length 2 (or nullptr).
    4647             :     // sorted[2] is a list of length 4 (or nullptr). etc.
    4648           0 :     for (left = &sorted[0]; left != fill && *left; ++left) {
    4649           0 :       current = SortedMerge<IsLessThanOrEqual>(*left, current);
    4650           0 :       *left = nullptr;
    4651             :     }
    4652             : 
    4653             :     // Fill the empty slot that we couldn't merge with the last result.
    4654           0 :     *left = current;
    4655             : 
    4656           0 :     if (left == fill)
    4657           0 :       ++fill;
    4658             :   } while (rest);
    4659             : 
    4660             :   // Collect and merge the results.
    4661           0 :   nsIFrame *result = nullptr;
    4662           0 :   for (left = &sorted[0]; left != fill; ++left) {
    4663           0 :     if (*left) {
    4664           0 :       result = result ? SortedMerge<IsLessThanOrEqual>(*left, result) : *left;
    4665             :     }
    4666             :   }
    4667           0 :   return result;
    4668             : }
    4669             : 
    4670             : template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
    4671             : /* static */ void
    4672           0 : nsIFrame::SortFrameList(nsFrameList& aFrameList)
    4673             : {
    4674           0 :   nsIFrame* head = MergeSort<IsLessThanOrEqual>(aFrameList.FirstChild());
    4675           0 :   aFrameList = nsFrameList(head, nsLayoutUtils::GetLastSibling(head));
    4676           0 :   MOZ_ASSERT(IsFrameListSorted<IsLessThanOrEqual>(aFrameList),
    4677             :              "After we sort a frame list, it should be in sorted order...");
    4678           0 : }
    4679             : 
    4680             : template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
    4681             : /* static */ bool
    4682         262 : nsIFrame::IsFrameListSorted(nsFrameList& aFrameList)
    4683             : {
    4684         262 :   if (aFrameList.IsEmpty()) {
    4685             :     // empty lists are trivially sorted.
    4686          77 :     return true;
    4687             :   }
    4688             : 
    4689             :   // We'll walk through the list with two iterators, one trailing behind the
    4690             :   // other. The list is sorted IFF trailingIter <= iter, across the whole list.
    4691         185 :   nsFrameList::Enumerator trailingIter(aFrameList);
    4692         185 :   nsFrameList::Enumerator iter(aFrameList);
    4693         185 :   iter.Next(); // Skip |iter| past first frame. (List is nonempty, so we can.)
    4694             : 
    4695             :   // Now, advance the iterators in parallel, comparing each adjacent pair.
    4696         559 :   while (!iter.AtEnd()) {
    4697         187 :     MOZ_ASSERT(!trailingIter.AtEnd(), "trailing iter shouldn't finish first");
    4698         187 :     if (!IsLessThanOrEqual(trailingIter.get(), iter.get())) {
    4699           0 :       return false;
    4700             :     }
    4701         187 :     trailingIter.Next();
    4702         187 :     iter.Next();
    4703             :   }
    4704             : 
    4705             :   // We made it to the end without returning early, so the list is sorted.
    4706         185 :   return true;
    4707             : }
    4708             : 
    4709             : // Needs to be defined here rather than nsIFrameInlines.h, because it is used
    4710             : // within this header.
    4711             : nsPoint
    4712           0 : nsIFrame::GetNormalPosition(bool* aHasProperty) const
    4713             : {
    4714           0 :   nsPoint* normalPosition = GetProperty(NormalPositionProperty());
    4715           0 :   if (normalPosition) {
    4716           0 :     if (aHasProperty) {
    4717           0 :       *aHasProperty = true;
    4718             :     }
    4719           0 :     return *normalPosition;
    4720             :   }
    4721           0 :   if (aHasProperty) {
    4722           0 :     *aHasProperty = false;
    4723             :   }
    4724           0 :   return GetPosition();
    4725             : }
    4726             : 
    4727             : #endif /* nsIFrame_h___ */

Generated by: LCOV version 1.13