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