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