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