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