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