forked from mirrors/gecko-dev
		
	 048a8ca37c
			
		
	
	
		048a8ca37c
		
	
	
	
	
		
			
			The reason why const_cast is used for nsLayoutUtils::GetNearestScrollableFrame is that if we changed the function as well, it ends up scattering const_cast in most call sites of the function. That's because GetNearestScrollableFrame has a do_QueryFrame call for the given nsIFrame* and returns the queried frame, so it will be like this; const nsIScrollableFrame* GetNearestScrollableFrame(const nsIFrame*, ..) Most call sites of this function are then calls do_QueryFrame for the returned nsIScrollableFrame*. MozReview-Commit-ID: EwccKUITL89 --HG-- extra : rebase_source : f3b915fc78c096ca18d0922c764d15d73d552910
		
			
				
	
	
		
			4946 lines
		
	
	
	
		
			184 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			4946 lines
		
	
	
	
		
			184 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| /* interface for all rendering objects */
 | |
| 
 | |
| #ifndef nsIFrame_h___
 | |
| #define nsIFrame_h___
 | |
| 
 | |
| #ifndef MOZILLA_INTERNAL_API
 | |
| #error This header/class should only be used within Mozilla code. It should not be used by extensions.
 | |
| #endif
 | |
| 
 | |
| #define MAX_REFLOW_DEPTH 200
 | |
| 
 | |
| /* nsIFrame is in the process of being deCOMtaminated, i.e., this file is eventually
 | |
|    going to be eliminated, and all callers will use nsFrame instead.  At the moment
 | |
|    we're midway through this process, so you will see inlined functions and member
 | |
|    variables in this file.  -dwh */
 | |
| 
 | |
| #include <algorithm>
 | |
| #include <stdio.h>
 | |
| 
 | |
| #include "CaretAssociationHint.h"
 | |
| #include "FrameProperties.h"
 | |
| #include "LayoutConstants.h"
 | |
| #include "mozilla/layout/FrameChildList.h"
 | |
| #include "mozilla/Maybe.h"
 | |
| #include "mozilla/SmallPointerArray.h"
 | |
| #include "mozilla/WritingModes.h"
 | |
| #include "nsDirection.h"
 | |
| #include "nsFrameList.h"
 | |
| #include "nsFrameState.h"
 | |
| #include "mozilla/ReflowOutput.h"
 | |
| #include "nsITheme.h"
 | |
| #include "nsLayoutUtils.h"
 | |
| #include "nsQueryFrame.h"
 | |
| #include "nsString.h"
 | |
| #include "mozilla/ComputedStyle.h"
 | |
| #include "nsStyleStruct.h"
 | |
| #include "Visibility.h"
 | |
| #include "nsChangeHint.h"
 | |
| #include "mozilla/ComputedStyleInlines.h"
 | |
| #include "mozilla/gfx/CompositorHitTestInfo.h"
 | |
| #include "mozilla/gfx/MatrixFwd.h"
 | |
| #include "nsDisplayItemTypes.h"
 | |
| 
 | |
| #ifdef ACCESSIBILITY
 | |
| #include "mozilla/a11y/AccTypes.h"
 | |
| #endif
 | |
| 
 | |
| /**
 | |
|  * New rules of reflow:
 | |
|  * 1. you get a WillReflow() followed by a Reflow() followed by a DidReflow() in order
 | |
|  *    (no separate pass over the tree)
 | |
|  * 2. it's the parent frame's responsibility to size/position the child's view (not
 | |
|  *    the child frame's responsibility as it is today) during reflow (and before
 | |
|  *    sending the DidReflow() notification)
 | |
|  * 3. positioning of child frames (and their views) is done on the way down the tree,
 | |
|  *    and sizing of child frames (and their views) on the way back up
 | |
|  * 4. if you move a frame (outside of the reflow process, or after reflowing it),
 | |
|  *    then you must make sure that its view (or its child frame's views) are re-positioned
 | |
|  *    as well. It's reasonable to not position the view until after all reflowing the
 | |
|  *    entire line, for example, but the frame should still be positioned and sized (and
 | |
|  *    the view sized) during the reflow (i.e., before sending the DidReflow() notification)
 | |
|  * 5. the view system handles moving of widgets, i.e., it's not our problem
 | |
|  */
 | |
| 
 | |
| class nsAtom;
 | |
| class nsPresContext;
 | |
| class nsIPresShell;
 | |
| class nsView;
 | |
| class nsIWidget;
 | |
| class nsISelectionController;
 | |
| class nsBoxLayoutState;
 | |
| class nsBoxLayout;
 | |
| class nsILineIterator;
 | |
| class nsDisplayItem;
 | |
| class nsDisplayListBuilder;
 | |
| class nsDisplayListSet;
 | |
| class nsDisplayList;
 | |
| class gfxSkipChars;
 | |
| class gfxSkipCharsIterator;
 | |
| class gfxContext;
 | |
| class nsLineList_iterator;
 | |
| class nsAbsoluteContainingBlock;
 | |
| class nsIContent;
 | |
| class nsContainerFrame;
 | |
| class nsPlaceholderFrame;
 | |
| class nsStyleChangeList;
 | |
| class nsWindowSizes;
 | |
| 
 | |
| struct nsPeekOffsetStruct;
 | |
| struct nsPoint;
 | |
| struct nsRect;
 | |
| struct nsSize;
 | |
| struct nsMargin;
 | |
| struct CharacterDataChangeInfo;
 | |
| 
 | |
| namespace mozilla {
 | |
| 
 | |
| enum class CSSPseudoElementType : uint8_t;
 | |
| class EventStates;
 | |
| struct ReflowInput;
 | |
| class ReflowOutput;
 | |
| class ServoRestyleState;
 | |
| class DisplayItemData;
 | |
| class EffectSet;
 | |
| 
 | |
| namespace layers {
 | |
| class Layer;
 | |
| class LayerManager;
 | |
| } // namespace layers
 | |
| 
 | |
| namespace dom {
 | |
| class Selection;
 | |
| } // namespace dom
 | |
| 
 | |
| } // namespace mozilla
 | |
| 
 | |
| /**
 | |
|  * Indication of how the frame can be split. This is used when doing runaround
 | |
|  * of floats, and when pulling up child frames from a next-in-flow.
 | |
|  *
 | |
|  * The choices are splittable, not splittable at all, and splittable in
 | |
|  * a non-rectangular fashion. This last type only applies to block-level
 | |
|  * elements, and indicates whether splitting can be used when doing runaround.
 | |
|  * If you can split across page boundaries, but you expect each continuing
 | |
|  * frame to be the same width then return frSplittable and not
 | |
|  * frSplittableNonRectangular.
 | |
|  *
 | |
|  * @see #GetSplittableType()
 | |
|  */
 | |
| typedef uint32_t nsSplittableType;
 | |
| 
 | |
| #define NS_FRAME_NOT_SPLITTABLE             0   // Note: not a bit!
 | |
| #define NS_FRAME_SPLITTABLE                 0x1
 | |
| #define NS_FRAME_SPLITTABLE_NON_RECTANGULAR 0x3
 | |
| 
 | |
| #define NS_FRAME_IS_SPLITTABLE(type)\
 | |
|   (0 != ((type) & NS_FRAME_SPLITTABLE))
 | |
| 
 | |
| #define NS_FRAME_IS_NOT_SPLITTABLE(type)\
 | |
|   (0 == ((type) & NS_FRAME_SPLITTABLE))
 | |
| 
 | |
| //----------------------------------------------------------------------
 | |
| 
 | |
| #define NS_SUBTREE_DIRTY(_frame)  \
 | |
|   (((_frame)->GetStateBits() &      \
 | |
|     (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN)) != 0)
 | |
| 
 | |
| // 1 million CSS pixels less than our max app unit measure.
 | |
| // For reflowing with an "infinite" available inline space per [css-sizing].
 | |
| // (reflowing with an NS_UNCONSTRAINEDSIZE available inline size isn't allowed
 | |
| //  and leads to assertions)
 | |
| #define INFINITE_ISIZE_COORD nscoord(NS_MAXSIZE - (1000000*60))
 | |
| 
 | |
| //----------------------------------------------------------------------
 | |
| 
 | |
| namespace mozilla {
 | |
| 
 | |
| enum class LayoutFrameType : uint8_t {
 | |
| #define FRAME_TYPE(ty_) ty_,
 | |
| #include "mozilla/FrameTypeList.h"
 | |
| #undef FRAME_TYPE
 | |
| };
 | |
| 
 | |
| } // namespace mozilla
 | |
| 
 | |
| enum nsSelectionAmount {
 | |
|   eSelectCharacter = 0, // a single Unicode character;
 | |
|                         // do not use this (prefer Cluster) unless you
 | |
|                         // are really sure it's what you want
 | |
|   eSelectCluster   = 1, // a grapheme cluster: this is usually the right
 | |
|                         // choice for movement or selection by "character"
 | |
|                         // as perceived by the user
 | |
|   eSelectWord      = 2,
 | |
|   eSelectWordNoSpace = 3, // select a "word" without selecting the following
 | |
|                           // space, no matter what the default platform
 | |
|                           // behavior is
 | |
|   eSelectLine      = 4, // previous drawn line in flow.
 | |
|   // NOTE that selection code depends on the ordering of the above values,
 | |
|   // allowing simple <= tests to check categories of caret movement.
 | |
|   // Don't rearrange without checking the usage in nsSelection.cpp!
 | |
| 
 | |
|   eSelectBeginLine = 5,
 | |
|   eSelectEndLine   = 6,
 | |
|   eSelectNoAmount  = 7, // just bounce back current offset.
 | |
|   eSelectParagraph = 8  // select a "paragraph"
 | |
| };
 | |
| 
 | |
| enum nsSpread {
 | |
|   eSpreadNone   = 0,
 | |
|   eSpreadAcross = 1,
 | |
|   eSpreadDown   = 2
 | |
| };
 | |
| 
 | |
| // Carried out margin flags
 | |
| #define NS_CARRIED_TOP_MARGIN_IS_AUTO    0x1
 | |
| #define NS_CARRIED_BOTTOM_MARGIN_IS_AUTO 0x2
 | |
| 
 | |
| //----------------------------------------------------------------------
 | |
| // Reflow status returned by the Reflow() methods.
 | |
| class nsReflowStatus final {
 | |
|   using StyleClear = mozilla::StyleClear;
 | |
| 
 | |
| public:
 | |
|   nsReflowStatus()
 | |
|     : mBreakType(StyleClear::None)
 | |
|     , mInlineBreak(InlineBreak::None)
 | |
|     , mCompletion(Completion::FullyComplete)
 | |
|     , mNextInFlowNeedsReflow(false)
 | |
|     , mTruncated(false)
 | |
|     , mFirstLetterComplete(false)
 | |
|   {}
 | |
| 
 | |
|   // Reset all the member variables.
 | |
|   void Reset() {
 | |
|     mBreakType = StyleClear::None;
 | |
|     mInlineBreak = InlineBreak::None;
 | |
|     mCompletion = Completion::FullyComplete;
 | |
|     mNextInFlowNeedsReflow = false;
 | |
|     mTruncated = false;
 | |
|     mFirstLetterComplete = false;
 | |
|   }
 | |
| 
 | |
|   // Return true if all member variables have their default values.
 | |
|   bool IsEmpty() const {
 | |
|     return (IsFullyComplete() &&
 | |
|             !IsInlineBreak() &&
 | |
|             !mNextInFlowNeedsReflow &&
 | |
|             !mTruncated &&
 | |
|             !mFirstLetterComplete);
 | |
|   }
 | |
| 
 | |
|   // There are three possible completion statuses, represented by
 | |
|   // mCompletion.
 | |
|   //
 | |
|   // Incomplete means the frame does *not* map all its content, and the
 | |
|   // parent frame should create a continuing frame.
 | |
|   //
 | |
|   // OverflowIncomplete means that the frame has an overflow that is not
 | |
|   // complete, but its own box is complete. (This happens when the content
 | |
|   // overflows a fixed-height box.) The reflower should place and size the
 | |
|   // frame and continue its reflow, but it needs to create an overflow
 | |
|   // container as a continuation for this frame. See "Overflow containers"
 | |
|   // documentation in nsContainerFrame.h for more information.
 | |
|   //
 | |
|   // FullyComplete means the frame is neither Incomplete nor
 | |
|   // OverflowIncomplete. This is the default state for a nsReflowStatus.
 | |
|   //
 | |
|   enum class Completion : uint8_t {
 | |
|     // The order of the enum values is important, which represents the
 | |
|     // precedence when merging.
 | |
|     FullyComplete,
 | |
|     OverflowIncomplete,
 | |
|     Incomplete,
 | |
|   };
 | |
| 
 | |
|   bool IsIncomplete() const { return mCompletion == Completion::Incomplete; }
 | |
|   bool IsOverflowIncomplete() const {
 | |
|     return mCompletion == Completion::OverflowIncomplete;
 | |
|   }
 | |
|   bool IsFullyComplete() const {
 | |
|     return mCompletion == Completion::FullyComplete;
 | |
|   }
 | |
|   // Just for convenience; not a distinct state.
 | |
|   bool IsComplete() const { return !IsIncomplete(); }
 | |
| 
 | |
|   void SetIncomplete() {
 | |
|     mCompletion = Completion::Incomplete;
 | |
|   }
 | |
|   void SetOverflowIncomplete() {
 | |
|     mCompletion = Completion::OverflowIncomplete;
 | |
|   }
 | |
| 
 | |
|   // mNextInFlowNeedsReflow bit flag means that the next-in-flow is dirty,
 | |
|   // and also needs to be reflowed. This status only makes sense for a frame
 | |
|   // that is not complete, i.e. you wouldn't set mNextInFlowNeedsReflow when
 | |
|   // IsComplete() is true.
 | |
|   bool NextInFlowNeedsReflow() const { return mNextInFlowNeedsReflow; }
 | |
|   void SetNextInFlowNeedsReflow() { mNextInFlowNeedsReflow = true; }
 | |
| 
 | |
|   // mTruncated bit flag means that the part of the frame before the first
 | |
|   // possible break point was unable to fit in the available space.
 | |
|   // Therefore, the entire frame should be moved to the next continuation of
 | |
|   // the parent frame. A frame that begins at the top of the page must never
 | |
|   // be truncated. Doing so would likely cause an infinite loop.
 | |
|   bool IsTruncated() const { return mTruncated; }
 | |
|   void UpdateTruncated(const mozilla::ReflowInput& aReflowInput,
 | |
|                        const mozilla::ReflowOutput& aMetrics);
 | |
| 
 | |
|   // Merge the frame completion status bits from aStatus into this.
 | |
|   void MergeCompletionStatusFrom(const nsReflowStatus& aStatus)
 | |
|   {
 | |
|     if (mCompletion < aStatus.mCompletion) {
 | |
|       mCompletion = aStatus.mCompletion;
 | |
|     }
 | |
| 
 | |
|     // These asserts ensure that the mCompletion merging works as we expect.
 | |
|     // (Incomplete beats OverflowIncomplete, which beats FullyComplete.)
 | |
|     static_assert(Completion::Incomplete > Completion::OverflowIncomplete &&
 | |
|                   Completion::OverflowIncomplete > Completion::FullyComplete,
 | |
|                   "mCompletion merging won't work without this!");
 | |
| 
 | |
|     mNextInFlowNeedsReflow |= aStatus.mNextInFlowNeedsReflow;
 | |
|     mTruncated |= aStatus.mTruncated;
 | |
|   }
 | |
| 
 | |
|   // There are three possible inline-break statuses, represented by
 | |
|   // mInlineBreak.
 | |
|   //
 | |
|   // "None" means no break is requested.
 | |
|   // "Before" means the break should occur before the frame.
 | |
|   // "After" means the break should occur after the frame.
 | |
|   // (Here, "the frame" is the frame whose reflow results are being reported by
 | |
|   // this nsReflowStatus.)
 | |
|   //
 | |
|   enum class InlineBreak : uint8_t {
 | |
|     None,
 | |
|     Before,
 | |
|     After,
 | |
|   };
 | |
| 
 | |
|   bool IsInlineBreak() const { return mInlineBreak != InlineBreak::None; }
 | |
|   bool IsInlineBreakBefore() const {
 | |
|     return mInlineBreak == InlineBreak::Before;
 | |
|   }
 | |
|   bool IsInlineBreakAfter() const {
 | |
|     return mInlineBreak == InlineBreak::After;
 | |
|   }
 | |
|   StyleClear BreakType() const { return mBreakType; }
 | |
| 
 | |
|   // Set the inline line-break-before status, and reset other bit flags. The
 | |
|   // break type is StyleClear::Line. Note that other frame completion status
 | |
|   // isn't expected to matter after calling this method.
 | |
|   void SetInlineLineBreakBeforeAndReset() {
 | |
|     Reset();
 | |
|     mBreakType = StyleClear::Line;
 | |
|     mInlineBreak = InlineBreak::Before;
 | |
|   }
 | |
| 
 | |
|   // Set the inline line-break-after status. The break type can be changed
 | |
|   // via the optional aBreakType param.
 | |
|   void SetInlineLineBreakAfter(StyleClear aBreakType = StyleClear::Line) {
 | |
|     MOZ_ASSERT(aBreakType != StyleClear::None,
 | |
|                "Break-after with StyleClear::None is meaningless!");
 | |
|     mBreakType = aBreakType;
 | |
|     mInlineBreak = InlineBreak::After;
 | |
|   }
 | |
| 
 | |
|   // mFirstLetterComplete bit flag means the break was induced by
 | |
|   // completion of a first-letter.
 | |
|   bool FirstLetterComplete() const { return mFirstLetterComplete; }
 | |
|   void SetFirstLetterComplete() { mFirstLetterComplete = true; }
 | |
| 
 | |
| #ifdef DEBUG
 | |
|   nsCString ToString() const;
 | |
| #endif
 | |
| 
 | |
| private:
 | |
|   StyleClear mBreakType;
 | |
|   InlineBreak mInlineBreak;
 | |
|   Completion mCompletion;
 | |
|   bool mNextInFlowNeedsReflow : 1;
 | |
|   bool mTruncated : 1;
 | |
|   bool mFirstLetterComplete : 1;
 | |
| };
 | |
| 
 | |
| #define NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aMetrics) \
 | |
|   aStatus.UpdateTruncated(aReflowInput, aMetrics);
 | |
| 
 | |
| #ifdef DEBUG
 | |
| // Convert nsReflowStatus to a human-readable string.
 | |
| std::ostream&
 | |
| operator<<(std::ostream& aStream, const nsReflowStatus& aStatus);
 | |
| #endif
 | |
| 
 | |
| //----------------------------------------------------------------------
 | |
| 
 | |
| /**
 | |
|  * When there is no scrollable overflow rect, the visual overflow rect
 | |
|  * may be stored as four 1-byte deltas each strictly LESS THAN 0xff, for
 | |
|  * the four edges of the rectangle, or the four bytes may be read as a
 | |
|  * single 32-bit "overflow-rect type" value including at least one 0xff
 | |
|  * byte as an indicator that the value does NOT represent four deltas.
 | |
|  * If all four deltas are zero, this means that no overflow rect has
 | |
|  * actually been set (this is the initial state of newly-created frames).
 | |
|  */
 | |
| #define NS_FRAME_OVERFLOW_DELTA_MAX     0xfe // max delta we can store
 | |
| 
 | |
| #define NS_FRAME_OVERFLOW_NONE    0x00000000 // there are no overflow rects;
 | |
|                                              // code relies on this being
 | |
|                                              // the all-zero value
 | |
| 
 | |
| #define NS_FRAME_OVERFLOW_LARGE   0x000000ff // overflow is stored as a
 | |
|                                              // separate rect property
 | |
| 
 | |
| /**
 | |
|  * nsBidiLevel is the type of the level values in our Unicode Bidi
 | |
|  * implementation.
 | |
|  * It holds an embedding level and indicates the visual direction
 | |
|  * by its bit 0 (even/odd value).<p>
 | |
|  *
 | |
|  * <li><code>aParaLevel</code> can be set to the
 | |
|  * pseudo-level values <code>NSBIDI_DEFAULT_LTR</code>
 | |
|  * and <code>NSBIDI_DEFAULT_RTL</code>.</li></ul>
 | |
|  *
 | |
|  * @see nsBidi::SetPara
 | |
|  *
 | |
|  * <p>The related constants are not real, valid level values.
 | |
|  * <code>NSBIDI_DEFAULT_XXX</code> can be used to specify
 | |
|  * a default for the paragraph level for
 | |
|  * when the <code>SetPara</code> function
 | |
|  * shall determine it but there is no
 | |
|  * strongly typed character in the input.<p>
 | |
|  *
 | |
|  * Note that the value for <code>NSBIDI_DEFAULT_LTR</code> is even
 | |
|  * and the one for <code>NSBIDI_DEFAULT_RTL</code> is odd,
 | |
|  * just like with normal LTR and RTL level values -
 | |
|  * these special values are designed that way. Also, the implementation
 | |
|  * assumes that NSBIDI_MAX_EXPLICIT_LEVEL is odd.
 | |
|  *
 | |
|  * @see NSBIDI_DEFAULT_LTR
 | |
|  * @see NSBIDI_DEFAULT_RTL
 | |
|  * @see NSBIDI_LEVEL_OVERRIDE
 | |
|  * @see NSBIDI_MAX_EXPLICIT_LEVEL
 | |
|  */
 | |
| typedef uint8_t nsBidiLevel;
 | |
| 
 | |
| /** Paragraph level setting.
 | |
|  *  If there is no strong character, then set the paragraph level to 0 (left-to-right).
 | |
|  */
 | |
| #define NSBIDI_DEFAULT_LTR 0xfe
 | |
| 
 | |
| /** Paragraph level setting.
 | |
|  *  If there is no strong character, then set the paragraph level to 1 (right-to-left).
 | |
|  */
 | |
| #define NSBIDI_DEFAULT_RTL 0xff
 | |
| 
 | |
| /**
 | |
|  * Maximum explicit embedding level.
 | |
|  * (The maximum resolved level can be up to <code>NSBIDI_MAX_EXPLICIT_LEVEL+1</code>).
 | |
|  *
 | |
|  */
 | |
| #define NSBIDI_MAX_EXPLICIT_LEVEL 125
 | |
| 
 | |
| /** Bit flag for level input.
 | |
|  *  Overrides directional properties.
 | |
|  */
 | |
| #define NSBIDI_LEVEL_OVERRIDE 0x80
 | |
| 
 | |
| /**
 | |
|  * <code>nsBidiDirection</code> values indicate the text direction.
 | |
|  */
 | |
| enum nsBidiDirection {
 | |
|   /** All left-to-right text This is a 0 value. */
 | |
|   NSBIDI_LTR,
 | |
|   /** All right-to-left text This is a 1 value. */
 | |
|   NSBIDI_RTL,
 | |
|   /** Mixed-directional text. */
 | |
|   NSBIDI_MIXED
 | |
| };
 | |
| 
 | |
| namespace mozilla {
 | |
| 
 | |
| // https://drafts.csswg.org/css-align-3/#baseline-sharing-group
 | |
| enum BaselineSharingGroup
 | |
| {
 | |
|   // NOTE Used as an array index so must be 0 and 1.
 | |
|   eFirst = 0,
 | |
|   eLast = 1,
 | |
| };
 | |
| 
 | |
| // Loosely: https://drafts.csswg.org/css-align-3/#shared-alignment-context
 | |
| enum class AlignmentContext
 | |
| {
 | |
|   eInline,
 | |
|   eTable,
 | |
|   eFlexbox,
 | |
|   eGrid,
 | |
| };
 | |
| 
 | |
| /*
 | |
|  * For replaced elements only. Gets the intrinsic dimensions of this element.
 | |
|  * The dimensions may only be one of the following two types:
 | |
|  *
 | |
|  *   eStyleUnit_Coord   - a length in app units
 | |
|  *   eStyleUnit_None    - the element has no intrinsic size in this dimension
 | |
|  */
 | |
| struct IntrinsicSize {
 | |
|   nsStyleCoord width, height;
 | |
| 
 | |
|   IntrinsicSize()
 | |
|     : width(eStyleUnit_None), height(eStyleUnit_None)
 | |
|   {}
 | |
|   IntrinsicSize(const IntrinsicSize& rhs)
 | |
|     : width(rhs.width), height(rhs.height)
 | |
|   {}
 | |
|   IntrinsicSize& operator=(const IntrinsicSize& rhs) {
 | |
|     width = rhs.width; height = rhs.height; return *this;
 | |
|   }
 | |
|   bool operator==(const IntrinsicSize& rhs) {
 | |
|     return width == rhs.width && height == rhs.height;
 | |
|   }
 | |
|   bool operator!=(const IntrinsicSize& rhs) {
 | |
|     return !(*this == rhs);
 | |
|   }
 | |
| };
 | |
| 
 | |
| // Pseudo bidi embedding level indicating nonexistence.
 | |
| static const nsBidiLevel kBidiLevelNone = 0xff;
 | |
| 
 | |
| struct FrameBidiData
 | |
| {
 | |
|   nsBidiLevel baseLevel;
 | |
|   nsBidiLevel embeddingLevel;
 | |
|   // The embedding level of virtual bidi formatting character before
 | |
|   // this frame if any. kBidiLevelNone is used to indicate nonexistence
 | |
|   // or unnecessity of such virtual character.
 | |
|   nsBidiLevel precedingControl;
 | |
| };
 | |
| 
 | |
| } // namespace mozilla
 | |
| 
 | |
| /// Generic destructor for frame properties. Calls delete.
 | |
| template<typename T>
 | |
| static void DeleteValue(T* aPropertyValue)
 | |
| {
 | |
|   delete aPropertyValue;
 | |
| }
 | |
| 
 | |
| /// Generic destructor for frame properties. Calls Release().
 | |
| template<typename T>
 | |
| static void ReleaseValue(T* aPropertyValue)
 | |
| {
 | |
|   aPropertyValue->Release();
 | |
| }
 | |
| 
 | |
| //----------------------------------------------------------------------
 | |
| 
 | |
| /**
 | |
|  * A frame in the layout model. This interface is supported by all frame
 | |
|  * objects.
 | |
|  *
 | |
|  * Frames can have multiple child lists: the default child list
 | |
|  * (referred to as the <i>principal</i> child list, and additional named
 | |
|  * child lists. There is an ordering of frames within a child list, but
 | |
|  * there is no order defined between frames in different child lists of
 | |
|  * the same parent frame.
 | |
|  *
 | |
|  * Frames are NOT reference counted. Use the Destroy() member function
 | |
|  * to destroy a frame. The lifetime of the frame hierarchy is bounded by the
 | |
|  * lifetime of the presentation shell which owns the frames.
 | |
|  *
 | |
|  * nsIFrame is a private Gecko interface. If you are not Gecko then you
 | |
|  * should not use it. If you're not in layout, then you won't be able to
 | |
|  * link to many of the functions defined here. Too bad.
 | |
|  *
 | |
|  * If you're not in layout but you must call functions in here, at least
 | |
|  * restrict yourself to calling virtual methods, which won't hurt you as badly.
 | |
|  */
 | |
| class nsIFrame : public nsQueryFrame
 | |
| {
 | |
| public:
 | |
|   using AlignmentContext = mozilla::AlignmentContext;
 | |
|   using BaselineSharingGroup = mozilla::BaselineSharingGroup;
 | |
|   template <typename T> using Maybe = mozilla::Maybe<T>;
 | |
|   using Nothing = mozilla::Nothing;
 | |
|   using OnNonvisible = mozilla::OnNonvisible;
 | |
|   template<typename T=void>
 | |
|   using PropertyDescriptor = const mozilla::FramePropertyDescriptor<T>*;
 | |
|   using ReflowInput = mozilla::ReflowInput;
 | |
|   using ReflowOutput = mozilla::ReflowOutput;
 | |
|   using Visibility = mozilla::Visibility;
 | |
| 
 | |
|   typedef mozilla::ComputedStyle ComputedStyle;
 | |
|   typedef mozilla::FrameProperties FrameProperties;
 | |
|   typedef mozilla::layers::Layer Layer;
 | |
|   typedef mozilla::layers::LayerManager LayerManager;
 | |
|   typedef mozilla::layout::FrameChildList ChildList;
 | |
|   typedef mozilla::layout::FrameChildListID ChildListID;
 | |
|   typedef mozilla::layout::FrameChildListIDs ChildListIDs;
 | |
|   typedef mozilla::layout::FrameChildListIterator ChildListIterator;
 | |
|   typedef mozilla::layout::FrameChildListArrayIterator ChildListArrayIterator;
 | |
|   typedef mozilla::gfx::DrawTarget DrawTarget;
 | |
|   typedef mozilla::gfx::Matrix Matrix;
 | |
|   typedef mozilla::gfx::Matrix4x4 Matrix4x4;
 | |
|   typedef mozilla::gfx::Matrix4x4Flagged Matrix4x4Flagged;
 | |
|   typedef mozilla::Sides Sides;
 | |
|   typedef mozilla::LogicalSides LogicalSides;
 | |
|   typedef mozilla::SmallPointerArray<mozilla::DisplayItemData> DisplayItemDataArray;
 | |
|   typedef nsQueryFrame::ClassID ClassID;
 | |
| 
 | |
|   NS_DECL_QUERYFRAME_TARGET(nsIFrame)
 | |
| 
 | |
|   explicit nsIFrame(ClassID aID)
 | |
|     : mRect()
 | |
|     , mContent(nullptr)
 | |
|     , mComputedStyle(nullptr)
 | |
|     , mParent(nullptr)
 | |
|     , mNextSibling(nullptr)
 | |
|     , mPrevSibling(nullptr)
 | |
|     , mState(NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY)
 | |
|     , mClass(aID)
 | |
|     , mMayHaveRoundedCorners(false)
 | |
|     , mHasImageRequest(false)
 | |
|     , mHasFirstLetterChild(false)
 | |
|     , mParentIsWrapperAnonBox(false)
 | |
|     , mIsWrapperBoxNeedingRestyle(false)
 | |
|     , mReflowRequestedForCharDataChange(false)
 | |
|     , mForceDescendIntoIfVisible(false)
 | |
|     , mBuiltDisplayList(false)
 | |
|     , mFrameIsModified(false)
 | |
|     , mHasOverrideDirtyRegion(false)
 | |
|     , mMayHaveWillChangeBudget(false)
 | |
|     , mIsPrimaryFrame(false)
 | |
|     , mMayHaveTransformAnimation(false)
 | |
|     , mMayHaveOpacityAnimation(false)
 | |
|     , mAllDescendantsAreInvisible(false)
 | |
|   {
 | |
|     mozilla::PodZero(&mOverflow);
 | |
|   }
 | |
| 
 | |
|   nsPresContext* PresContext() const {
 | |
|     return Style()->PresContextForFrame();
 | |
|   }
 | |
| 
 | |
|   nsIPresShell* PresShell() const {
 | |
|     return PresContext()->PresShell();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Called to initialize the frame. This is called immediately after creating
 | |
|    * the frame.
 | |
|    *
 | |
|    * If the frame is a continuing frame, then aPrevInFlow indicates the previous
 | |
|    * frame (the frame that was split).
 | |
|    *
 | |
|    * Each subclass that need a view should override this method and call
 | |
|    * CreateView() after calling its base class Init().
 | |
|    *
 | |
|    * @param   aContent the content object associated with the frame
 | |
|    * @param   aParent the parent frame
 | |
|    * @param   aPrevInFlow the prev-in-flow frame
 | |
|    */
 | |
|   virtual void Init(nsIContent*       aContent,
 | |
|                     nsContainerFrame* aParent,
 | |
|                     nsIFrame*         aPrevInFlow) = 0;
 | |
| 
 | |
|   using PostDestroyData = mozilla::layout::PostFrameDestroyData;
 | |
|   struct MOZ_RAII AutoPostDestroyData
 | |
|   {
 | |
|     explicit AutoPostDestroyData(nsPresContext* aPresContext)
 | |
|       : mPresContext(aPresContext) {}
 | |
|     ~AutoPostDestroyData() {
 | |
|       for (auto& content : mozilla::Reversed(mData.mAnonymousContent)) {
 | |
|         nsIFrame::DestroyAnonymousContent(mPresContext, content.forget());
 | |
|       }
 | |
|       for (auto& content : mozilla::Reversed(mData.mGeneratedContent)) {
 | |
|         content->UnbindFromTree();
 | |
|       }
 | |
|     }
 | |
|     nsPresContext* mPresContext;
 | |
|     PostDestroyData mData;
 | |
|   };
 | |
|   /**
 | |
|    * Destroys this frame and each of its child frames (recursively calls
 | |
|    * Destroy() for each child). If this frame is a first-continuation, this
 | |
|    * also removes the frame from the primary frame map and clears undisplayed
 | |
|    * content for its content node.
 | |
|    * If the frame is a placeholder, it also ensures the out-of-flow frame's
 | |
|    * removal and destruction.
 | |
|    */
 | |
|   void Destroy() {
 | |
|     AutoPostDestroyData data(PresContext());
 | |
|     DestroyFrom(this, data.mData);
 | |
|     // Note that |this| is deleted at this point.
 | |
|   }
 | |
| 
 | |
|   /** Flags for PeekOffsetCharacter, PeekOffsetNoAmount, PeekOffsetWord return values.
 | |
|     */
 | |
|   enum FrameSearchResult {
 | |
|     // Peek found a appropriate offset within frame.
 | |
|     FOUND = 0x00,
 | |
|     // try next frame for offset.
 | |
|     CONTINUE = 0x1,
 | |
|     // offset not found because the frame was empty of text.
 | |
|     CONTINUE_EMPTY = 0x2 | CONTINUE,
 | |
|     // offset not found because the frame didn't contain any text that could be selected.
 | |
|     CONTINUE_UNSELECTABLE = 0x4 | CONTINUE,
 | |
|   };
 | |
| 
 | |
|   /**
 | |
|    * Options for PeekOffsetCharacter().
 | |
|    */
 | |
|   struct MOZ_STACK_CLASS PeekOffsetCharacterOptions
 | |
|   {
 | |
|     // Whether to restrict result to valid cursor locations (between grapheme
 | |
|     // clusters) - if this is included, maintains "normal" behavior, otherwise,
 | |
|     // used for selection by "code unit" (instead of "character")
 | |
|     bool mRespectClusters;
 | |
|     // Whether to check user-select style value - if this is included, checks
 | |
|     // if user-select is all, then, it may return CONTINUE_UNSELECTABLE.
 | |
|     bool mIgnoreUserStyleAll;
 | |
| 
 | |
|     PeekOffsetCharacterOptions()
 | |
|       : mRespectClusters(true)
 | |
|       , mIgnoreUserStyleAll(false)
 | |
|     {
 | |
|     }
 | |
|   };
 | |
| 
 | |
| protected:
 | |
|   friend class nsBlockFrame; // for access to DestroyFrom
 | |
| 
 | |
|   /**
 | |
|    * Return true if the frame is part of a Selection.
 | |
|    * Helper method to implement the public IsSelected() API.
 | |
|    */
 | |
|   virtual bool IsFrameSelected() const;
 | |
| 
 | |
|   /**
 | |
|    * Implements Destroy(). Do not call this directly except from within a
 | |
|    * DestroyFrom() implementation.
 | |
|    *
 | |
|    * @note This will always be called, so it is not necessary to override
 | |
|    *       Destroy() in subclasses of nsFrame, just DestroyFrom().
 | |
|    *
 | |
|    * @param  aDestructRoot is the root of the subtree being destroyed
 | |
|    */
 | |
|   virtual void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) = 0;
 | |
|   friend class nsFrameList; // needed to pass aDestructRoot through to children
 | |
|   friend class nsLineBox;   // needed to pass aDestructRoot through to children
 | |
|   friend class nsContainerFrame; // needed to pass aDestructRoot through to children
 | |
|   friend class nsFrame; // need to assign mParent
 | |
|   template<class Source> friend class do_QueryFrameHelper; // to read mClass
 | |
| public:
 | |
| 
 | |
|   /**
 | |
|    * Get the content object associated with this frame. Does not add a reference.
 | |
|    */
 | |
|   nsIContent* GetContent() const { return mContent; }
 | |
| 
 | |
|   /**
 | |
|    * Get the frame that should be the parent for the frames of child elements
 | |
|    * May return nullptr during reflow
 | |
|    */
 | |
|   virtual nsContainerFrame* GetContentInsertionFrame() { return nullptr; }
 | |
| 
 | |
|   /**
 | |
|    * Move any frames on our overflow list to the end of our principal list.
 | |
|    * @return true if there were any overflow frames
 | |
|    */
 | |
|   virtual bool DrainSelfOverflowList() { return false; }
 | |
| 
 | |
|   /**
 | |
|    * Get the frame that should be scrolled if the content associated
 | |
|    * with this frame is targeted for scrolling. For frames implementing
 | |
|    * nsIScrollableFrame this will return the frame itself. For frames
 | |
|    * like nsTextControlFrame that contain a scrollframe, will return
 | |
|    * that scrollframe.
 | |
|    */
 | |
|   virtual nsIScrollableFrame* GetScrollTargetFrame() { return nullptr; }
 | |
| 
 | |
|   /**
 | |
|    * Get the offsets of the frame. most will be 0,0
 | |
|    *
 | |
|    */
 | |
|   virtual nsresult GetOffsets(int32_t &start, int32_t &end) const = 0;
 | |
| 
 | |
|   /**
 | |
|    * Reset the offsets when splitting frames during Bidi reordering
 | |
|    *
 | |
|    */
 | |
|   virtual void AdjustOffsetsForBidi(int32_t aStart, int32_t aEnd) {}
 | |
| 
 | |
|   /**
 | |
|    * Get the style associated with this frame.
 | |
|    */
 | |
|   ComputedStyle* Style() const { return mComputedStyle; }
 | |
|   void SetComputedStyle(ComputedStyle* aStyle)
 | |
|   {
 | |
|     if (aStyle != mComputedStyle) {
 | |
|       MOZ_DIAGNOSTIC_ASSERT(PresShell() == aStyle->PresContextForFrame()->PresShell());
 | |
|       RefPtr<ComputedStyle> oldComputedStyle = mComputedStyle.forget();
 | |
|       mComputedStyle = aStyle;
 | |
|       DidSetComputedStyle(oldComputedStyle);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * SetComputedStyleWithoutNotification is for changes to the style
 | |
|    * context that should suppress style change processing, in other
 | |
|    * words, those that aren't really changes.  This generally means only
 | |
|    * changes that happen during frame construction.
 | |
|    */
 | |
|   void SetComputedStyleWithoutNotification(ComputedStyle* aStyle)
 | |
|   {
 | |
|     if (aStyle != mComputedStyle) {
 | |
|       MOZ_DIAGNOSTIC_ASSERT(PresShell() == aStyle->PresContextForFrame()->PresShell());
 | |
|       mComputedStyle = aStyle;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Style post processing hook
 | |
|   // Attention: the old style is the one we're forgetting,
 | |
|   // and hence possibly completely bogus for GetStyle* purposes.
 | |
|   // Use PeekStyleData instead.
 | |
|   virtual void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) = 0;
 | |
| 
 | |
|   /**
 | |
|    * Define typesafe getter functions for each style struct by
 | |
|    * preprocessing the list of style structs.  These functions are the
 | |
|    * preferred way to get style data.  The macro creates functions like:
 | |
|    *   const nsStyleBorder* StyleBorder();
 | |
|    *   const nsStyleColor* StyleColor();
 | |
|    *
 | |
|    * Callers outside of libxul should use nsIDOMWindow::GetComputedStyle()
 | |
|    * instead of these accessors.
 | |
|    *
 | |
|    * Callers can use Style*WithOptionalParam if they're in a function that
 | |
|    * accepts an *optional* pointer the style struct.
 | |
|    */
 | |
|   #define STYLE_STRUCT(name_)                                         \
 | |
|     const nsStyle##name_ * Style##name_ () const MOZ_NONNULL_RETURN { \
 | |
|       NS_ASSERTION(mComputedStyle, "No style found!");                \
 | |
|       return mComputedStyle->Style##name_ ();                         \
 | |
|     }                                                                 \
 | |
|     const nsStyle##name_ * Style##name_##WithOptionalParam(           \
 | |
|       const nsStyle##name_ * aStyleStruct) const MOZ_NONNULL_RETURN { \
 | |
|       if (aStyleStruct) {                                             \
 | |
|         MOZ_ASSERT(aStyleStruct == Style##name_());                   \
 | |
|         return aStyleStruct;                                          \
 | |
|       }                                                               \
 | |
|       return Style##name_();                                          \
 | |
|     }
 | |
|   #include "nsStyleStructList.h"
 | |
|   #undef STYLE_STRUCT
 | |
| 
 | |
|   /** Also forward GetVisitedDependentColor to the style */
 | |
|   template<typename T, typename S>
 | |
|   nscolor GetVisitedDependentColor(T S::* aField)
 | |
|     { return mComputedStyle->GetVisitedDependentColor(aField); }
 | |
| 
 | |
|   /**
 | |
|    * These methods are to access any additional ComputedStyles that
 | |
|    * the frame may be holding.
 | |
|    *
 | |
|    * These are styles that are children of the frame's primary style and are NOT
 | |
|    * used as styles for any child frames.
 | |
|    *
 | |
|    * These contexts also MUST NOT have any child styles whatsoever. If you need
 | |
|    * to insert styles into the style tree, then you should create pseudo element
 | |
|    * frames to own them.
 | |
|    *
 | |
|    * The indicies must be consecutive and implementations MUST return null if
 | |
|    * asked for an index that is out of range.
 | |
|    */
 | |
|   virtual ComputedStyle* GetAdditionalComputedStyle(int32_t aIndex) const = 0;
 | |
| 
 | |
|   virtual void SetAdditionalComputedStyle(int32_t aIndex,
 | |
|                                           ComputedStyle* aComputedStyle) = 0;
 | |
| 
 | |
|   already_AddRefed<ComputedStyle> ComputeSelectionStyle() const;
 | |
| 
 | |
|   /**
 | |
|    * Accessor functions for geometric parent.
 | |
|    */
 | |
|   nsContainerFrame* GetParent() const { return mParent; }
 | |
| 
 | |
|   /**
 | |
|    * Gets the parent of a frame, using the parent of the placeholder for
 | |
|    * out-of-flow frames.
 | |
|    *
 | |
|    * This is effectively the primary frame (or one of the continuations) of the
 | |
|    * closest flattened tree ancestor that has a frame (flattened tree ancestors
 | |
|    * may not have frames in presence of display: contents).
 | |
|    */
 | |
|   inline nsContainerFrame* GetInFlowParent() const;
 | |
| 
 | |
|   /**
 | |
|    * Return the placeholder for this frame (which must be out-of-flow).
 | |
|    * @note this will only return non-null if |this| is the first-in-flow
 | |
|    * although we don't assert that here for legacy reasons.
 | |
|    */
 | |
|   inline nsPlaceholderFrame* GetPlaceholderFrame() const {
 | |
|     MOZ_ASSERT(HasAnyStateBits(NS_FRAME_OUT_OF_FLOW));
 | |
|     return GetProperty(PlaceholderFrameProperty());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Set this frame's parent to aParent.
 | |
|    * If the frame may have moved into or out of a scrollframe's
 | |
|    * frame subtree, StickyScrollContainer::NotifyReparentedFrameAcrossScrollFrameBoundary
 | |
|    * must also be called.
 | |
|    */
 | |
|   void SetParent(nsContainerFrame* aParent);
 | |
| 
 | |
|   /**
 | |
|    * The frame's writing-mode, used for logical layout computations.
 | |
|    * It's usually the 'writing-mode' computed value, but there are exceptions:
 | |
|    *   * inner table frames copy the value from the table frame
 | |
|    *     (@see nsTableRowGroupFrame::Init, nsTableRowFrame::Init etc)
 | |
|    *   * the root element frame propagates its value to its ancestors
 | |
|    *     (@see nsCanvasFrame::MaybePropagateRootElementWritingMode)
 | |
|    *   * a scrolled frame propagates its value to its ancestor scroll frame
 | |
|    *     (@see nsHTMLScrollFrame::ReloadChildFrames)
 | |
|    */
 | |
|   mozilla::WritingMode GetWritingMode() const { return mWritingMode; }
 | |
| 
 | |
|   /**
 | |
|    * Construct a writing mode for line layout in this frame.  This is
 | |
|    * the writing mode of this frame, except that if this frame is styled with
 | |
|    * unicode-bidi:plaintext, we reset the direction to the resolved paragraph
 | |
|    * level of the given subframe (typically the first frame on the line),
 | |
|    * because the container frame could be split by hard line breaks into
 | |
|    * multiple paragraphs with different base direction.
 | |
|    * @param aSelfWM the WM of 'this'
 | |
|    */
 | |
|   mozilla::WritingMode WritingModeForLine(mozilla::WritingMode aSelfWM,
 | |
|                                           nsIFrame* aSubFrame) const;
 | |
| 
 | |
|   /**
 | |
|    * Bounding rect of the frame.
 | |
|    *
 | |
|    * For frames that are laid out according to CSS box model rules the values
 | |
|    * are in app units, and the origin is relative to the upper-left of the
 | |
|    * geometric parent.  The size includes the content area, borders, and
 | |
|    * padding.
 | |
|    *
 | |
|    * Frames that are laid out according to SVG's coordinate space based rules
 | |
|    * (frames with the NS_FRAME_SVG_LAYOUT bit set, which *excludes*
 | |
|    * nsSVGOuterSVGFrame) are different.  Many frames of this type do not set or
 | |
|    * use mRect, in which case the frame rect is undefined.  The exceptions are:
 | |
|    *
 | |
|    *   - nsSVGInnerSVGFrame
 | |
|    *   - SVGGeometryFrame (used for <path>, <circle>, etc.)
 | |
|    *   - nsSVGImageFrame
 | |
|    *   - nsSVGForeignObjectFrame
 | |
|    *
 | |
|    * For these frames the frame rect contains the frame's element's userspace
 | |
|    * bounds including fill, stroke and markers, but converted to app units
 | |
|    * rather than being in user units (CSS px).  In the SVG code "userspace" is
 | |
|    * defined to be the coordinate system for the attributes that define an
 | |
|    * element's geometry (such as the 'cx' attribute for <circle>).  For more
 | |
|    * precise details see these frames' implementations of the ReflowSVG method
 | |
|    * where mRect is set.
 | |
|    *
 | |
|    * Note: moving or sizing the frame does not affect the view's size or
 | |
|    * position.
 | |
|    */
 | |
|   nsRect GetRect() const { return mRect; }
 | |
|   nsPoint GetPosition() const { return mRect.TopLeft(); }
 | |
|   nsSize GetSize() const { return mRect.Size(); }
 | |
|   nsRect GetRectRelativeToSelf() const {
 | |
|     return nsRect(nsPoint(0, 0), mRect.Size());
 | |
|   }
 | |
|   /**
 | |
|    * Dimensions and position in logical coordinates in the frame's writing mode
 | |
|    *  or another writing mode
 | |
|    */
 | |
|   mozilla::LogicalRect GetLogicalRect(const nsSize& aContainerSize) const {
 | |
|     return GetLogicalRect(GetWritingMode(), aContainerSize);
 | |
|   }
 | |
|   mozilla::LogicalPoint GetLogicalPosition(const nsSize& aContainerSize) const {
 | |
|     return GetLogicalPosition(GetWritingMode(), aContainerSize);
 | |
|   }
 | |
|   mozilla::LogicalSize GetLogicalSize() const {
 | |
|     return GetLogicalSize(GetWritingMode());
 | |
|   }
 | |
|   mozilla::LogicalRect GetLogicalRect(mozilla::WritingMode aWritingMode,
 | |
|                                       const nsSize& aContainerSize) const {
 | |
|     return mozilla::LogicalRect(aWritingMode, GetRect(), aContainerSize);
 | |
|   }
 | |
|   mozilla::LogicalPoint GetLogicalPosition(mozilla::WritingMode aWritingMode,
 | |
|                                            const nsSize& aContainerSize) const {
 | |
|     return GetLogicalRect(aWritingMode, aContainerSize).Origin(aWritingMode);
 | |
|   }
 | |
|   mozilla::LogicalSize GetLogicalSize(mozilla::WritingMode aWritingMode) const {
 | |
|     return mozilla::LogicalSize(aWritingMode, GetSize());
 | |
|   }
 | |
|   nscoord IStart(const nsSize& aContainerSize) const {
 | |
|     return IStart(GetWritingMode(), aContainerSize);
 | |
|   }
 | |
|   nscoord IStart(mozilla::WritingMode aWritingMode,
 | |
|                  const nsSize& aContainerSize) const {
 | |
|     return GetLogicalPosition(aWritingMode, aContainerSize).I(aWritingMode);
 | |
|   }
 | |
|   nscoord BStart(const nsSize& aContainerSize) const {
 | |
|     return BStart(GetWritingMode(), aContainerSize);
 | |
|   }
 | |
|   nscoord BStart(mozilla::WritingMode aWritingMode,
 | |
|                  const nsSize& aContainerSize) const {
 | |
|     return GetLogicalPosition(aWritingMode, aContainerSize).B(aWritingMode);
 | |
|   }
 | |
|   nscoord ISize() const { return ISize(GetWritingMode()); }
 | |
|   nscoord ISize(mozilla::WritingMode aWritingMode) const {
 | |
|     return GetLogicalSize(aWritingMode).ISize(aWritingMode);
 | |
|   }
 | |
|   nscoord BSize() const { return BSize(GetWritingMode()); }
 | |
|   nscoord BSize(mozilla::WritingMode aWritingMode) const {
 | |
|     return GetLogicalSize(aWritingMode).BSize(aWritingMode);
 | |
|   }
 | |
|   nscoord ContentBSize() const { return ContentBSize(GetWritingMode()); }
 | |
|   nscoord ContentBSize(mozilla::WritingMode aWritingMode) const {
 | |
|     auto bp = GetLogicalUsedBorderAndPadding(aWritingMode);
 | |
|     bp.ApplySkipSides(GetLogicalSkipSides());
 | |
|     return std::max(0, BSize(aWritingMode) - bp.BStartEnd(aWritingMode));
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * When we change the size of the frame's border-box rect, we may need to
 | |
|    * reset the overflow rect if it was previously stored as deltas.
 | |
|    * (If it is currently a "large" overflow and could be re-packed as deltas,
 | |
|    * we don't bother as the cost of the allocation has already been paid.)
 | |
|    * @param aRebuildDisplayItems If true, then adds this frame to the
 | |
|    * list of modified frames for display list building if the rect has changed.
 | |
|    * Only pass false if you're sure that the relevant display items will be rebuilt
 | |
|    * already (possibly by an ancestor being in the modified list), or if this is
 | |
|    * a temporary change.
 | |
|    */
 | |
|   void SetRect(const nsRect& aRect, bool aRebuildDisplayItems = true) {
 | |
|     if (aRect == mRect) {
 | |
|       return;
 | |
|     }
 | |
|     if (mOverflow.mType != NS_FRAME_OVERFLOW_LARGE &&
 | |
|         mOverflow.mType != NS_FRAME_OVERFLOW_NONE) {
 | |
|       nsOverflowAreas overflow = GetOverflowAreas();
 | |
|       mRect = aRect;
 | |
|       SetOverflowAreas(overflow);
 | |
|     } else {
 | |
|       mRect = aRect;
 | |
|     }
 | |
|     if (aRebuildDisplayItems) {
 | |
|       MarkNeedsDisplayItemRebuild();
 | |
|     }
 | |
|   }
 | |
|   /**
 | |
|    * Set this frame's rect from a logical rect in its own writing direction
 | |
|    */
 | |
|   void SetRect(const mozilla::LogicalRect& aRect,
 | |
|                const nsSize& aContainerSize) {
 | |
|     SetRect(GetWritingMode(), aRect, aContainerSize);
 | |
|   }
 | |
|   /**
 | |
|    * Set this frame's rect from a logical rect in a different writing direction
 | |
|    * (GetPhysicalRect will assert if the writing mode doesn't match)
 | |
|    */
 | |
|   void SetRect(mozilla::WritingMode aWritingMode,
 | |
|                const mozilla::LogicalRect& aRect,
 | |
|                const nsSize& aContainerSize) {
 | |
|     SetRect(aRect.GetPhysicalRect(aWritingMode, aContainerSize));
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Set this frame's size from a logical size in its own writing direction.
 | |
|    * This leaves the frame's logical position unchanged, which means its
 | |
|    * physical position may change (for right-to-left modes).
 | |
|    */
 | |
|   void SetSize(const mozilla::LogicalSize& aSize) {
 | |
|     SetSize(GetWritingMode(), aSize);
 | |
|   }
 | |
|   /*
 | |
|    * Set this frame's size from a logical size in a different writing direction.
 | |
|    * This leaves the frame's logical position in the given mode unchanged,
 | |
|    * which means its physical position may change (for right-to-left modes).
 | |
|    */
 | |
|   void SetSize(mozilla::WritingMode aWritingMode,
 | |
|                const mozilla::LogicalSize& aSize)
 | |
|   {
 | |
|     if ((!aWritingMode.IsVertical() && !aWritingMode.IsBidiLTR()) ||
 | |
|         aWritingMode.IsVerticalRL()) {
 | |
|       nscoord oldWidth = mRect.Width();
 | |
|       SetSize(aSize.GetPhysicalSize(aWritingMode));
 | |
|       mRect.x -= mRect.Width() - oldWidth;
 | |
|     } else {
 | |
|       SetSize(aSize.GetPhysicalSize(aWritingMode));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Set this frame's physical size. This leaves the frame's physical position
 | |
|    * (topLeft) unchanged.
 | |
|    * @param aRebuildDisplayItems If true, then adds this frame to the
 | |
|    * list of modified frames for display list building if the size has changed.
 | |
|    * Only pass false if you're sure that the relevant display items will be rebuilt
 | |
|    * already (possibly by an ancestor being in the modified list), or if this is
 | |
|    * a temporary change.
 | |
|    */
 | |
|   void SetSize(const nsSize& aSize, bool aRebuildDisplayItems = true) {
 | |
|     SetRect(nsRect(mRect.TopLeft(), aSize), aRebuildDisplayItems);
 | |
|   }
 | |
| 
 | |
|   void SetPosition(const nsPoint& aPt) {
 | |
|     if (mRect.TopLeft() == aPt) {
 | |
|       return;
 | |
|     }
 | |
|     mRect.MoveTo(aPt);
 | |
|     MarkNeedsDisplayItemRebuild();
 | |
|   }
 | |
|   void SetPosition(mozilla::WritingMode aWritingMode,
 | |
|                    const mozilla::LogicalPoint& aPt,
 | |
|                    const nsSize& aContainerSize) {
 | |
|     // We subtract mRect.Size() from the container size to account for
 | |
|     // the fact that logical origins in RTL coordinate systems are at
 | |
|     // the top right of the frame instead of the top left.
 | |
|     SetPosition(aPt.GetPhysicalPoint(aWritingMode,
 | |
|                                     aContainerSize - mRect.Size()));
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Move the frame, accounting for relative positioning. Use this when
 | |
|    * adjusting the frame's position by a known amount, to properly update its
 | |
|    * saved normal position (see GetNormalPosition below).
 | |
|    *
 | |
|    * This must be used only when moving a frame *after*
 | |
|    * ReflowInput::ApplyRelativePositioning is called.  When moving
 | |
|    * a frame during the reflow process prior to calling
 | |
|    * ReflowInput::ApplyRelativePositioning, the position should
 | |
|    * simply be adjusted directly (e.g., using SetPosition()).
 | |
|    */
 | |
|   void MovePositionBy(const nsPoint& aTranslation);
 | |
| 
 | |
|   /**
 | |
|    * As above, using a logical-point delta in a given writing mode.
 | |
|    */
 | |
|   void MovePositionBy(mozilla::WritingMode aWritingMode,
 | |
|                       const mozilla::LogicalPoint& aTranslation)
 | |
|   {
 | |
|     // The LogicalPoint represents a vector rather than a point within a
 | |
|     // rectangular coordinate space, so we use a null containerSize when
 | |
|     // converting logical to physical.
 | |
|     const nsSize nullContainerSize;
 | |
|     MovePositionBy(aTranslation.GetPhysicalPoint(aWritingMode,
 | |
|                                                  nullContainerSize));
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return frame's rect without relative positioning
 | |
|    */
 | |
|   nsRect GetNormalRect() const;
 | |
| 
 | |
|   /**
 | |
|    * Return frame's position without relative positioning.
 | |
|    * If aHasProperty is provided, returns whether the normal position
 | |
|    * was stored in a frame property.
 | |
|    */
 | |
|   inline nsPoint GetNormalPosition(bool* aHasProperty = nullptr) const;
 | |
| 
 | |
|   mozilla::LogicalPoint
 | |
|   GetLogicalNormalPosition(mozilla::WritingMode aWritingMode,
 | |
|                            const nsSize& aContainerSize) const
 | |
|   {
 | |
|     // Subtract the size of this frame from the container size to get
 | |
|     // the correct position in rtl frames where the origin is on the
 | |
|     // right instead of the left
 | |
|     return mozilla::LogicalPoint(aWritingMode,
 | |
|                                  GetNormalPosition(),
 | |
|                                  aContainerSize - mRect.Size());
 | |
|   }
 | |
| 
 | |
|   virtual nsPoint GetPositionOfChildIgnoringScrolling(const nsIFrame* aChild)
 | |
|   { return aChild->GetPosition(); }
 | |
| 
 | |
|   nsPoint GetPositionIgnoringScrolling() const;
 | |
| 
 | |
|   typedef AutoTArray<nsDisplayItem*, 4> DisplayItemArray;
 | |
| 
 | |
| #define NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, dtor)             \
 | |
|   static const mozilla::FramePropertyDescriptor<type>* prop() {           \
 | |
|     /* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */    \
 | |
|     static const auto descriptor =                                        \
 | |
|       mozilla::FramePropertyDescriptor<type>::NewWithDestructor<dtor>();  \
 | |
|     return &descriptor;                                                   \
 | |
|   }
 | |
| 
 | |
| // Don't use this unless you really know what you're doing!
 | |
| #define NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(prop, type, dtor)    \
 | |
|   static const mozilla::FramePropertyDescriptor<type>* prop() {           \
 | |
|     /* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */    \
 | |
|     static const auto descriptor = mozilla::                              \
 | |
|       FramePropertyDescriptor<type>::NewWithDestructorWithFrame<dtor>();  \
 | |
|     return &descriptor;                                                   \
 | |
|   }
 | |
| 
 | |
| #define NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(prop, type)                \
 | |
|   static const mozilla::FramePropertyDescriptor<type>* prop() {           \
 | |
|     /* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */    \
 | |
|     static const auto descriptor =                                        \
 | |
|       mozilla::FramePropertyDescriptor<type>::NewWithoutDestructor();     \
 | |
|     return &descriptor;                                                   \
 | |
|   }
 | |
| 
 | |
| #define NS_DECLARE_FRAME_PROPERTY_DELETABLE(prop, type) \
 | |
|   NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, DeleteValue)
 | |
| 
 | |
| #define NS_DECLARE_FRAME_PROPERTY_RELEASABLE(prop, type) \
 | |
|   NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, ReleaseValue)
 | |
| 
 | |
| #define NS_DECLARE_FRAME_PROPERTY_WITH_DTOR_NEVER_CALLED(prop, type)  \
 | |
|   static void AssertOnDestroyingProperty##prop(type*) {               \
 | |
|     MOZ_ASSERT_UNREACHABLE("Frame property " #prop " should never "   \
 | |
|                            "be destroyed by the FrameProperties class");  \
 | |
|   }                                                                   \
 | |
|   NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type,                     \
 | |
|                                       AssertOnDestroyingProperty##prop)
 | |
| 
 | |
| #define NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(prop, type) \
 | |
|   NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(prop, mozilla::SmallValueHolder<type>)
 | |
| 
 | |
|   NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(IBSplitSibling, nsContainerFrame)
 | |
|   NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(IBSplitPrevSibling, nsContainerFrame)
 | |
| 
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(NormalPositionProperty, nsPoint)
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(ComputedOffsetProperty, nsMargin)
 | |
| 
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(OutlineInnerRectProperty, nsRect)
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(PreEffectsBBoxProperty, nsRect)
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(PreTransformOverflowAreasProperty,
 | |
|                                       nsOverflowAreas)
 | |
| 
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(OverflowAreasProperty, nsOverflowAreas)
 | |
| 
 | |
|   // The initial overflow area passed to FinishAndStoreOverflow. This is only set
 | |
|   // on frames that Preserve3D() or HasPerspective() or IsTransformed(), and
 | |
|   // when at least one of the overflow areas differs from the frame bound rect.
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(InitialOverflowProperty, nsOverflowAreas)
 | |
| 
 | |
| #ifdef DEBUG
 | |
|   // InitialOverflowPropertyDebug is added to the frame to indicate that either
 | |
|   // the InitialOverflowProperty has been stored or the InitialOverflowProperty
 | |
|   // has been suppressed due to being set to the default value (frame bounds)
 | |
|   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(DebugInitialOverflowPropertyApplied, bool)
 | |
| #endif
 | |
| 
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedMarginProperty, nsMargin)
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedPaddingProperty, nsMargin)
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(UsedBorderProperty, nsMargin)
 | |
| 
 | |
|   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(LineBaselineOffset, nscoord)
 | |
| 
 | |
|   // Temporary override for a flex item's main-size property (either width
 | |
|   // or height), imposed by its flex container.
 | |
|   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(FlexItemMainSizeOverride, nscoord)
 | |
| 
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(InvalidationRect, nsRect)
 | |
| 
 | |
|   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(RefusedAsyncAnimationProperty, bool)
 | |
| 
 | |
|   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(FragStretchBSizeProperty, nscoord)
 | |
| 
 | |
|   // The block-axis margin-box size associated with eBClampMarginBoxMinSize.
 | |
|   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BClampMarginBoxMinSizeProperty, nscoord)
 | |
| 
 | |
|   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(IBaselinePadProperty, nscoord)
 | |
|   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BBaselinePadProperty, nscoord)
 | |
| 
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(ModifiedFrameList, nsTArray<nsIFrame*>)
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(OverriddenDirtyRectFrameList, nsTArray<nsIFrame*>)
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayItems, DisplayItemArray)
 | |
| 
 | |
|   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BidiDataProperty, mozilla::FrameBidiData)
 | |
| 
 | |
|   NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(PlaceholderFrameProperty, nsPlaceholderFrame)
 | |
| 
 | |
|   mozilla::FrameBidiData GetBidiData() const
 | |
|   {
 | |
|     bool exists;
 | |
|     mozilla::FrameBidiData bidiData = GetProperty(BidiDataProperty(), &exists);
 | |
|     if (!exists) {
 | |
|       bidiData.precedingControl = mozilla::kBidiLevelNone;
 | |
|     }
 | |
|     return bidiData;
 | |
|   }
 | |
| 
 | |
|   nsBidiLevel GetBaseLevel() const
 | |
|   {
 | |
|     return GetBidiData().baseLevel;
 | |
|   }
 | |
| 
 | |
|   nsBidiLevel GetEmbeddingLevel() const
 | |
|   {
 | |
|     return GetBidiData().embeddingLevel;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return the distance between the border edge of the frame and the
 | |
|    * margin edge of the frame.  Like GetRect(), returns the dimensions
 | |
|    * as of the most recent reflow.
 | |
|    *
 | |
|    * This doesn't include any margin collapsing that may have occurred.
 | |
|    *
 | |
|    * It also treats 'auto' margins as zero, and treats any margins that
 | |
|    * should have been turned into 'auto' because of overconstraint as
 | |
|    * having their original values.
 | |
|    */
 | |
|   virtual nsMargin GetUsedMargin() const;
 | |
|   virtual mozilla::LogicalMargin
 | |
|   GetLogicalUsedMargin(mozilla::WritingMode aWritingMode) const {
 | |
|     return mozilla::LogicalMargin(aWritingMode, GetUsedMargin());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return the distance between the border edge of the frame (which is
 | |
|    * its rect) and the padding edge of the frame. Like GetRect(), returns
 | |
|    * the dimensions as of the most recent reflow.
 | |
|    *
 | |
|    * Note that this differs from StyleBorder()->GetComputedBorder() in
 | |
|    * that this describes a region of the frame's box, and
 | |
|    * StyleBorder()->GetComputedBorder() describes a border.  They differ
 | |
|    * for tables (particularly border-collapse tables) and themed
 | |
|    * elements.
 | |
|    */
 | |
|   virtual nsMargin GetUsedBorder() const;
 | |
|   virtual mozilla::LogicalMargin
 | |
|   GetLogicalUsedBorder(mozilla::WritingMode aWritingMode) const {
 | |
|     return mozilla::LogicalMargin(aWritingMode, GetUsedBorder());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return the distance between the padding edge of the frame and the
 | |
|    * content edge of the frame.  Like GetRect(), returns the dimensions
 | |
|    * as of the most recent reflow.
 | |
|    */
 | |
|   virtual nsMargin GetUsedPadding() const;
 | |
|   virtual mozilla::LogicalMargin
 | |
|   GetLogicalUsedPadding(mozilla::WritingMode aWritingMode) const {
 | |
|     return mozilla::LogicalMargin(aWritingMode, GetUsedPadding());
 | |
|   }
 | |
| 
 | |
|   nsMargin GetUsedBorderAndPadding() const {
 | |
|     return GetUsedBorder() + GetUsedPadding();
 | |
|   }
 | |
|   mozilla::LogicalMargin
 | |
|   GetLogicalUsedBorderAndPadding(mozilla::WritingMode aWritingMode) const {
 | |
|     return mozilla::LogicalMargin(aWritingMode, GetUsedBorderAndPadding());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Like the frame's rect (see |GetRect|), which is the border rect,
 | |
|    * other rectangles of the frame, in app units, relative to the parent.
 | |
|    */
 | |
|   nsRect GetPaddingRect() const;
 | |
|   nsRect GetPaddingRectRelativeToSelf() const;
 | |
|   nsRect GetContentRect() const;
 | |
|   nsRect GetContentRectRelativeToSelf() const;
 | |
|   nsRect GetMarginRectRelativeToSelf() const;
 | |
| 
 | |
|   /**
 | |
|    * The area to paint box-shadows around.  The default is the border rect.
 | |
|    * (nsFieldSetFrame overrides this).
 | |
|    */
 | |
|   virtual nsRect VisualBorderRectRelativeToSelf() const {
 | |
|     return nsRect(0, 0, mRect.Width(), mRect.Height());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Get the size, in app units, of the border radii. It returns FALSE iff all
 | |
|    * returned radii == 0 (so no border radii), TRUE otherwise.
 | |
|    * For the aRadii indexes, use the enum HalfCorner constants in gfx/2d/Types.h
 | |
|    * If a side is skipped via aSkipSides, its corners are forced to 0.
 | |
|    *
 | |
|    * All corner radii are then adjusted so they do not require more
 | |
|    * space than aBorderArea, according to the algorithm in css3-background.
 | |
|    *
 | |
|    * aFrameSize is used as the basis for percentage widths and heights.
 | |
|    * aBorderArea is used for the adjustment of radii that might be too
 | |
|    * large.
 | |
|    * FIXME: In the long run, we can probably get away with only one of
 | |
|    * these, especially if we change the way we handle outline-radius (by
 | |
|    * removing it and inflating the border radius)
 | |
|    *
 | |
|    * Return whether any radii are nonzero.
 | |
|    */
 | |
|   static bool ComputeBorderRadii(const nsStyleCorners& aBorderRadius,
 | |
|                                  const nsSize& aFrameSize,
 | |
|                                  const nsSize& aBorderArea,
 | |
|                                  Sides aSkipSides,
 | |
|                                  nscoord aRadii[8]);
 | |
| 
 | |
|   /*
 | |
|    * Given a set of border radii for one box (e.g., border box), convert
 | |
|    * it to the equivalent set of radii for another box (e.g., in to
 | |
|    * padding box, out to outline box) by reducing radii or increasing
 | |
|    * nonzero radii as appropriate.
 | |
|    *
 | |
|    * Indices into aRadii are the enum HalfCorner constants in gfx/2d/Types.h
 | |
|    *
 | |
|    * Note that InsetBorderRadii is lossy, since it can turn nonzero
 | |
|    * radii into zero, and OutsetBorderRadii does not inflate zero radii.
 | |
|    * Therefore, callers should always inset or outset directly from the
 | |
|    * original value coming from style.
 | |
|    */
 | |
|   static void InsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets);
 | |
|   static void OutsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets);
 | |
| 
 | |
|   /**
 | |
|    * Fill in border radii for this frame.  Return whether any are nonzero.
 | |
|    * Indices into aRadii are the enum HalfCorner constants in gfx/2d/Types.h
 | |
|    * aSkipSides is a union of eSideBitsLeft/Right/Top/Bottom bits that says
 | |
|    * which side(s) to skip.
 | |
|    *
 | |
|    * Note: GetMarginBoxBorderRadii() and GetShapeBoxBorderRadii() work only
 | |
|    * on frames that establish block formatting contexts since they don't
 | |
|    * participate in margin-collapsing.
 | |
|    */
 | |
|   virtual bool GetBorderRadii(const nsSize& aFrameSize,
 | |
|                               const nsSize& aBorderArea,
 | |
|                               Sides aSkipSides,
 | |
|                               nscoord aRadii[8]) const;
 | |
|   bool GetBorderRadii(nscoord aRadii[8]) const;
 | |
|   bool GetMarginBoxBorderRadii(nscoord aRadii[8]) const;
 | |
|   bool GetPaddingBoxBorderRadii(nscoord aRadii[8]) const;
 | |
|   bool GetContentBoxBorderRadii(nscoord aRadii[8]) const;
 | |
|   bool GetBoxBorderRadii(nscoord aRadii[8], nsMargin aOffset, bool aIsOutset) const;
 | |
|   bool GetShapeBoxBorderRadii(nscoord aRadii[8]) const;
 | |
| 
 | |
|   /**
 | |
|    * XXX: this method will likely be replaced by GetVerticalAlignBaseline
 | |
|    * Get the position of the frame's baseline, relative to the top of
 | |
|    * the frame (its top border edge).  Only valid when Reflow is not
 | |
|    * needed.
 | |
|    * @note You should only call this on frames with a WM that's parallel to aWM.
 | |
|    * @param aWM the writing-mode of the alignment context, with the ltr/rtl
 | |
|    * direction tweak done by nsIFrame::GetWritingMode(nsIFrame*) in inline
 | |
|    * contexts (see that method).
 | |
|    */
 | |
|   virtual nscoord GetLogicalBaseline(mozilla::WritingMode aWM) const = 0;
 | |
| 
 | |
|   /**
 | |
|    * Synthesize a first(last) inline-axis baseline from our margin-box.
 | |
|    * An alphabetical baseline is at the start(end) edge and a central baseline
 | |
|    * is at the center of our block-axis margin-box (aWM tells which to use).
 | |
|    * https://drafts.csswg.org/css-align-3/#synthesize-baselines
 | |
|    * @note You should only call this on frames with a WM that's parallel to aWM.
 | |
|    * @param aWM the writing-mode of the alignment context
 | |
|    * @return an offset from our border-box block-axis start(end) edge for
 | |
|    * a first(last) baseline respectively
 | |
|    * (implemented in nsIFrameInlines.h)
 | |
|    */
 | |
|   inline nscoord SynthesizeBaselineBOffsetFromMarginBox(
 | |
|                    mozilla::WritingMode aWM,
 | |
|                    BaselineSharingGroup aGroup) const;
 | |
| 
 | |
|   /**
 | |
|    * Synthesize a first(last) inline-axis baseline from our border-box.
 | |
|    * An alphabetical baseline is at the start(end) edge and a central baseline
 | |
|    * is at the center of our block-axis border-box (aWM tells which to use).
 | |
|    * https://drafts.csswg.org/css-align-3/#synthesize-baselines
 | |
|    * @note The returned value is only valid when reflow is not needed.
 | |
|    * @note You should only call this on frames with a WM that's parallel to aWM.
 | |
|    * @param aWM the writing-mode of the alignment context
 | |
|    * @return an offset from our border-box block-axis start(end) edge for
 | |
|    * a first(last) baseline respectively
 | |
|    * (implemented in nsIFrameInlines.h)
 | |
|    */
 | |
|   inline nscoord SynthesizeBaselineBOffsetFromBorderBox(
 | |
|                    mozilla::WritingMode aWM,
 | |
|                    BaselineSharingGroup aGroup) const;
 | |
| 
 | |
|   /**
 | |
|    * Return the position of the frame's inline-axis baseline, or synthesize one
 | |
|    * for the given alignment context. The returned baseline is the distance from
 | |
|    * the block-axis border-box start(end) edge for aBaselineGroup eFirst(eLast).
 | |
|    * @note The returned value is only valid when reflow is not needed.
 | |
|    * @note You should only call this on frames with a WM that's parallel to aWM.
 | |
|    * @param aWM the writing-mode of the alignment context
 | |
|    * @param aBaselineOffset out-param, only valid if the method returns true
 | |
|    * (implemented in nsIFrameInlines.h)
 | |
|    */
 | |
|   inline nscoord BaselineBOffset(mozilla::WritingMode aWM,
 | |
|                                  BaselineSharingGroup aBaselineGroup,
 | |
|                                  AlignmentContext     aAlignmentContext) const;
 | |
| 
 | |
|   /**
 | |
|    * XXX: this method is taking over the role that GetLogicalBaseline has.
 | |
|    * Return true if the frame has a CSS2 'vertical-align' baseline.
 | |
|    * If it has, then the returned baseline is the distance from the block-
 | |
|    * axis border-box start edge.
 | |
|    * @note This method should only be used in AlignmentContext::eInline contexts.
 | |
|    * @note The returned value is only valid when reflow is not needed.
 | |
|    * @note You should only call this on frames with a WM that's parallel to aWM.
 | |
|    * @param aWM the writing-mode of the alignment context
 | |
|    * @param aBaseline the baseline offset, only valid if the method returns true
 | |
|    */
 | |
|   virtual bool GetVerticalAlignBaseline(mozilla::WritingMode aWM,
 | |
|                                         nscoord* aBaseline) const {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return true if the frame has a first(last) inline-axis natural baseline per
 | |
|    * CSS Box Alignment.  If so, then the returned baseline is the distance from
 | |
|    * the block-axis border-box start(end) edge for aBaselineGroup eFirst(eLast).
 | |
|    * https://drafts.csswg.org/css-align-3/#natural-baseline
 | |
|    * @note The returned value is only valid when reflow is not needed.
 | |
|    * @note You should only call this on frames with a WM that's parallel to aWM.
 | |
|    * @param aWM the writing-mode of the alignment context
 | |
|    * @param aBaseline the baseline offset, only valid if the method returns true
 | |
|    */
 | |
|   virtual bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM,
 | |
|                                          BaselineSharingGroup aBaselineGroup,
 | |
|                                          nscoord*             aBaseline) const {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Get the position of the baseline on which the caret needs to be placed,
 | |
|    * relative to the top of the frame.  This is mostly needed for frames
 | |
|    * which return a baseline from GetBaseline which is not useful for
 | |
|    * caret positioning.
 | |
|    */
 | |
|   virtual nscoord GetCaretBaseline() const {
 | |
|     return GetLogicalBaseline(GetWritingMode());
 | |
|   }
 | |
| 
 | |
|   ///////////////////////////////////////////////////////////////////////////////
 | |
|   // The public visibility API.
 | |
|   ///////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
|   /// @return true if we're tracking visibility for this frame.
 | |
|   bool TrackingVisibility() const
 | |
|   {
 | |
|     return bool(GetStateBits() & NS_FRAME_VISIBILITY_IS_TRACKED);
 | |
|   }
 | |
| 
 | |
|   /// @return the visibility state of this frame. See the Visibility enum
 | |
|   /// for the possible return values and their meanings.
 | |
|   Visibility GetVisibility() const;
 | |
| 
 | |
|   /// Update the visibility state of this frame synchronously.
 | |
|   /// XXX(seth): Avoid using this method; we should be relying on the refresh
 | |
|   /// driver for visibility updates. This method, which replaces
 | |
|   /// nsLayoutUtils::UpdateApproximateFrameVisibility(), exists purely as a
 | |
|   /// temporary measure to avoid changing behavior during the transition from
 | |
|   /// the old image visibility code.
 | |
|   void UpdateVisibilitySynchronously();
 | |
| 
 | |
|   // A frame property which stores the visibility state of this frame. Right
 | |
|   // now that consists of an approximate visibility counter represented as a
 | |
|   // uint32_t. When the visibility of this frame is not being tracked, this
 | |
|   // property is absent.
 | |
|   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(VisibilityStateProperty, uint32_t);
 | |
| 
 | |
| protected:
 | |
| 
 | |
|   /**
 | |
|    * Subclasses can call this method to enable visibility tracking for this frame.
 | |
|    *
 | |
|    * If visibility tracking was previously disabled, this will schedule an
 | |
|    * update an asynchronous update of visibility.
 | |
|    */
 | |
|   void EnableVisibilityTracking();
 | |
| 
 | |
|   /**
 | |
|    * Subclasses can call this method to disable visibility tracking for this frame.
 | |
|    *
 | |
|    * Note that if visibility tracking was previously enabled, disabling visibility
 | |
|    * tracking will cause a synchronous call to OnVisibilityChange().
 | |
|    */
 | |
|   void DisableVisibilityTracking();
 | |
| 
 | |
|   /**
 | |
|    * Called when a frame transitions between visibility states (for example,
 | |
|    * from nonvisible to visible, or from visible to nonvisible).
 | |
|    *
 | |
|    * @param aNewVisibility    The new visibility state.
 | |
|    * @param aNonvisibleAction A requested action if the frame has become
 | |
|    *                          nonvisible. If Nothing(), no action is
 | |
|    *                          requested. If DISCARD_IMAGES is specified, the
 | |
|    *                          frame is requested to ask any images it's
 | |
|    *                          associated with to discard their surfaces if
 | |
|    *                          possible.
 | |
|    *
 | |
|    * Subclasses which override this method should call their parent class's
 | |
|    * implementation.
 | |
|    */
 | |
|   virtual void OnVisibilityChange(Visibility aNewVisibility,
 | |
|                                   const Maybe<OnNonvisible>& aNonvisibleAction = Nothing());
 | |
| 
 | |
| public:
 | |
| 
 | |
|   ///////////////////////////////////////////////////////////////////////////////
 | |
|   // Internal implementation for the approximate frame visibility API.
 | |
|   ///////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
|   /**
 | |
|    * We track the approximate visibility of frames using a counter; if it's
 | |
|    * non-zero, then the frame is considered visible. Using a counter allows us
 | |
|    * to account for situations where the frame may be visible in more than one
 | |
|    * place (for example, via -moz-element), and it simplifies the
 | |
|    * implementation of our approximate visibility tracking algorithms.
 | |
|    *
 | |
|    * @param aNonvisibleAction A requested action if the frame has become
 | |
|    *                          nonvisible. If Nothing(), no action is
 | |
|    *                          requested. If DISCARD_IMAGES is specified, the
 | |
|    *                          frame is requested to ask any images it's
 | |
|    *                          associated with to discard their surfaces if
 | |
|    *                          possible.
 | |
|    */
 | |
|   void DecApproximateVisibleCount(const Maybe<OnNonvisible>& aNonvisibleAction = Nothing());
 | |
|   void IncApproximateVisibleCount();
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    * Get the specified child list.
 | |
|    *
 | |
|    * @param   aListID identifies the requested child list.
 | |
|    * @return  the child list.  If the requested list is unsupported by this
 | |
|    *          frame type, an empty list will be returned.
 | |
|    */
 | |
|   virtual const nsFrameList& GetChildList(ChildListID aListID) const = 0;
 | |
|   const nsFrameList& PrincipalChildList() const { return GetChildList(kPrincipalList); }
 | |
|   virtual void GetChildLists(nsTArray<ChildList>* aLists) const = 0;
 | |
| 
 | |
|   /**
 | |
|    * Gets the child lists for this frame, including
 | |
|    * ones belong to a child document.
 | |
|    */
 | |
|   void GetCrossDocChildLists(nsTArray<ChildList>* aLists);
 | |
| 
 | |
|   // The individual concrete child lists.
 | |
|   static const ChildListID kPrincipalList = mozilla::layout::kPrincipalList;
 | |
|   static const ChildListID kAbsoluteList = mozilla::layout::kAbsoluteList;
 | |
|   static const ChildListID kBulletList = mozilla::layout::kBulletList;
 | |
|   static const ChildListID kCaptionList = mozilla::layout::kCaptionList;
 | |
|   static const ChildListID kColGroupList = mozilla::layout::kColGroupList;
 | |
|   static const ChildListID kExcessOverflowContainersList = mozilla::layout::kExcessOverflowContainersList;
 | |
|   static const ChildListID kFixedList = mozilla::layout::kFixedList;
 | |
|   static const ChildListID kFloatList = mozilla::layout::kFloatList;
 | |
|   static const ChildListID kOverflowContainersList = mozilla::layout::kOverflowContainersList;
 | |
|   static const ChildListID kOverflowList = mozilla::layout::kOverflowList;
 | |
|   static const ChildListID kOverflowOutOfFlowList = mozilla::layout::kOverflowOutOfFlowList;
 | |
|   static const ChildListID kPopupList = mozilla::layout::kPopupList;
 | |
|   static const ChildListID kPushedFloatsList = mozilla::layout::kPushedFloatsList;
 | |
|   static const ChildListID kSelectPopupList = mozilla::layout::kSelectPopupList;
 | |
|   static const ChildListID kBackdropList = mozilla::layout::kBackdropList;
 | |
|   // A special alias for kPrincipalList that do not request reflow.
 | |
|   static const ChildListID kNoReflowPrincipalList = mozilla::layout::kNoReflowPrincipalList;
 | |
| 
 | |
|   /**
 | |
|    * Child frames are linked together in a doubly-linked list
 | |
|    */
 | |
|   nsIFrame* GetNextSibling() const { return mNextSibling; }
 | |
|   void SetNextSibling(nsIFrame* aNextSibling) {
 | |
|     NS_ASSERTION(this != aNextSibling, "Creating a circular frame list, this is very bad.");
 | |
|     if (mNextSibling && mNextSibling->GetPrevSibling() == this) {
 | |
|       mNextSibling->mPrevSibling = nullptr;
 | |
|     }
 | |
|     mNextSibling = aNextSibling;
 | |
|     if (mNextSibling) {
 | |
|       mNextSibling->mPrevSibling = this;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   nsIFrame* GetPrevSibling() const { return mPrevSibling; }
 | |
| 
 | |
|   /**
 | |
|    * Builds the display lists for the content represented by this frame
 | |
|    * and its descendants. The background+borders of this element must
 | |
|    * be added first, before any other content.
 | |
|    *
 | |
|    * This should only be called by methods in nsFrame. Instead of calling this
 | |
|    * directly, call either BuildDisplayListForStackingContext or
 | |
|    * BuildDisplayListForChild.
 | |
|    *
 | |
|    * See nsDisplayList.h for more information about display lists.
 | |
|    */
 | |
|   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
 | |
|                                 const nsDisplayListSet& aLists) {}
 | |
|   /**
 | |
|    * Displays the caret onto the given display list builder. The caret is
 | |
|    * painted on top of the rest of the display list items.
 | |
|    */
 | |
|   void DisplayCaret(nsDisplayListBuilder* aBuilder,
 | |
|                     nsDisplayList*        aList);
 | |
| 
 | |
|   /**
 | |
|    * Get the preferred caret color at the offset.
 | |
|    *
 | |
|    * @param aOffset is offset of the content.
 | |
|    */
 | |
|   virtual nscolor GetCaretColorAt(int32_t aOffset);
 | |
| 
 | |
| 
 | |
|   bool IsThemed(nsITheme::Transparency* aTransparencyState = nullptr) const {
 | |
|     return IsThemed(StyleDisplay(), aTransparencyState);
 | |
|   }
 | |
|   bool IsThemed(const nsStyleDisplay* aDisp,
 | |
|                   nsITheme::Transparency* aTransparencyState = nullptr) const {
 | |
|     nsIFrame* mutable_this = const_cast<nsIFrame*>(this);
 | |
|     if (!aDisp->mAppearance)
 | |
|       return false;
 | |
|     nsPresContext* pc = PresContext();
 | |
|     nsITheme *theme = pc->GetTheme();
 | |
|     if(!theme ||
 | |
|        !theme->ThemeSupportsWidget(pc, mutable_this, aDisp->mAppearance))
 | |
|       return false;
 | |
|     if (aTransparencyState) {
 | |
|       *aTransparencyState =
 | |
|         theme->GetWidgetTransparency(mutable_this, aDisp->mAppearance);
 | |
|     }
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Builds a display list for the content represented by this frame,
 | |
|    * treating this frame as the root of a stacking context.
 | |
|    * Optionally sets aCreatedContainerItem to true if we created a
 | |
|    * single container display item for the stacking context, and no
 | |
|    * other wrapping items are needed.
 | |
|    */
 | |
|   void BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
 | |
|                                           nsDisplayList*        aList,
 | |
|                                           bool*                 aCreatedContainerItem = nullptr);
 | |
| 
 | |
|   enum {
 | |
|     DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT = 0x01,
 | |
|     DISPLAY_CHILD_FORCE_STACKING_CONTEXT = 0x02,
 | |
|     DISPLAY_CHILD_INLINE = 0x04
 | |
|   };
 | |
|   /**
 | |
|    * Adjusts aDirtyRect for the child's offset, checks that the dirty rect
 | |
|    * actually intersects the child (or its descendants), calls BuildDisplayList
 | |
|    * on the child if necessary, and puts things in the right lists if the child
 | |
|    * is positioned.
 | |
|    *
 | |
|    * @param aFlags combination of DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT,
 | |
|    *    DISPLAY_CHILD_FORCE_STACKING_CONTEXT and DISPLAY_CHILD_INLINE
 | |
|    */
 | |
|   void BuildDisplayListForChild(nsDisplayListBuilder*   aBuilder,
 | |
|                                 nsIFrame*               aChild,
 | |
|                                 const nsDisplayListSet& aLists,
 | |
|                                 uint32_t                aFlags = 0);
 | |
| 
 | |
|   bool RefusedAsyncAnimation() const
 | |
|   {
 | |
|     return GetProperty(RefusedAsyncAnimationProperty());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns true if this frame is transformed (e.g. has CSS or SVG transforms)
 | |
|    * or if its parent is an SVG frame that has children-only transforms (e.g.
 | |
|    * an SVG viewBox attribute) or if its transform-style is preserve-3d or
 | |
|    * the frame has transform animations.
 | |
|    *
 | |
|    * @param aStyleDisplay:  If the caller has this->StyleDisplay(), providing
 | |
|    *   it here will improve performance.
 | |
|    */
 | |
|   bool IsTransformed(const nsStyleDisplay* aStyleDisplay) const;
 | |
|   bool IsTransformed() const {
 | |
|     return IsTransformed(StyleDisplay());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Same as IsTransformed, except that it doesn't take SVG transforms
 | |
|    * into account.
 | |
|    */
 | |
|   bool IsCSSTransformed(const nsStyleDisplay* aStyleDisplay) const;
 | |
| 
 | |
|   /**
 | |
|    * True if this frame has any animation of transform in effect.
 | |
|    *
 | |
|    */
 | |
|   bool HasAnimationOfTransform() const;
 | |
| 
 | |
|   /**
 | |
|    * Returns true if the frame is translucent or the frame has opacity
 | |
|    * animations for the purposes of creating a stacking context.
 | |
|    *
 | |
|    * @param aEffectSet: This function may need to look up EffectSet property.
 | |
|    *   If a caller already have one, pass it in can save property look up
 | |
|    *   time; otherwise, just left it as nullptr.
 | |
|    */
 | |
|   bool HasOpacity(mozilla::EffectSet* aEffectSet = nullptr) const
 | |
|   {
 | |
|     return HasOpacityInternal(1.0f, aEffectSet);
 | |
|   }
 | |
|   /**
 | |
|    * Returns true if the frame is translucent for display purposes.
 | |
|    *
 | |
|    * @param aEffectSet: This function may need to look up EffectSet property.
 | |
|    *   If a caller already have one, pass it in can save property look up
 | |
|    *   time; otherwise, just left it as nullptr.
 | |
|    */
 | |
|   bool HasVisualOpacity(mozilla::EffectSet* aEffectSet = nullptr) const
 | |
|   {
 | |
|     // Treat an opacity value of 0.99 and above as opaque.  This is an
 | |
|     // optimization aimed at Web content which use opacity:0.99 as a hint for
 | |
|     // creating a stacking context only.
 | |
|     return HasOpacityInternal(0.99f, aEffectSet);
 | |
|   }
 | |
| 
 | |
|    /**
 | |
|    * Return true if this frame might be using a transform getter.
 | |
|    */
 | |
|   virtual bool HasTransformGetter() const { return false; }
 | |
| 
 | |
|   /**
 | |
|    * Returns true if this frame is an SVG frame that has SVG transforms applied
 | |
|    * to it, or if its parent frame is an SVG frame that has children-only
 | |
|    * transforms (e.g. an SVG viewBox attribute).
 | |
|    * If aOwnTransforms is non-null and the frame has its own SVG transforms,
 | |
|    * aOwnTransforms will be set to these transforms. If aFromParentTransforms
 | |
|    * is non-null and the frame has an SVG parent with children-only transforms,
 | |
|    * then aFromParentTransforms will be set to these transforms.
 | |
|    */
 | |
|   virtual bool IsSVGTransformed(Matrix *aOwnTransforms = nullptr,
 | |
|                                 Matrix *aFromParentTransforms = nullptr) const;
 | |
| 
 | |
|   /**
 | |
|    * Returns whether this frame will attempt to extend the 3d transforms of its
 | |
|    * children. This requires transform-style: preserve-3d, as well as no clipping
 | |
|    * or svg effects.
 | |
|    *
 | |
|    * @param aStyleDisplay:  If the caller has this->StyleDisplay(), providing
 | |
|    *   it here will improve performance.
 | |
|    *
 | |
|    * @param aEffectSet: This function may need to look up EffectSet property.
 | |
|    *   If a caller already have one, pass it in can save property look up
 | |
|    *   time; otherwise, just left it as nullptr.
 | |
|    */
 | |
|   bool Extend3DContext(const nsStyleDisplay* aStyleDisplay,
 | |
|                        mozilla::EffectSet* aEffectSet = nullptr) const;
 | |
|   bool Extend3DContext(mozilla::EffectSet* aEffectSet = nullptr) const {
 | |
|     return Extend3DContext(StyleDisplay(), aEffectSet);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns whether this frame has a parent that Extend3DContext() and has
 | |
|    * its own transform (or hidden backface) to be combined with the parent's
 | |
|    * transform.
 | |
|    *
 | |
|    * @param aStyleDisplay:  If the caller has this->StyleDisplay(), providing
 | |
|    *   it here will improve performance.
 | |
|    */
 | |
|   bool Combines3DTransformWithAncestors(const nsStyleDisplay* aStyleDisplay) const;
 | |
|   bool Combines3DTransformWithAncestors() const {
 | |
|     return Combines3DTransformWithAncestors(StyleDisplay());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns whether this frame has a hidden backface and has a parent that
 | |
|    * Extend3DContext(). This is useful because in some cases the hidden
 | |
|    * backface can safely be ignored if it could not be visible anyway.
 | |
|    *
 | |
|    */
 | |
|   bool In3DContextAndBackfaceIsHidden() const;
 | |
| 
 | |
|   bool IsPreserve3DLeaf(const nsStyleDisplay* aStyleDisplay,
 | |
|                         mozilla::EffectSet* aEffectSet = nullptr) const {
 | |
|     return Combines3DTransformWithAncestors(aStyleDisplay) &&
 | |
|            !Extend3DContext(aStyleDisplay, aEffectSet);
 | |
|   }
 | |
|   bool IsPreserve3DLeaf(mozilla::EffectSet* aEffectSet = nullptr) const {
 | |
|     return IsPreserve3DLeaf(StyleDisplay(), aEffectSet);
 | |
|   }
 | |
| 
 | |
|   bool HasPerspective(const nsStyleDisplay* aStyleDisplay) const;
 | |
|   bool HasPerspective() const {
 | |
|     return HasPerspective(StyleDisplay());
 | |
|   }
 | |
| 
 | |
|   bool ChildrenHavePerspective(const nsStyleDisplay* aStyleDisplay) const;
 | |
|   bool ChildrenHavePerspective() const {
 | |
|     return ChildrenHavePerspective(StyleDisplay());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Includes the overflow area of all descendants that participate in the current
 | |
|    * 3d context into aOverflowAreas.
 | |
|    */
 | |
|   void ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas);
 | |
| 
 | |
|   void RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame);
 | |
| 
 | |
|   /**
 | |
|    * Returns the number of ancestors between this and the root of our frame tree
 | |
|    */
 | |
|   uint32_t GetDepthInFrameTree() const;
 | |
| 
 | |
|   /**
 | |
|    * Event handling of GUI events.
 | |
|    *
 | |
|    * @param   aEvent event structure describing the type of event and rge widget
 | |
|    *            where the event originated
 | |
|    *          The |point| member of this is in the coordinate system of the
 | |
|    *          view returned by GetOffsetFromView.
 | |
|    * @param   aEventStatus a return value indicating whether the event was handled
 | |
|    *            and whether default processing should be done
 | |
|    *
 | |
|    * XXX From a frame's perspective it's unclear what the effect of the event status
 | |
|    * is. Does it cause the event to continue propagating through the frame hierarchy
 | |
|    * or is it just returned to the widgets?
 | |
|    *
 | |
|    * @see     WidgetGUIEvent
 | |
|    * @see     nsEventStatus
 | |
|    */
 | |
|   virtual nsresult  HandleEvent(nsPresContext* aPresContext,
 | |
|                                 mozilla::WidgetGUIEvent* aEvent,
 | |
|                                 nsEventStatus* aEventStatus) = 0;
 | |
| 
 | |
|   virtual nsresult  GetContentForEvent(mozilla::WidgetEvent* aEvent,
 | |
|                                        nsIContent** aContent) = 0;
 | |
| 
 | |
|   // This structure keeps track of the content node and offsets associated with
 | |
|   // a point; there is a primary and a secondary offset associated with any
 | |
|   // point.  The primary and secondary offsets differ when the point is over a
 | |
|   // non-text object.  The primary offset is the expected position of the
 | |
|   // cursor calculated from a point; the secondary offset, when it is different,
 | |
|   // indicates that the point is in the boundaries of some selectable object.
 | |
|   // Note that the primary offset can be after the secondary offset; for places
 | |
|   // that need the beginning and end of the object, the StartOffset and
 | |
|   // EndOffset helpers can be used.
 | |
|   struct MOZ_STACK_CLASS ContentOffsets
 | |
|   {
 | |
|     ContentOffsets() : offset(0)
 | |
|                      , secondaryOffset(0)
 | |
|                      , associate(mozilla::CARET_ASSOCIATE_BEFORE) {}
 | |
|     bool IsNull() { return !content; }
 | |
|     // Helpers for places that need the ends of the offsets and expect them in
 | |
|     // numerical order, as opposed to wanting the primary and secondary offsets
 | |
|     int32_t StartOffset() { return std::min(offset, secondaryOffset); }
 | |
|     int32_t EndOffset() { return std::max(offset, secondaryOffset); }
 | |
| 
 | |
|     nsCOMPtr<nsIContent> content;
 | |
|     int32_t offset;
 | |
|     int32_t secondaryOffset;
 | |
|     // This value indicates whether the associated content is before or after
 | |
|     // the offset; the most visible use is to allow the caret to know which line
 | |
|     // to display on.
 | |
|     mozilla::CaretAssociationHint associate;
 | |
|   };
 | |
|   enum {
 | |
|     IGNORE_SELECTION_STYLE = 0x01,
 | |
|     // Treat visibility:hidden frames as non-selectable
 | |
|     SKIP_HIDDEN = 0x02
 | |
|   };
 | |
|   /**
 | |
|    * This function calculates the content offsets for selection relative to
 | |
|    * a point.  Note that this should generally only be callled on the event
 | |
|    * frame associated with an event because this function does not account
 | |
|    * for frame lists other than the primary one.
 | |
|    * @param aPoint point relative to this frame
 | |
|    */
 | |
|   ContentOffsets GetContentOffsetsFromPoint(const nsPoint& aPoint,
 | |
|                                             uint32_t aFlags = 0);
 | |
| 
 | |
|   virtual ContentOffsets GetContentOffsetsFromPointExternal(const nsPoint& aPoint,
 | |
|                                                             uint32_t aFlags = 0)
 | |
|   { return GetContentOffsetsFromPoint(aPoint, aFlags); }
 | |
| 
 | |
|   /**
 | |
|    * Ensure that aImage gets notifed when the underlying image request loads
 | |
|    * or animates.
 | |
|    */
 | |
|   void AssociateImage(const nsStyleImage& aImage, nsPresContext* aPresContext,
 | |
|                       uint32_t aImageLoaderFlags);
 | |
| 
 | |
|   /**
 | |
|    * This structure holds information about a cursor. mContainer represents a
 | |
|    * loaded image that should be preferred. If it is not possible to use it, or
 | |
|    * if it is null, mCursor should be used.
 | |
|    */
 | |
|   struct MOZ_STACK_CLASS Cursor {
 | |
|     nsCOMPtr<imgIContainer> mContainer;
 | |
|     int32_t mCursor = NS_STYLE_CURSOR_AUTO;
 | |
|     bool mHaveHotspot = false;
 | |
|     bool mLoading = false;
 | |
|     float mHotspotX = 0.0f, mHotspotY = 0.0f;
 | |
|   };
 | |
|   /**
 | |
|    * Get the cursor for a given frame.
 | |
|    */
 | |
|   virtual nsresult  GetCursor(const nsPoint&  aPoint,
 | |
|                               Cursor&         aCursor) = 0;
 | |
| 
 | |
|   /**
 | |
|    * Get a point (in the frame's coordinate space) given an offset into
 | |
|    * the content. This point should be on the baseline of text with
 | |
|    * the correct horizontal offset
 | |
|    */
 | |
|   virtual nsresult  GetPointFromOffset(int32_t                  inOffset,
 | |
|                                        nsPoint*                 outPoint) = 0;
 | |
| 
 | |
|   /**
 | |
|    * Get a list of character rects in a given range.
 | |
|    * This is similar version of GetPointFromOffset.
 | |
|    */
 | |
|   virtual nsresult  GetCharacterRectsInRange(int32_t aInOffset,
 | |
|                                              int32_t aLength,
 | |
|                                              nsTArray<nsRect>& aRects) = 0;
 | |
| 
 | |
|   /**
 | |
|    * Get the child frame of this frame which contains the given
 | |
|    * content offset. outChildFrame may be this frame, or nullptr on return.
 | |
|    * outContentOffset returns the content offset relative to the start
 | |
|    * of the returned node. You can also pass a hint which tells the method
 | |
|    * to stick to the end of the first found frame or the beginning of the
 | |
|    * next in case the offset falls on a boundary.
 | |
|    */
 | |
|   virtual nsresult GetChildFrameContainingOffset(int32_t    inContentOffset,
 | |
|                                                  bool       inHint,//false stick left
 | |
|                                                  int32_t*   outFrameContentOffset,
 | |
|                                                  nsIFrame** outChildFrame) = 0;
 | |
| 
 | |
|  /**
 | |
|    * Get the current frame-state value for this frame. aResult is
 | |
|    * filled in with the state bits.
 | |
|    */
 | |
|   nsFrameState GetStateBits() const { return mState; }
 | |
| 
 | |
|   /**
 | |
|    * Update the current frame-state value for this frame.
 | |
|    */
 | |
|   void AddStateBits(nsFrameState aBits) { mState |= aBits; }
 | |
|   void RemoveStateBits(nsFrameState aBits) { mState &= ~aBits; }
 | |
|   void AddOrRemoveStateBits(nsFrameState aBits, bool aVal) {
 | |
|     aVal ? AddStateBits(aBits) : RemoveStateBits(aBits);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Checks if the current frame-state includes all of the listed bits
 | |
|    */
 | |
|   bool HasAllStateBits(nsFrameState aBits) const
 | |
|   {
 | |
|     return (mState & aBits) == aBits;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Checks if the current frame-state includes any of the listed bits
 | |
|    */
 | |
|   bool HasAnyStateBits(nsFrameState aBits) const
 | |
|   {
 | |
|     return mState & aBits;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return true if this frame is the primary frame for mContent.
 | |
|    */
 | |
|   bool IsPrimaryFrame() const { return mIsPrimaryFrame; }
 | |
| 
 | |
|   void SetIsPrimaryFrame(bool aIsPrimary) { mIsPrimaryFrame = aIsPrimary; }
 | |
| 
 | |
|   /**
 | |
|    * This call is invoked on the primary frame for a character data content
 | |
|    * node, when it is changed in the content tree.
 | |
|    */
 | |
|   virtual nsresult  CharacterDataChanged(const CharacterDataChangeInfo&) = 0;
 | |
| 
 | |
|   /**
 | |
|    * This call is invoked when the value of a content objects's attribute
 | |
|    * is changed.
 | |
|    * The first frame that maps that content is asked to deal
 | |
|    * with the change by doing whatever is appropriate.
 | |
|    *
 | |
|    * @param aNameSpaceID the namespace of the attribute
 | |
|    * @param aAttribute the atom name of the attribute
 | |
|    * @param aModType Whether or not the attribute was added, changed, or removed.
 | |
|    *   The constants are defined in MutationEvent.webidl.
 | |
|    */
 | |
|   virtual nsresult  AttributeChanged(int32_t         aNameSpaceID,
 | |
|                                      nsAtom*        aAttribute,
 | |
|                                      int32_t         aModType) = 0;
 | |
| 
 | |
|   /**
 | |
|    * When the content states of a content object change, this method is invoked
 | |
|    * on the primary frame of that content object.
 | |
|    *
 | |
|    * @param aStates the changed states
 | |
|    */
 | |
|   virtual void ContentStatesChanged(mozilla::EventStates aStates);
 | |
| 
 | |
|   /**
 | |
|    * Return how your frame can be split.
 | |
|    */
 | |
|   virtual nsSplittableType GetSplittableType() const = 0;
 | |
| 
 | |
|   /**
 | |
|    * Continuation member functions
 | |
|    */
 | |
|   virtual nsIFrame* GetPrevContinuation() const = 0;
 | |
|   virtual void SetPrevContinuation(nsIFrame*) = 0;
 | |
|   virtual nsIFrame* GetNextContinuation() const = 0;
 | |
|   virtual void SetNextContinuation(nsIFrame*) = 0;
 | |
|   virtual nsIFrame* FirstContinuation() const {
 | |
|     return const_cast<nsIFrame*>(this);
 | |
|   }
 | |
|   virtual nsIFrame* LastContinuation() const {
 | |
|     return const_cast<nsIFrame*>(this);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * GetTailContinuation gets the last non-overflow-container continuation
 | |
|    * in the continuation chain, i.e. where the next sibling element
 | |
|    * should attach).
 | |
|    */
 | |
|   nsIFrame* GetTailContinuation();
 | |
| 
 | |
|   /**
 | |
|    * Flow member functions
 | |
|    */
 | |
|   virtual nsIFrame* GetPrevInFlowVirtual() const = 0;
 | |
|   nsIFrame* GetPrevInFlow() const { return GetPrevInFlowVirtual(); }
 | |
|   virtual void SetPrevInFlow(nsIFrame*) = 0;
 | |
| 
 | |
|   virtual nsIFrame* GetNextInFlowVirtual() const = 0;
 | |
|   nsIFrame* GetNextInFlow() const { return GetNextInFlowVirtual(); }
 | |
|   virtual void SetNextInFlow(nsIFrame*) = 0;
 | |
| 
 | |
|   /**
 | |
|    * Return the first frame in our current flow.
 | |
|    */
 | |
|   virtual nsIFrame* FirstInFlow() const {
 | |
|     return const_cast<nsIFrame*>(this);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return the last frame in our current flow.
 | |
|    */
 | |
|   virtual nsIFrame* LastInFlow() const {
 | |
|     return const_cast<nsIFrame*>(this);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Note: "width" in the names and comments on the following methods
 | |
|    * means inline-size, which could be height in vertical layout
 | |
|    */
 | |
| 
 | |
|   /**
 | |
|    * Mark any stored intrinsic width information as dirty (requiring
 | |
|    * re-calculation).  Note that this should generally not be called
 | |
|    * directly; nsPresShell::FrameNeedsReflow will call it instead.
 | |
|    */
 | |
|   virtual void MarkIntrinsicISizesDirty() = 0;
 | |
| 
 | |
|   /**
 | |
|    * Get the min-content intrinsic inline size of the frame.  This must be
 | |
|    * less than or equal to the max-content intrinsic inline size.
 | |
|    *
 | |
|    * This is *not* affected by the CSS 'min-width', 'width', and
 | |
|    * 'max-width' properties on this frame, but it is affected by the
 | |
|    * values of those properties on this frame's descendants.  (It may be
 | |
|    * called during computation of the values of those properties, so it
 | |
|    * cannot depend on any values in the nsStylePosition for this frame.)
 | |
|    *
 | |
|    * The value returned should **NOT** include the space required for
 | |
|    * padding and border.
 | |
|    *
 | |
|    * Note that many frames will cache the result of this function call
 | |
|    * unless MarkIntrinsicISizesDirty is called.
 | |
|    *
 | |
|    * It is not acceptable for a frame to mark itself dirty when this
 | |
|    * method is called.
 | |
|    *
 | |
|    * This method must not return a negative value.
 | |
|    */
 | |
|   virtual nscoord GetMinISize(gfxContext *aRenderingContext) = 0;
 | |
| 
 | |
|   /**
 | |
|    * Get the max-content intrinsic inline size of the frame.  This must be
 | |
|    * greater than or equal to the min-content intrinsic inline size.
 | |
|    *
 | |
|    * Otherwise, all the comments for |GetMinISize| above apply.
 | |
|    */
 | |
|   virtual nscoord GetPrefISize(gfxContext *aRenderingContext) = 0;
 | |
| 
 | |
|   /**
 | |
|    * |InlineIntrinsicISize| represents the intrinsic width information
 | |
|    * in inline layout.  Code that determines the intrinsic width of a
 | |
|    * region of inline layout accumulates the result into this structure.
 | |
|    * This pattern is needed because we need to maintain state
 | |
|    * information about whitespace (for both collapsing and trimming).
 | |
|    */
 | |
|   struct InlineIntrinsicISizeData {
 | |
|     InlineIntrinsicISizeData()
 | |
|       : mLine(nullptr)
 | |
|       , mLineContainer(nullptr)
 | |
|       , mPrevLines(0)
 | |
|       , mCurrentLine(0)
 | |
|       , mTrailingWhitespace(0)
 | |
|       , mSkipWhitespace(true)
 | |
|     {}
 | |
| 
 | |
|     // The line. This may be null if the inlines are not associated with
 | |
|     // a block or if we just don't know the line.
 | |
|     const nsLineList_iterator* mLine;
 | |
| 
 | |
|     // The line container. Private, to ensure we always use SetLineContainer
 | |
|     // to update it (so that we have a chance to store the mLineContainerWM).
 | |
|     //
 | |
|     // Note that nsContainerFrame::DoInlineIntrinsicISize will clear the
 | |
|     // |mLine| and |mLineContainer| fields when following a next-in-flow link,
 | |
|     // so we must not assume these can always be dereferenced.
 | |
|   private:
 | |
|     nsIFrame* mLineContainer;
 | |
| 
 | |
|     // Setter and getter for the lineContainer field:
 | |
|   public:
 | |
|     void SetLineContainer(nsIFrame* aLineContainer)
 | |
|     {
 | |
|       mLineContainer = aLineContainer;
 | |
|       if (mLineContainer) {
 | |
|         mLineContainerWM = mLineContainer->GetWritingMode();
 | |
|       }
 | |
|     }
 | |
|     nsIFrame* LineContainer() const { return mLineContainer; }
 | |
| 
 | |
|     // The maximum intrinsic width for all previous lines.
 | |
|     nscoord mPrevLines;
 | |
| 
 | |
|     // The maximum intrinsic width for the current line.  At a line
 | |
|     // break (mandatory for preferred width; allowed for minimum width),
 | |
|     // the caller should call |Break()|.
 | |
|     nscoord mCurrentLine;
 | |
| 
 | |
|     // This contains the width of the trimmable whitespace at the end of
 | |
|     // |mCurrentLine|; it is zero if there is no such whitespace.
 | |
|     nscoord mTrailingWhitespace;
 | |
| 
 | |
|     // True if initial collapsable whitespace should be skipped.  This
 | |
|     // should be true at the beginning of a block, after hard breaks
 | |
|     // and when the last text ended with whitespace.
 | |
|     bool mSkipWhitespace;
 | |
| 
 | |
|     // Writing mode of the line container (stored here so that we don't
 | |
|     // lose track of it if the mLineContainer field is reset).
 | |
|     mozilla::WritingMode mLineContainerWM;
 | |
| 
 | |
|     // Floats encountered in the lines.
 | |
|     class FloatInfo {
 | |
|     public:
 | |
|       FloatInfo(const nsIFrame* aFrame, nscoord aWidth)
 | |
|         : mFrame(aFrame), mWidth(aWidth)
 | |
|       { }
 | |
|       const nsIFrame* Frame() const { return mFrame; }
 | |
|       nscoord         Width() const { return mWidth; }
 | |
| 
 | |
|     private:
 | |
|       const nsIFrame* mFrame;
 | |
|       nscoord         mWidth;
 | |
|     };
 | |
| 
 | |
|     nsTArray<FloatInfo> mFloats;
 | |
|   };
 | |
| 
 | |
|   struct InlineMinISizeData : public InlineIntrinsicISizeData {
 | |
|     InlineMinISizeData()
 | |
|       : mAtStartOfLine(true)
 | |
|     {}
 | |
| 
 | |
|     // The default implementation for nsIFrame::AddInlineMinISize.
 | |
|     void DefaultAddInlineMinISize(nsIFrame* aFrame,
 | |
|                                   nscoord   aISize,
 | |
|                                   bool      aAllowBreak = true);
 | |
| 
 | |
|     // We need to distinguish forced and optional breaks for cases where the
 | |
|     // current line total is negative.  When it is, we need to ignore
 | |
|     // optional breaks to prevent min-width from ending up bigger than
 | |
|     // pref-width.
 | |
|     void ForceBreak();
 | |
| 
 | |
|     // If the break here is actually taken, aHyphenWidth must be added to the
 | |
|     // width of the current line.
 | |
|     void OptionallyBreak(nscoord aHyphenWidth = 0);
 | |
| 
 | |
|     // Whether we're currently at the start of the line.  If we are, we
 | |
|     // can't break (for example, between the text-indent and the first
 | |
|     // word).
 | |
|     bool mAtStartOfLine;
 | |
|   };
 | |
| 
 | |
|   struct InlinePrefISizeData : public InlineIntrinsicISizeData {
 | |
|     typedef mozilla::StyleClear StyleClear;
 | |
| 
 | |
|     InlinePrefISizeData()
 | |
|       : mLineIsEmpty(true)
 | |
|     {}
 | |
| 
 | |
|     /**
 | |
|      * Finish the current line and start a new line.
 | |
|      *
 | |
|      * @param aBreakType controls whether isize of floats are considered
 | |
|      * and what floats are kept for the next line:
 | |
|      *  * |None| skips handling floats, which means no floats are
 | |
|      *    removed, and isizes of floats are not considered either.
 | |
|      *  * |Both| takes floats into consideration when computing isize
 | |
|      *    of the current line, and removes all floats after that.
 | |
|      *  * |Left| and |Right| do the same as |Both| except that they only
 | |
|      *    remove floats on the given side, and any floats on the other
 | |
|      *    side that are prior to a float on the given side that has a
 | |
|      *    'clear' property that clears them.
 | |
|      * All other values of StyleClear must be converted to the four
 | |
|      * physical values above for this function.
 | |
|      */
 | |
|     void ForceBreak(StyleClear aBreakType = StyleClear::Both);
 | |
| 
 | |
|     // The default implementation for nsIFrame::AddInlinePrefISize.
 | |
|     void DefaultAddInlinePrefISize(nscoord aISize);
 | |
| 
 | |
|     // True if the current line contains nothing other than placeholders.
 | |
|     bool mLineIsEmpty;
 | |
|   };
 | |
| 
 | |
|   /**
 | |
|    * Add the intrinsic minimum width of a frame in a way suitable for
 | |
|    * use in inline layout to an |InlineIntrinsicISizeData| object that
 | |
|    * represents the intrinsic width information of all the previous
 | |
|    * frames in the inline layout region.
 | |
|    *
 | |
|    * All *allowed* breakpoints within the frame determine what counts as
 | |
|    * a line for the |InlineIntrinsicISizeData|.  This means that
 | |
|    * |aData->mTrailingWhitespace| will always be zero (unlike for
 | |
|    * AddInlinePrefISize).
 | |
|    *
 | |
|    * All the comments for |GetMinISize| apply, except that this function
 | |
|    * is responsible for adding padding, border, and margin and for
 | |
|    * considering the effects of 'width', 'min-width', and 'max-width'.
 | |
|    *
 | |
|    * This may be called on any frame.  Frames that do not participate in
 | |
|    * line breaking can inherit the default implementation on nsFrame,
 | |
|    * which calls |GetMinISize|.
 | |
|    */
 | |
|   virtual void
 | |
|   AddInlineMinISize(gfxContext *aRenderingContext,
 | |
|                     InlineMinISizeData *aData) = 0;
 | |
| 
 | |
|   /**
 | |
|    * Add the intrinsic preferred width of a frame in a way suitable for
 | |
|    * use in inline layout to an |InlineIntrinsicISizeData| object that
 | |
|    * represents the intrinsic width information of all the previous
 | |
|    * frames in the inline layout region.
 | |
|    *
 | |
|    * All the comments for |AddInlineMinISize| and |GetPrefISize| apply,
 | |
|    * except that this fills in an |InlineIntrinsicISizeData| structure
 | |
|    * based on using all *mandatory* breakpoints within the frame.
 | |
|    */
 | |
|   virtual void
 | |
|   AddInlinePrefISize(gfxContext *aRenderingContext,
 | |
|                      InlinePrefISizeData *aData) = 0;
 | |
| 
 | |
|   /**
 | |
|    * Return the horizontal components of padding, border, and margin
 | |
|    * that contribute to the intrinsic width that applies to the parent.
 | |
|    * @param aPercentageBasis the percentage basis to use for padding/margin -
 | |
|    *   i.e. the Containing Block's inline-size
 | |
|    */
 | |
|   struct IntrinsicISizeOffsetData {
 | |
|     nscoord hPadding, hBorder, hMargin;
 | |
| 
 | |
|     IntrinsicISizeOffsetData()
 | |
|       : hPadding(0), hBorder(0), hMargin(0)
 | |
|     {}
 | |
|   };
 | |
|   virtual IntrinsicISizeOffsetData
 | |
|   IntrinsicISizeOffsets(nscoord aPercentageBasis = NS_UNCONSTRAINEDSIZE) = 0;
 | |
| 
 | |
|   /**
 | |
|    * Return the bsize components of padding, border, and margin
 | |
|    * that contribute to the intrinsic width that applies to the parent.
 | |
|    * @param aPercentageBasis the percentage basis to use for padding/margin -
 | |
|    *   i.e. the Containing Block's inline-size
 | |
|    */
 | |
|   IntrinsicISizeOffsetData
 | |
|   IntrinsicBSizeOffsets(nscoord aPercentageBasis = NS_UNCONSTRAINEDSIZE);
 | |
| 
 | |
|   virtual mozilla::IntrinsicSize GetIntrinsicSize() = 0;
 | |
| 
 | |
|   /**
 | |
|    * Get the intrinsic ratio of this element, or nsSize(0,0) if it has
 | |
|    * no intrinsic ratio.  The intrinsic ratio is the ratio of the
 | |
|    * height/width of a box with an intrinsic size or the intrinsic
 | |
|    * aspect ratio of a scalable vector image without an intrinsic size.
 | |
|    *
 | |
|    * Either one of the sides may be zero, indicating a zero or infinite
 | |
|    * ratio.
 | |
|    */
 | |
|   virtual nsSize GetIntrinsicRatio() = 0;
 | |
| 
 | |
|   /**
 | |
|    * Bit-flags to pass to ComputeSize in |aFlags| parameter.
 | |
|    */
 | |
|   enum ComputeSizeFlags {
 | |
|     eDefault =           0,
 | |
|     /**
 | |
|      * Set if the frame is in a context where non-replaced blocks should
 | |
|      * shrink-wrap (e.g., it's floating, absolutely positioned, or
 | |
|      * inline-block).
 | |
|      */
 | |
|     eShrinkWrap =        1 << 0,
 | |
|     /**
 | |
|      * Set if we'd like to compute our 'auto' bsize, regardless of our actual
 | |
|      * corresponding computed value. (e.g. to get an intrinsic height for flex
 | |
|      * items with "min-height: auto" to use during flexbox layout.)
 | |
|      */
 | |
|     eUseAutoBSize =      1 << 1,
 | |
|     /**
 | |
|      * Indicates that we should clamp the margin-box min-size to the given CB
 | |
|      * size.  This is used for implementing the grid area clamping here:
 | |
|      * https://drafts.csswg.org/css-grid/#min-size-auto
 | |
|      */
 | |
|     eIClampMarginBoxMinSize = 1 << 2, // clamp in our inline axis
 | |
|     eBClampMarginBoxMinSize = 1 << 3, // clamp in our block axis
 | |
|     /**
 | |
|      * The frame is stretching (per CSS Box Alignment) and doesn't have an
 | |
|      * Automatic Minimum Size in the indicated axis.
 | |
|      * (may be used for both flex/grid items, but currently only used for Grid)
 | |
|      * https://drafts.csswg.org/css-grid/#min-size-auto
 | |
|      * https://drafts.csswg.org/css-align-3/#valdef-justify-self-stretch
 | |
|      */
 | |
|     eIApplyAutoMinSize = 1 << 4, // only has an effect when eShrinkWrap is false
 | |
|   };
 | |
| 
 | |
|   /**
 | |
|    * Compute the size that a frame will occupy.  Called while
 | |
|    * constructing the ReflowInput to be used to Reflow the frame,
 | |
|    * in order to fill its mComputedWidth and mComputedHeight member
 | |
|    * variables.
 | |
|    *
 | |
|    * The |height| member of the return value may be
 | |
|    * NS_UNCONSTRAINEDSIZE, but the |width| member must not be.
 | |
|    *
 | |
|    * Note that the reason that border and padding need to be passed
 | |
|    * separately is so that the 'box-sizing' property can be handled.
 | |
|    * Thus aMargin includes absolute positioning offsets as well.
 | |
|    *
 | |
|    * @param aWritingMode  The writing mode to use for the returned size
 | |
|    *                      (need not match this frame's writing mode).
 | |
|    *                      This is also the writing mode of the passed-in
 | |
|    *                      LogicalSize parameters.
 | |
|    * @param aCBSize  The size of the element's containing block.  (Well,
 | |
|    *                 the |height| component isn't really.)
 | |
|    * @param aAvailableWidth  The available width for 'auto' widths.
 | |
|    *                         This is usually the same as aCBSize.width,
 | |
|    *                         but differs in cases such as block
 | |
|    *                         formatting context roots next to floats, or
 | |
|    *                         in some cases of float reflow in quirks
 | |
|    *                         mode.
 | |
|    * @param aMargin  The sum of the vertical / horizontal margins
 | |
|    *                 ***AND*** absolute positioning offsets (top, right,
 | |
|    *                 bottom, left) of the frame, including actual values
 | |
|    *                 resulting from percentages and from the
 | |
|    *                 "hypothetical box" for absolute positioning, but
 | |
|    *                 not including actual values resulting from 'auto'
 | |
|    *                 margins or ignored 'auto' values in absolute
 | |
|    *                 positioning.
 | |
|    * @param aBorder  The sum of the vertical / horizontal border widths
 | |
|    *                 of the frame.
 | |
|    * @param aPadding The sum of the vertical / horizontal margins of
 | |
|    *                 the frame, including actual values resulting from
 | |
|    *                 percentages.
 | |
|    * @param aFlags   Flags to further customize behavior (definitions above).
 | |
|    */
 | |
|   virtual mozilla::LogicalSize
 | |
|   ComputeSize(gfxContext *aRenderingContext,
 | |
|               mozilla::WritingMode aWritingMode,
 | |
|               const mozilla::LogicalSize& aCBSize,
 | |
|               nscoord aAvailableISize,
 | |
|               const mozilla::LogicalSize& aMargin,
 | |
|               const mozilla::LogicalSize& aBorder,
 | |
|               const mozilla::LogicalSize& aPadding,
 | |
|               ComputeSizeFlags aFlags) = 0;
 | |
| 
 | |
|   /**
 | |
|    * Compute a tight bounding rectangle for the frame. This is a rectangle
 | |
|    * that encloses the pixels that are actually drawn. We're allowed to be
 | |
|    * conservative and currently we don't try very hard. The rectangle is
 | |
|    * in appunits and relative to the origin of this frame.
 | |
|    *
 | |
|    * This probably only needs to include frame bounds, glyph bounds, and
 | |
|    * text decorations, but today it sometimes includes other things that
 | |
|    * contribute to visual overflow.
 | |
|    *
 | |
|    * @param aDrawTarget a draw target that can be used if we need
 | |
|    * to do measurement
 | |
|    */
 | |
|   virtual nsRect ComputeTightBounds(DrawTarget* aDrawTarget) const;
 | |
| 
 | |
|   /**
 | |
|    * This function is similar to GetPrefISize and ComputeTightBounds: it
 | |
|    * computes the left and right coordinates of a preferred tight bounding
 | |
|    * rectangle for the frame. This is a rectangle that would enclose the pixels
 | |
|    * that are drawn if we lay out the element without taking any optional line
 | |
|    * breaks. The rectangle is in appunits and relative to the origin of this
 | |
|    * frame. Currently, this function is only implemented for nsBlockFrame and
 | |
|    * nsTextFrame and is used to determine intrinsic widths of MathML token
 | |
|    * elements.
 | |
| 
 | |
|    * @param aContext a rendering context that can be used if we need
 | |
|    * to do measurement
 | |
|    * @param aX      computed left coordinate of the tight bounding rectangle
 | |
|    * @param aXMost  computed intrinsic width of the tight bounding rectangle
 | |
|    *
 | |
|    */
 | |
|   virtual nsresult GetPrefWidthTightBounds(gfxContext* aContext,
 | |
|                                            nscoord* aX,
 | |
|                                            nscoord* aXMost);
 | |
| 
 | |
|   /**
 | |
|    * The frame is given an available size and asked for its desired
 | |
|    * size.  This is the frame's opportunity to reflow its children.
 | |
|    *
 | |
|    * If the frame has the NS_FRAME_IS_DIRTY bit set then it is
 | |
|    * responsible for completely reflowing itself and all of its
 | |
|    * descendants.
 | |
|    *
 | |
|    * Otherwise, if the frame has the NS_FRAME_HAS_DIRTY_CHILDREN bit
 | |
|    * set, then it is responsible for reflowing at least those
 | |
|    * children that have NS_FRAME_HAS_DIRTY_CHILDREN or NS_FRAME_IS_DIRTY
 | |
|    * set.
 | |
|    *
 | |
|    * If a difference in available size from the previous reflow causes
 | |
|    * the frame's size to change, it should reflow descendants as needed.
 | |
|    *
 | |
|    * @param aReflowOutput <i>out</i> parameter where you should return the
 | |
|    *          desired size and ascent/descent info. You should include any
 | |
|    *          space you want for border/padding in the desired size you return.
 | |
|    *
 | |
|    *          It's okay to return a desired size that exceeds the avail
 | |
|    *          size if that's the smallest you can be, i.e. it's your
 | |
|    *          minimum size.
 | |
|    *
 | |
|    *          For an incremental reflow you are responsible for invalidating
 | |
|    *          any area within your frame that needs repainting (including
 | |
|    *          borders). If your new desired size is different than your current
 | |
|    *          size, then your parent frame is responsible for making sure that
 | |
|    *          the difference between the two rects is repainted
 | |
|    *
 | |
|    * @param aReflowInput information about your reflow including the reason
 | |
|    *          for the reflow and the available space in which to lay out. Each
 | |
|    *          dimension of the available space can either be constrained or
 | |
|    *          unconstrained (a value of NS_UNCONSTRAINEDSIZE).
 | |
|    *
 | |
|    *          Note that the available space can be negative. In this case you
 | |
|    *          still must return an accurate desired size. If you're a container
 | |
|    *          you must <b>always</b> reflow at least one frame regardless of the
 | |
|    *          available space
 | |
|    *
 | |
|    * @param aStatus a return value indicating whether the frame is complete
 | |
|    *          and whether the next-in-flow is dirty and needs to be reflowed
 | |
|    */
 | |
|   virtual void Reflow(nsPresContext*           aPresContext,
 | |
|                       ReflowOutput&     aReflowOutput,
 | |
|                       const ReflowInput& aReflowInput,
 | |
|                       nsReflowStatus&          aStatus) = 0;
 | |
| 
 | |
|   /**
 | |
|    * Post-reflow hook. After a frame is reflowed this method will be called
 | |
|    * informing the frame that this reflow process is complete, and telling the
 | |
|    * frame the status returned by the Reflow member function.
 | |
|    *
 | |
|    * This call may be invoked many times, while NS_FRAME_IN_REFLOW is set, before
 | |
|    * it is finally called once with a NS_FRAME_REFLOW_COMPLETE value. When called
 | |
|    * with a NS_FRAME_REFLOW_COMPLETE value the NS_FRAME_IN_REFLOW bit in the
 | |
|    * frame state will be cleared.
 | |
|    *
 | |
|    * XXX This doesn't make sense. If the frame is reflowed but not complete, then
 | |
|    * the status should have IsIncomplete() equal to true.
 | |
|    * XXX Don't we want the semantics to dictate that we only call this once for
 | |
|    * a given reflow?
 | |
|    */
 | |
|   virtual void DidReflow(nsPresContext*           aPresContext,
 | |
|                          const ReflowInput* aReflowInput) = 0;
 | |
| 
 | |
|   /**
 | |
|    * Updates the overflow areas of the frame. This can be called if an
 | |
|    * overflow area of the frame's children has changed without reflowing.
 | |
|    * @return true if either of the overflow areas for this frame have changed.
 | |
|    */
 | |
|   bool UpdateOverflow();
 | |
| 
 | |
|   /**
 | |
|    * Computes any overflow area created by the frame itself (outside of the
 | |
|    * frame bounds) and includes it into aOverflowAreas.
 | |
|    *
 | |
|    * Returns false if updating overflow isn't supported for this frame.
 | |
|    * If the frame requires a reflow instead, then it is responsible
 | |
|    * for scheduling one.
 | |
|    */
 | |
|   virtual bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) = 0;
 | |
| 
 | |
|   /**
 | |
|    * Computes any overflow area created by children of this frame and
 | |
|    * includes it into aOverflowAreas.
 | |
|    */
 | |
|   virtual void UnionChildOverflow(nsOverflowAreas& aOverflowAreas) = 0;
 | |
| 
 | |
|   /**
 | |
|    * Helper method used by block reflow to identify runs of text so
 | |
|    * that proper word-breaking can be done.
 | |
|    *
 | |
|    * @return
 | |
|    *    true if we can continue a "text run" through the frame. A
 | |
|    *    text run is text that should be treated contiguously for line
 | |
|    *    and word breaking.
 | |
|    */
 | |
|   virtual bool CanContinueTextRun() const = 0;
 | |
| 
 | |
|   /**
 | |
|    * Computes an approximation of the rendered text of the frame and its
 | |
|    * continuations. Returns nothing for non-text frames.
 | |
|    * The appended text will often not contain all the whitespace from source,
 | |
|    * depending on CSS white-space processing.
 | |
|    * if aEndOffset goes past end, use the text up to the string's end.
 | |
|    * Call this on the primary frame for a text node.
 | |
|    * aStartOffset and aEndOffset can be content offsets or offsets in the
 | |
|    * rendered text, depending on aOffsetType.
 | |
|    * Returns a string, as well as offsets identifying the start of the text
 | |
|    * within the rendered text for the whole node, and within the text content
 | |
|    * of the node.
 | |
|    */
 | |
|   struct RenderedText {
 | |
|     nsAutoString mString;
 | |
|     uint32_t mOffsetWithinNodeRenderedText;
 | |
|     int32_t mOffsetWithinNodeText;
 | |
|     RenderedText() : mOffsetWithinNodeRenderedText(0),
 | |
|         mOffsetWithinNodeText(0) {}
 | |
|   };
 | |
|   enum class TextOffsetType {
 | |
|     // Passed-in start and end offsets are within the content text.
 | |
|     OFFSETS_IN_CONTENT_TEXT,
 | |
|     // Passed-in start and end offsets are within the rendered text.
 | |
|     OFFSETS_IN_RENDERED_TEXT
 | |
|   };
 | |
|   enum class TrailingWhitespace {
 | |
|     TRIM_TRAILING_WHITESPACE,
 | |
|     // Spaces preceding a caret at the end of a line should not be trimmed
 | |
|     DONT_TRIM_TRAILING_WHITESPACE
 | |
|   };
 | |
|   virtual RenderedText GetRenderedText(uint32_t aStartOffset = 0,
 | |
|                                        uint32_t aEndOffset = UINT32_MAX,
 | |
|                                        TextOffsetType aOffsetType =
 | |
|                                            TextOffsetType::OFFSETS_IN_CONTENT_TEXT,
 | |
|                                        TrailingWhitespace aTrimTrailingWhitespace =
 | |
|                                            TrailingWhitespace::TRIM_TRAILING_WHITESPACE)
 | |
|   { return RenderedText(); }
 | |
| 
 | |
|   /**
 | |
|    * Returns true if the frame contains any non-collapsed characters.
 | |
|    * This method is only available for text frames, and it will return false
 | |
|    * for all other frame types.
 | |
|    */
 | |
|   virtual bool HasAnyNoncollapsedCharacters()
 | |
|   { return false; }
 | |
| 
 | |
|   /**
 | |
|    * Returns true if events of the given type targeted at this frame
 | |
|    * should only be dispatched to the system group.
 | |
|    */
 | |
|   virtual bool OnlySystemGroupDispatch(mozilla::EventMessage aMessage) const
 | |
|   { return false; }
 | |
| 
 | |
|   //
 | |
|   // Accessor functions to an associated view object:
 | |
|   //
 | |
|   bool HasView() const { return !!(mState & NS_FRAME_HAS_VIEW); }
 | |
| protected:
 | |
|   virtual nsView* GetViewInternal() const
 | |
|   {
 | |
|     MOZ_ASSERT_UNREACHABLE("method should have been overridden by subclass");
 | |
|     return nullptr;
 | |
|   }
 | |
|   virtual void SetViewInternal(nsView* aView)
 | |
|   {
 | |
|     MOZ_ASSERT_UNREACHABLE("method should have been overridden by subclass");
 | |
|   }
 | |
| public:
 | |
|   nsView* GetView() const
 | |
|   {
 | |
|     if (MOZ_LIKELY(!HasView())) {
 | |
|       return nullptr;
 | |
|     }
 | |
|     nsView* view = GetViewInternal();
 | |
|     MOZ_ASSERT(view, "GetViewInternal() should agree with HasView()");
 | |
|     return view;
 | |
|   }
 | |
|   void SetView(nsView* aView);
 | |
| 
 | |
|   /**
 | |
|    * Find the closest view (on |this| or an ancestor).
 | |
|    * If aOffset is non-null, it will be set to the offset of |this|
 | |
|    * from the returned view.
 | |
|    */
 | |
|   nsView* GetClosestView(nsPoint* aOffset = nullptr) const;
 | |
| 
 | |
|   /**
 | |
|    * Find the closest ancestor (excluding |this| !) that has a view
 | |
|    */
 | |
|   nsIFrame* GetAncestorWithView() const;
 | |
| 
 | |
|   /**
 | |
|    * Sets the view's attributes from the frame style.
 | |
|    * Call this for nsChangeHint_SyncFrameView style changes or when the view
 | |
|    * has just been created.
 | |
|    * @param aView the frame's view or use GetView() if nullptr is given
 | |
|    */
 | |
|   void SyncFrameViewProperties(nsView* aView = nullptr);
 | |
| 
 | |
|   /**
 | |
|    * Get the offset between the coordinate systems of |this| and aOther.
 | |
|    * Adding the return value to a point in the coordinate system of |this|
 | |
|    * will transform the point to the coordinate system of aOther.
 | |
|    *
 | |
|    * aOther must be non-null.
 | |
|    *
 | |
|    * This function is fastest when aOther is an ancestor of |this|.
 | |
|    *
 | |
|    * This function _DOES NOT_ work across document boundaries.
 | |
|    * Use this function only when |this| and aOther are in the same document.
 | |
|    *
 | |
|    * NOTE: this actually returns the offset from aOther to |this|, but
 | |
|    * that offset is added to transform _coordinates_ from |this| to
 | |
|    * aOther.
 | |
|    */
 | |
|   nsPoint GetOffsetTo(const nsIFrame* aOther) const;
 | |
| 
 | |
|   /**
 | |
|    * Just like GetOffsetTo, but treats all scrollframes as scrolled to
 | |
|    * their origin.
 | |
|    */
 | |
|   nsPoint GetOffsetToIgnoringScrolling(const nsIFrame* aOther) const;
 | |
| 
 | |
|   /**
 | |
|    * Get the offset between the coordinate systems of |this| and aOther
 | |
|    * expressed in appunits per dev pixel of |this|' document. Adding the return
 | |
|    * value to a point that is relative to the origin of |this| will make the
 | |
|    * point relative to the origin of aOther but in the appunits per dev pixel
 | |
|    * ratio of |this|.
 | |
|    *
 | |
|    * aOther must be non-null.
 | |
|    *
 | |
|    * This function is fastest when aOther is an ancestor of |this|.
 | |
|    *
 | |
|    * This function works across document boundaries.
 | |
|    *
 | |
|    * Because this function may cross document boundaries that have different
 | |
|    * app units per dev pixel ratios it needs to be used very carefully.
 | |
|    *
 | |
|    * NOTE: this actually returns the offset from aOther to |this|, but
 | |
|    * that offset is added to transform _coordinates_ from |this| to
 | |
|    * aOther.
 | |
|    */
 | |
|   nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther) const;
 | |
| 
 | |
|   /**
 | |
|    * Like GetOffsetToCrossDoc, but the caller can specify which appunits
 | |
|    * to return the result in.
 | |
|    */
 | |
|   nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther, const int32_t aAPD) const;
 | |
| 
 | |
|   /**
 | |
|    * Get the rect of the frame relative to the top-left corner of the
 | |
|    * screen in CSS pixels.
 | |
|    * @return the CSS pixel rect of the frame relative to the top-left
 | |
|    *         corner of the screen.
 | |
|    */
 | |
|   mozilla::CSSIntRect GetScreenRect() const;
 | |
| 
 | |
|   /**
 | |
|    * Get the screen rect of the frame in app units.
 | |
|    * @return the app unit rect of the frame in screen coordinates.
 | |
|    */
 | |
|   nsRect GetScreenRectInAppUnits() const;
 | |
| 
 | |
|   /**
 | |
|    * Returns the offset from this frame to the closest geometric parent that
 | |
|    * has a view. Also returns the containing view or null in case of error
 | |
|    */
 | |
|   void GetOffsetFromView(nsPoint& aOffset, nsView** aView) const;
 | |
| 
 | |
|   /**
 | |
|    * Returns the nearest widget containing this frame. If this frame has a
 | |
|    * view and the view has a widget, then this frame's widget is
 | |
|    * returned, otherwise this frame's geometric parent is checked
 | |
|    * recursively upwards.
 | |
|    */
 | |
|   nsIWidget* GetNearestWidget() const;
 | |
| 
 | |
|   /**
 | |
|    * Same as GetNearestWidget() above but uses an outparam to return the offset
 | |
|    * of this frame to the returned widget expressed in appunits of |this| (the
 | |
|    * widget might be in a different document with a different zoom).
 | |
|    */
 | |
|   nsIWidget* GetNearestWidget(nsPoint& aOffset) const;
 | |
| 
 | |
|   /**
 | |
|    * Whether the content for this frame is disabled, used for event handling.
 | |
|    */
 | |
|   bool IsContentDisabled() const;
 | |
| 
 | |
|   /**
 | |
|    * Get the "type" of the frame.
 | |
|    *
 | |
|    * @see mozilla::LayoutFrameType
 | |
|    */
 | |
|   mozilla::LayoutFrameType Type() const {
 | |
|     MOZ_ASSERT(uint8_t(mClass) < mozilla::ArrayLength(sLayoutFrameTypes));
 | |
|     return sLayoutFrameTypes[uint8_t(mClass)];
 | |
|   }
 | |
| 
 | |
| #define FRAME_TYPE(name_)                                                      \
 | |
|   bool Is##name_##Frame() const                                                \
 | |
|   {                                                                            \
 | |
|     return Type() == mozilla::LayoutFrameType::name_;                          \
 | |
|   }
 | |
| #include "mozilla/FrameTypeList.h"
 | |
| #undef FRAME_TYPE
 | |
| 
 | |
|   /**
 | |
|    * Returns a transformation matrix that converts points in this frame's
 | |
|    * coordinate space to points in some ancestor frame's coordinate space.
 | |
|    * The frame decides which ancestor it will use as a reference point.
 | |
|    * If this frame has no ancestor, aOutAncestor will be set to null.
 | |
|    *
 | |
|    * @param aStopAtAncestor don't look further than aStopAtAncestor. If null,
 | |
|    *   all ancestors (including across documents) will be traversed.
 | |
|    * @param aOutAncestor [out] The ancestor frame the frame has chosen.  If
 | |
|    *   this frame has no ancestor, *aOutAncestor will be set to null. If
 | |
|    * this frame is not a root frame, then *aOutAncestor will be in the same
 | |
|    * document as this frame. If this frame IsTransformed(), then *aOutAncestor
 | |
|    * will be the parent frame (if not preserve-3d) or the nearest non-transformed
 | |
|    * ancestor (if preserve-3d).
 | |
|    * @return A Matrix4x4 that converts points in this frame's coordinate space
 | |
|    *   into points in aOutAncestor's coordinate space.
 | |
|    */
 | |
|   enum {
 | |
|     IN_CSS_UNITS = 1 << 0,
 | |
|     STOP_AT_STACKING_CONTEXT_AND_DISPLAY_PORT = 1 << 1
 | |
|   };
 | |
|   Matrix4x4Flagged GetTransformMatrix(const nsIFrame* aStopAtAncestor,
 | |
|                                       nsIFrame **aOutAncestor,
 | |
|                                       uint32_t aFlags = 0) const;
 | |
| 
 | |
|   /**
 | |
|    * Bit-flags to pass to IsFrameOfType()
 | |
|    */
 | |
|   enum {
 | |
|     eMathML =                           1 << 0,
 | |
|     eSVG =                              1 << 1,
 | |
|     eSVGForeignObject =                 1 << 2,
 | |
|     eSVGContainer =                     1 << 3,
 | |
|     eSVGGeometry =                      1 << 4,
 | |
|     eSVGPaintServer =                   1 << 5,
 | |
|     eBidiInlineContainer =              1 << 6,
 | |
|     // the frame is for a replaced element, such as an image
 | |
|     eReplaced =                         1 << 7,
 | |
|     // Frame that contains a block but looks like a replaced element
 | |
|     // from the outside
 | |
|     eReplacedContainsBlock =            1 << 8,
 | |
|     // A frame that participates in inline reflow, i.e., one that
 | |
|     // requires ReflowInput::mLineLayout.
 | |
|     eLineParticipant =                  1 << 9,
 | |
|     eXULBox =                           1 << 10,
 | |
|     eCanContainOverflowContainers =     1 << 11,
 | |
|     eBlockFrame =                       1 << 12,
 | |
|     eTablePart =                        1 << 13,
 | |
|     // If this bit is set, the frame doesn't allow ignorable whitespace as
 | |
|     // children. For example, the whitespace between <table>\n<tr>\n<td>
 | |
|     // will be excluded during the construction of children.
 | |
|     eExcludesIgnorableWhitespace =      1 << 14,
 | |
|     eSupportsCSSTransforms =            1 << 15,
 | |
| 
 | |
|     // A replaced element that has replaced-element sizing
 | |
|     // characteristics (i.e., like images or iframes), as opposed to
 | |
|     // inline-block sizing characteristics (like form controls).
 | |
|     eReplacedSizing =                   1 << 16,
 | |
| 
 | |
|     // These are to allow nsFrame::Init to assert that IsFrameOfType
 | |
|     // implementations all call the base class method.  They are only
 | |
|     // meaningful in DEBUG builds.
 | |
|     eDEBUGAllFrames =                   1 << 30,
 | |
|     eDEBUGNoFrames =                    1 << 31
 | |
|   };
 | |
| 
 | |
|   /**
 | |
|    * API for doing a quick check if a frame is of a given
 | |
|    * type. Returns true if the frame matches ALL flags passed in.
 | |
|    *
 | |
|    * Implementations should always override with inline virtual
 | |
|    * functions that call the base class's IsFrameOfType method.
 | |
|    */
 | |
|   virtual bool IsFrameOfType(uint32_t aFlags) const
 | |
|   {
 | |
| #ifdef DEBUG
 | |
|     return !(aFlags & ~(nsIFrame::eDEBUGAllFrames | nsIFrame::eSupportsCSSTransforms));
 | |
| #else
 | |
|     return !(aFlags & ~nsIFrame::eSupportsCSSTransforms);
 | |
| #endif
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns true if the frame is a block wrapper.
 | |
|    */
 | |
|   bool IsBlockWrapper() const;
 | |
| 
 | |
|   /**
 | |
|    * Get this frame's CSS containing block.
 | |
|    *
 | |
|    * The algorithm is defined in
 | |
|    * http://www.w3.org/TR/CSS2/visudet.html#containing-block-details.
 | |
|    *
 | |
|    * NOTE: This is guaranteed to return a non-null pointer when invoked on any
 | |
|    * frame other than the root frame.
 | |
|    *
 | |
|    * Requires SKIP_SCROLLED_FRAME to get behaviour matching the spec, otherwise
 | |
|    * it can return anonymous inner scrolled frames. Bug 1204044 is filed for
 | |
|    * investigating whether any of the callers actually require the default
 | |
|    * behaviour.
 | |
|    */
 | |
|   enum {
 | |
|     // If the containing block is an anonymous scrolled frame, then skip over
 | |
|     // this and return the outer scroll frame.
 | |
|     SKIP_SCROLLED_FRAME = 0x01
 | |
|   };
 | |
|   nsIFrame* GetContainingBlock(uint32_t aFlags,
 | |
|                                const nsStyleDisplay* aStyleDisplay) const;
 | |
|   nsIFrame* GetContainingBlock(uint32_t aFlags = 0) const {
 | |
|     return GetContainingBlock(aFlags, StyleDisplay());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Is this frame a containing block for floating elements?
 | |
|    * Note that very few frames are, so default to false.
 | |
|    */
 | |
|   virtual bool IsFloatContainingBlock() const { return false; }
 | |
| 
 | |
|   /**
 | |
|    * Is this a leaf frame?  Frames that want the frame constructor to be able
 | |
|    * to construct kids for them should return false, all others should return
 | |
|    * true.  Note that returning true here does not mean that the frame _can't_
 | |
|    * have kids.  It could still have kids created via
 | |
|    * nsIAnonymousContentCreator.  Returning true indicates that "normal"
 | |
|    * (non-anonymous, XBL-bound, CSS generated content, etc) children should not
 | |
|    * be constructed.
 | |
|    */
 | |
|   bool IsLeaf() const
 | |
|   {
 | |
|     MOZ_ASSERT(uint8_t(mClass) < mozilla::ArrayLength(sFrameClassBits));
 | |
|     FrameClassBits bits = sFrameClassBits[uint8_t(mClass)];
 | |
|     if (MOZ_UNLIKELY(bits & eFrameClassBitsDynamicLeaf)) {
 | |
|       return IsLeafDynamic();
 | |
|     }
 | |
|     return bits & eFrameClassBitsLeaf;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Marks all display items created by this frame as needing a repaint,
 | |
|    * and calls SchedulePaint() if requested and one is not already pending.
 | |
|    *
 | |
|    * This includes all display items created by this frame, including
 | |
|    * container types.
 | |
|    *
 | |
|    * @param aDisplayItemKey If specified, only issues an invalidate
 | |
|    * if this frame painted a display item of that type during the
 | |
|    * previous paint. SVG rendering observers are always notified.
 | |
|    * @param aRebuildDisplayItems If true, then adds this frame to the
 | |
|    * list of modified frames for display list building. Only pass false
 | |
|    * if you're sure that the relevant display items will be rebuilt
 | |
|    * already (possibly by an ancestor being in the modified list).
 | |
|    */
 | |
|   virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0, bool aRebuildDisplayItems = true);
 | |
| 
 | |
|   /**
 | |
|    * Same as InvalidateFrame(), but only mark a fixed rect as needing
 | |
|    * repainting.
 | |
|    *
 | |
|    * @param aRect The rect to invalidate, relative to the TopLeft of the
 | |
|    * frame's border box.
 | |
|    * @param aDisplayItemKey If specified, only issues an invalidate
 | |
|    * if this frame painted a display item of that type during the
 | |
|    * previous paint. SVG rendering observers are always notified.
 | |
|    * @param aRebuildDisplayItems If true, then adds this frame to the
 | |
|    * list of modified frames for display list building. Only pass false
 | |
|    * if you're sure that the relevant display items will be rebuilt
 | |
|    * already (possibly by an ancestor being in the modified list).
 | |
|    */
 | |
|   virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0, bool aRebuildDisplayItems = true);
 | |
| 
 | |
|   /**
 | |
|    * Calls InvalidateFrame() on all frames descendant frames (including
 | |
|    * this one).
 | |
|    *
 | |
|    * This function doesn't walk through placeholder frames to invalidate
 | |
|    * the out-of-flow frames.
 | |
|    *
 | |
|    * @param aRebuildDisplayItems If true, then adds this frame to the
 | |
|    * list of modified frames for display list building. Only pass false
 | |
|    * if you're sure that the relevant display items will be rebuilt
 | |
|    * already (possibly by an ancestor being in the modified list).
 | |
|    */
 | |
|   void InvalidateFrameSubtree(bool aRebuildDisplayItems = true);
 | |
| 
 | |
|   /**
 | |
|    * Called when a frame is about to be removed and needs to be invalidated.
 | |
|    * Normally does nothing since DLBI handles removed frames.
 | |
|    */
 | |
|   virtual void InvalidateFrameForRemoval() {}
 | |
| 
 | |
|   /**
 | |
|    * When HasUserData(frame->LayerIsPrerenderedDataKey()), then the
 | |
|    * entire overflow area of this frame has been rendered in its
 | |
|    * layer(s).
 | |
|    */
 | |
|   static void* LayerIsPrerenderedDataKey() {
 | |
|     return &sLayerIsPrerenderedDataKey;
 | |
|   }
 | |
|   static uint8_t sLayerIsPrerenderedDataKey;
 | |
| 
 | |
|    /**
 | |
|    * Try to update this frame's transform without invalidating any
 | |
|    * content.  Return true iff successful.  If unsuccessful, the
 | |
|    * caller is responsible for scheduling an invalidating paint.
 | |
|    *
 | |
|    * If the result is true, aLayerResult will be filled in with the
 | |
|    * transform layer for the frame.
 | |
|    */
 | |
|   bool TryUpdateTransformOnly(Layer** aLayerResult);
 | |
| 
 | |
|   /**
 | |
|    * Checks if a frame has had InvalidateFrame() called on it since the
 | |
|    * last paint.
 | |
|    *
 | |
|    * If true, then the invalid rect is returned in aRect, with an
 | |
|    * empty rect meaning all pixels drawn by this frame should be
 | |
|    * invalidated.
 | |
|    * If false, aRect is left unchanged.
 | |
|    */
 | |
|   bool IsInvalid(nsRect& aRect);
 | |
| 
 | |
|   /**
 | |
|    * Check if any frame within the frame subtree (including this frame)
 | |
|    * returns true for IsInvalid().
 | |
|    */
 | |
|   bool HasInvalidFrameInSubtree()
 | |
|   {
 | |
|     return HasAnyStateBits(NS_FRAME_NEEDS_PAINT | NS_FRAME_DESCENDANT_NEEDS_PAINT);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Removes the invalid state from the current frame and all
 | |
|    * descendant frames.
 | |
|    */
 | |
|   void ClearInvalidationStateBits();
 | |
| 
 | |
|   /**
 | |
|    * Ensures that the refresh driver is running, and schedules a view
 | |
|    * manager flush on the next tick.
 | |
|    *
 | |
|    * The view manager flush will update the layer tree, repaint any
 | |
|    * invalid areas in the layer tree and schedule a layer tree
 | |
|    * composite operation to display the layer tree.
 | |
|    *
 | |
|    * In general it is not necessary for frames to call this when they change.
 | |
|    * For example, changes that result in a reflow will have this called for
 | |
|    * them by PresContext::DoReflow when the reflow begins. Style changes that
 | |
|    * do not trigger a reflow should have this called for them by
 | |
|    * DoApplyRenderingChangeToTree.
 | |
|    *
 | |
|    * @param aType PAINT_COMPOSITE_ONLY : No changes have been made
 | |
|    * that require a layer tree update, so only schedule a layer
 | |
|    * tree composite.
 | |
|    * PAINT_DELAYED_COMPRESS : Schedule a paint to be executed after a delay, and
 | |
|    * put FrameLayerBuilder in 'compressed' mode that avoids short cut optimizations.
 | |
|    */
 | |
|   enum PaintType {
 | |
|     PAINT_DEFAULT = 0,
 | |
|     PAINT_COMPOSITE_ONLY,
 | |
|     PAINT_DELAYED_COMPRESS
 | |
|   };
 | |
|   void SchedulePaint(PaintType aType = PAINT_DEFAULT, bool aFrameChanged = true);
 | |
| 
 | |
|   // Similar to SchedulePaint() but without calling
 | |
|   // InvalidateRenderingObservers() for SVG.
 | |
|   void SchedulePaintWithoutInvalidatingObservers(
 | |
|     PaintType aType = PAINT_DEFAULT);
 | |
| 
 | |
|   /**
 | |
|    * Checks if the layer tree includes a dedicated layer for this
 | |
|    * frame/display item key pair, and invalidates at least aDamageRect
 | |
|    * area within that layer.
 | |
|    *
 | |
|    * If no layer is found, calls InvalidateFrame() instead.
 | |
|    *
 | |
|    * @param aDamageRect Area of the layer to invalidate.
 | |
|    * @param aFrameDamageRect If no layer is found, the area of the frame to
 | |
|    *                         invalidate. If null, the entire frame will be
 | |
|    *                         invalidated.
 | |
|    * @param aDisplayItemKey Display item type.
 | |
|    * @param aFlags UPDATE_IS_ASYNC : Will skip the invalidation
 | |
|    * if the found layer is being composited by a remote
 | |
|    * compositor.
 | |
|    * @return Layer, if found, nullptr otherwise.
 | |
|    */
 | |
|   enum {
 | |
|     UPDATE_IS_ASYNC = 1 << 0
 | |
|   };
 | |
|   Layer* InvalidateLayer(DisplayItemType aDisplayItemKey,
 | |
|                          const nsIntRect* aDamageRect = nullptr,
 | |
|                          const nsRect* aFrameDamageRect = nullptr,
 | |
|                          uint32_t aFlags = 0);
 | |
| 
 | |
|   void MarkNeedsDisplayItemRebuild();
 | |
| 
 | |
|   /**
 | |
|    * Returns a rect that encompasses everything that might be painted by
 | |
|    * this frame.  This includes this frame, all its descendant frames, this
 | |
|    * frame's outline, and descendant frames' outline, but does not include
 | |
|    * areas clipped out by the CSS "overflow" and "clip" properties.
 | |
|    *
 | |
|    * HasOverflowRects() (below) will return true when this overflow
 | |
|    * rect has been explicitly set, even if it matches mRect.
 | |
|    * XXX Note: because of a space optimization using the formula above,
 | |
|    * during reflow this function does not give accurate data if
 | |
|    * FinishAndStoreOverflow has been called but mRect hasn't yet been
 | |
|    * updated yet.  FIXME: This actually isn't true, but it should be.
 | |
|    *
 | |
|    * The visual overflow rect should NEVER be used for things that
 | |
|    * affect layout.  The scrollable overflow rect is permitted to affect
 | |
|    * layout.
 | |
|    *
 | |
|    * @return the rect relative to this frame's origin, but after
 | |
|    * CSS transforms have been applied (i.e. not really this frame's coordinate
 | |
|    * system, and may not contain the frame's border-box, e.g. if there
 | |
|    * is a CSS transform scaling it down)
 | |
|    */
 | |
|   nsRect GetVisualOverflowRect() const {
 | |
|     return GetOverflowRect(eVisualOverflow);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns a rect that encompasses the area of this frame that the
 | |
|    * user should be able to scroll to reach.  This is similar to
 | |
|    * GetVisualOverflowRect, but does not include outline or shadows, and
 | |
|    * may in the future include more margins than visual overflow does.
 | |
|    * It does not include areas clipped out by the CSS "overflow" and
 | |
|    * "clip" properties.
 | |
|    *
 | |
|    * HasOverflowRects() (below) will return true when this overflow
 | |
|    * rect has been explicitly set, even if it matches mRect.
 | |
|    * XXX Note: because of a space optimization using the formula above,
 | |
|    * during reflow this function does not give accurate data if
 | |
|    * FinishAndStoreOverflow has been called but mRect hasn't yet been
 | |
|    * updated yet.
 | |
|    *
 | |
|    * @return the rect relative to this frame's origin, but after
 | |
|    * CSS transforms have been applied (i.e. not really this frame's coordinate
 | |
|    * system, and may not contain the frame's border-box, e.g. if there
 | |
|    * is a CSS transform scaling it down)
 | |
|    */
 | |
|   nsRect GetScrollableOverflowRect() const {
 | |
|     return GetOverflowRect(eScrollableOverflow);
 | |
|   }
 | |
| 
 | |
|   nsRect GetOverflowRect(nsOverflowType aType) const;
 | |
| 
 | |
|   nsOverflowAreas GetOverflowAreas() const;
 | |
| 
 | |
|   /**
 | |
|    * Same as GetOverflowAreas, except in this frame's coordinate
 | |
|    * system (before transforms are applied).
 | |
|    *
 | |
|    * @return the overflow areas relative to this frame, before any CSS transforms have
 | |
|    * been applied, i.e. in this frame's coordinate system
 | |
|    */
 | |
|   nsOverflowAreas GetOverflowAreasRelativeToSelf() const;
 | |
| 
 | |
|   /**
 | |
|    * Same as GetScrollableOverflowRect, except relative to the parent
 | |
|    * frame.
 | |
|    *
 | |
|    * @return the rect relative to the parent frame, in the parent frame's
 | |
|    * coordinate system
 | |
|    */
 | |
|   nsRect GetScrollableOverflowRectRelativeToParent() const;
 | |
| 
 | |
|   /**
 | |
|    * Same as GetScrollableOverflowRect, except in this frame's coordinate
 | |
|    * system (before transforms are applied).
 | |
|    *
 | |
|    * @return the rect relative to this frame, before any CSS transforms have
 | |
|    * been applied, i.e. in this frame's coordinate system
 | |
|    */
 | |
|   nsRect GetScrollableOverflowRectRelativeToSelf() const;
 | |
| 
 | |
|   /**
 | |
|    * Like GetVisualOverflowRect, except in this frame's
 | |
|    * coordinate system (before transforms are applied).
 | |
|    *
 | |
|    * @return the rect relative to this frame, before any CSS transforms have
 | |
|    * been applied, i.e. in this frame's coordinate system
 | |
|    */
 | |
|   nsRect GetVisualOverflowRectRelativeToSelf() const;
 | |
| 
 | |
|   /**
 | |
|    * Same as GetVisualOverflowRect, except relative to the parent
 | |
|    * frame.
 | |
|    *
 | |
|    * @return the rect relative to the parent frame, in the parent frame's
 | |
|    * coordinate system
 | |
|    */
 | |
|   nsRect GetVisualOverflowRectRelativeToParent() const;
 | |
| 
 | |
|   /**
 | |
|    * Returns this frame's visual overflow rect as it would be before taking
 | |
|    * account of SVG effects or transforms. The rect returned is relative to
 | |
|    * this frame.
 | |
|    */
 | |
|   nsRect GetPreEffectsVisualOverflowRect() const;
 | |
| 
 | |
|   /**
 | |
|    * Store the overflow area in the frame's mOverflow.mVisualDeltas
 | |
|    * fields or as a frame property in the frame manager so that it can
 | |
|    * be retrieved later without reflowing the frame. Returns true if either of
 | |
|    * the overflow areas changed.
 | |
|    */
 | |
|   bool FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
 | |
|                               nsSize aNewSize, nsSize* aOldSize = nullptr,
 | |
|                               const nsStyleDisplay* aStyleDisplay = nullptr);
 | |
| 
 | |
|   bool FinishAndStoreOverflow(ReflowOutput* aMetrics,
 | |
|                               const nsStyleDisplay* aStyleDisplay = nullptr) {
 | |
|     return FinishAndStoreOverflow(aMetrics->mOverflowAreas,
 | |
|                                   nsSize(aMetrics->Width(), aMetrics->Height()),
 | |
|                                   nullptr, aStyleDisplay);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns whether the frame has an overflow rect that is different from
 | |
|    * its border-box.
 | |
|    */
 | |
|   bool HasOverflowAreas() const {
 | |
|     return mOverflow.mType != NS_FRAME_OVERFLOW_NONE;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Removes any stored overflow rects (visual and scrollable) from the frame.
 | |
|    * Returns true if the overflow changed.
 | |
|    */
 | |
|   bool ClearOverflowRects();
 | |
| 
 | |
|   /**
 | |
|    * Determine whether borders, padding, margins etc should NOT be applied
 | |
|    * on certain sides of the frame.
 | |
|    * @see mozilla::Sides in gfx/2d/BaseMargin.h
 | |
|    * @see mozilla::LogicalSides in layout/generic/WritingModes.h
 | |
|    *
 | |
|    * @note (See also bug 743402, comment 11) GetSkipSides() checks to see
 | |
|    *       if this frame has a previous or next continuation to determine
 | |
|    *       if a side should be skipped.
 | |
|    *       Unfortunately, this only works after reflow has been completed. In
 | |
|    *       lieu of this, during reflow, an ReflowInput parameter can be
 | |
|    *       passed in, indicating that it should be used to determine if sides
 | |
|    *       should be skipped during reflow.
 | |
|    */
 | |
|   Sides GetSkipSides(const ReflowInput* aReflowInput = nullptr) const;
 | |
|   virtual LogicalSides
 | |
|   GetLogicalSkipSides(const ReflowInput* aReflowInput = nullptr) const {
 | |
|     return LogicalSides();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * @returns true if this frame is selected.
 | |
|    */
 | |
|   bool IsSelected() const;
 | |
| 
 | |
|   /**
 | |
|    *  called to discover where this frame, or a parent frame has user-select style
 | |
|    *  applied, which affects that way that it is selected.
 | |
|    *
 | |
|    *  @param aSelectStyle  out param. Returns the type of selection style found
 | |
|    *                        (using values defined in nsStyleConsts.h).
 | |
|    *
 | |
|    *  @return Whether the frame can be selected (i.e. is not affected by
 | |
|    *          user-select: none)
 | |
|    */
 | |
|   bool IsSelectable(mozilla::StyleUserSelect* aSelectStyle) const;
 | |
| 
 | |
|   /**
 | |
|    *  Called to retrieve the SelectionController associated with the frame.
 | |
|    *  @param aSelCon will contain the selection controller associated with
 | |
|    *  the frame.
 | |
|    */
 | |
|   virtual nsresult  GetSelectionController(nsPresContext *aPresContext, nsISelectionController **aSelCon) = 0;
 | |
| 
 | |
|   /**
 | |
|    *  Call to get nsFrameSelection for this frame.
 | |
|    */
 | |
|   already_AddRefed<nsFrameSelection> GetFrameSelection();
 | |
| 
 | |
|   /**
 | |
|    * GetConstFrameSelection returns an object which methods are safe to use for
 | |
|    * example in nsIFrame code.
 | |
|    */
 | |
|   const nsFrameSelection* GetConstFrameSelection() const;
 | |
| 
 | |
|   /**
 | |
|    *  called to find the previous/next character, word, or line  returns the actual
 | |
|    *  nsIFrame and the frame offset.  THIS DOES NOT CHANGE SELECTION STATE
 | |
|    *  uses frame's begin selection state to start. if no selection on this frame will
 | |
|    *  return NS_ERROR_FAILURE
 | |
|    *  @param aPOS is defined in nsFrameSelection
 | |
|    */
 | |
|   virtual nsresult PeekOffset(nsPeekOffsetStruct *aPos);
 | |
| 
 | |
|   /**
 | |
|    *  called to find the previous/next non-anonymous selectable leaf frame.
 | |
|    *  @param aDirection [in] the direction to move in (eDirPrevious or eDirNext)
 | |
|    *  @param aVisual [in] whether bidi caret behavior is visual (true) or logical (false)
 | |
|    *  @param aJumpLines [in] whether to allow jumping across line boundaries
 | |
|    *  @param aScrollViewStop [in] whether to stop when reaching a scroll frame boundary
 | |
|    *  @param aOutFrame [out] the previous/next selectable leaf frame
 | |
|    *  @param aOutOffset [out] 0 indicates that we arrived at the beginning of the output frame;
 | |
|    *                          -1 indicates that we arrived at its end.
 | |
|    *  @param aOutJumpedLine [out] whether this frame and the returned frame are on different lines
 | |
|    *  @param aOutMovedOverNonSelectableText [out] whether we jumped over a non-selectable
 | |
|    *                                              frame during the search
 | |
|    */
 | |
|   nsresult GetFrameFromDirection(nsDirection aDirection, bool aVisual,
 | |
|                                  bool aJumpLines, bool aScrollViewStop,
 | |
|                                  nsIFrame** aOutFrame, int32_t* aOutOffset,
 | |
|                                  bool* aOutJumpedLine, bool* aOutMovedOverNonSelectableText);
 | |
| 
 | |
|   /**
 | |
|    *  called to see if the children of the frame are visible from indexstart to index end.
 | |
|    *  this does not change any state. returns true only if the indexes are valid and any of
 | |
|    *  the children are visible.  for textframes this index is the character index.
 | |
|    *  if aStart = aEnd result will be false
 | |
|    *  @param aStart start index of first child from 0-N (number of children)
 | |
|    *  @param aEnd   end index of last child from 0-N
 | |
|    *  @param aRecurse should this frame talk to siblings to get to the contents other children?
 | |
|    *  @param aFinished did this frame have the aEndIndex? or is there more work to do
 | |
|    *  @param _retval  return value true or false. false = range is not rendered.
 | |
|    */
 | |
|   virtual nsresult CheckVisibility(nsPresContext* aContext, int32_t aStartIndex, int32_t aEndIndex, bool aRecurse, bool *aFinished, bool *_retval)=0;
 | |
| 
 | |
|   /**
 | |
|    * Called to tell a frame that one of its child frames is dirty (i.e.,
 | |
|    * has the NS_FRAME_IS_DIRTY *or* NS_FRAME_HAS_DIRTY_CHILDREN bit
 | |
|    * set).  This should always set the NS_FRAME_HAS_DIRTY_CHILDREN on
 | |
|    * the frame, and may do other work.
 | |
|    */
 | |
|   virtual void ChildIsDirty(nsIFrame* aChild) = 0;
 | |
| 
 | |
|   /**
 | |
|    * Called to retrieve this frame's accessible.
 | |
|    * If this frame implements Accessibility return a valid accessible
 | |
|    * If not return NS_ERROR_NOT_IMPLEMENTED.
 | |
|    * Note: Accessible must be refcountable. Do not implement directly on your frame
 | |
|    * Use a mediatior of some kind.
 | |
|    */
 | |
| #ifdef ACCESSIBILITY
 | |
|   virtual mozilla::a11y::AccType AccessibleType() = 0;
 | |
| #endif
 | |
| 
 | |
|   /**
 | |
|    * Get the frame whose style should be the parent of this frame's style (i.e.,
 | |
|    * provide the parent style).
 | |
|    *
 | |
|    * This frame must either be an ancestor of this frame or a child.  If
 | |
|    * this returns a child frame, then the child frame must be sure to
 | |
|    * return a grandparent or higher!  Furthermore, if a child frame is
 | |
|    * returned it must have the same GetContent() as this frame.
 | |
|    *
 | |
|    * @param aProviderFrame (out) the frame associated with the returned value
 | |
|    *     or nullptr if the style is for display:contents content.
 | |
|    * @return The style that should be the parent of this frame's style. Null is
 | |
|    *         permitted, and means that this frame's style should be the root of
 | |
|    *         the style tree.
 | |
|    */
 | |
|   virtual ComputedStyle* GetParentComputedStyle(nsIFrame** aProviderFrame) const = 0;
 | |
| 
 | |
|   /**
 | |
|    * Called by RestyleManager to update the style of anonymous boxes
 | |
|    * directly associated with this frame.
 | |
|    *
 | |
|    * The passed-in ServoRestyleState can be used to create new ComputedStyles as
 | |
|    * needed, as well as posting changes to the change list.
 | |
|    *
 | |
|    * It's guaranteed to already have a change in it for this frame and this
 | |
|    * frame's content.
 | |
|    *
 | |
|    * This function will be called after this frame's style has already been
 | |
|    * updated.  This function will only be called on frames which have the
 | |
|    * NS_FRAME_OWNS_ANON_BOXES bit set.
 | |
|    */
 | |
|   void UpdateStyleOfOwnedAnonBoxes(mozilla::ServoRestyleState& aRestyleState)
 | |
|   {
 | |
|     if (GetStateBits() & NS_FRAME_OWNS_ANON_BOXES) {
 | |
|       DoUpdateStyleOfOwnedAnonBoxes(aRestyleState);
 | |
|     }
 | |
|   }
 | |
| 
 | |
| protected:
 | |
|   // This does the actual work of UpdateStyleOfOwnedAnonBoxes.  It calls
 | |
|   // AppendDirectlyOwnedAnonBoxes to find all of the anonymous boxes
 | |
|   // owned by this frame, and then updates styles on each of them.
 | |
|   void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoRestyleState& aRestyleState);
 | |
| 
 | |
|   // A helper for DoUpdateStyleOfOwnedAnonBoxes for the specific case
 | |
|   // of the owned anon box being a child of this frame.
 | |
|   void UpdateStyleOfChildAnonBox(nsIFrame* aChildFrame,
 | |
|                                  mozilla::ServoRestyleState& aRestyleState);
 | |
| 
 | |
|   // Allow ServoRestyleState to call UpdateStyleOfChildAnonBox.
 | |
|   friend class mozilla::ServoRestyleState;
 | |
| 
 | |
| public:
 | |
|   // A helper both for UpdateStyleOfChildAnonBox, and to update frame-backed
 | |
|   // pseudo-elements in RestyleManager.
 | |
|   //
 | |
|   // This gets a ComputedStyle that will be the new style for `aChildFrame`, and
 | |
|   // takes care of updating it, calling CalcStyleDifference, and adding to the
 | |
|   // change list as appropriate.
 | |
|   //
 | |
|   // If aContinuationComputedStyle is not Nothing, it should be used for
 | |
|   // continuations instead of aNewComputedStyle.  In either case, changehints
 | |
|   // are only computed based on aNewComputedStyle.
 | |
|   //
 | |
|   // Returns the generated change hint for the frame.
 | |
|   static nsChangeHint UpdateStyleOfOwnedChildFrame(
 | |
|     nsIFrame* aChildFrame,
 | |
|     ComputedStyle* aNewComputedStyle,
 | |
|     mozilla::ServoRestyleState& aRestyleState,
 | |
|     const Maybe<ComputedStyle*>& aContinuationComputedStyle = Nothing());
 | |
| 
 | |
|   struct OwnedAnonBox
 | |
|   {
 | |
|     typedef void (*UpdateStyleFn)(nsIFrame* aOwningFrame,
 | |
|                                   nsIFrame* aAnonBox,
 | |
|                                   mozilla::ServoRestyleState& aRestyleState);
 | |
| 
 | |
|     explicit OwnedAnonBox(nsIFrame* aAnonBoxFrame,
 | |
|                           UpdateStyleFn aUpdateStyleFn = nullptr)
 | |
|       : mAnonBoxFrame(aAnonBoxFrame)
 | |
|       , mUpdateStyleFn(aUpdateStyleFn)
 | |
|     {}
 | |
| 
 | |
|     nsIFrame* mAnonBoxFrame;
 | |
|     UpdateStyleFn mUpdateStyleFn;
 | |
|   };
 | |
| 
 | |
|   /**
 | |
|    * Appends information about all of the anonymous boxes owned by this frame,
 | |
|    * including other anonymous boxes owned by those which this frame owns
 | |
|    * directly.
 | |
|    */
 | |
|   void AppendOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) {
 | |
|     if (GetStateBits() & NS_FRAME_OWNS_ANON_BOXES) {
 | |
|       if (IsInlineFrame()) {
 | |
|         // See comment in nsIFrame::DoUpdateStyleOfOwnedAnonBoxes for why
 | |
|         // we skip nsInlineFrames.
 | |
|         return;
 | |
|       }
 | |
|       DoAppendOwnedAnonBoxes(aResult);
 | |
|     }
 | |
|   }
 | |
| 
 | |
| protected:
 | |
|   // This does the actual work of AppendOwnedAnonBoxes.
 | |
|   void DoAppendOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult);
 | |
| 
 | |
| public:
 | |
|   /**
 | |
|    * Hook subclasses can override to return their owned anonymous boxes.
 | |
|    *
 | |
|    * This function only appends anonymous boxes that are directly owned by
 | |
|    * this frame, i.e. direct children or (for certain frames) a wrapper
 | |
|    * parent, unlike AppendOwnedAnonBoxes, which will append all anonymous
 | |
|    * boxes transitively owned by this frame.
 | |
|    */
 | |
|   virtual void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult);
 | |
| 
 | |
|   /**
 | |
|    * Determines whether a frame is visible for painting;
 | |
|    * taking into account whether it is painting a selection or printing.
 | |
|    */
 | |
|   bool IsVisibleForPainting(nsDisplayListBuilder* aBuilder);
 | |
|   /**
 | |
|    * Determines whether a frame is visible for painting or collapsed;
 | |
|    * taking into account whether it is painting a selection or printing,
 | |
|    */
 | |
|   bool IsVisibleOrCollapsedForPainting(nsDisplayListBuilder* aBuilder);
 | |
|   /**
 | |
|    * As above, but slower because we have to recompute some stuff that
 | |
|    * aBuilder already has.
 | |
|    */
 | |
|   bool IsVisibleForPainting();
 | |
|   /**
 | |
|    * Check whether this frame is visible in the current selection. Returns
 | |
|    * true if there is no current selection.
 | |
|    */
 | |
|   bool IsVisibleInSelection(nsDisplayListBuilder* aBuilder);
 | |
| 
 | |
|   /**
 | |
|    * Overridable function to determine whether this frame should be considered
 | |
|    * "in" the given non-null aSelection for visibility purposes.
 | |
|    */
 | |
|   virtual bool IsVisibleInSelection(mozilla::dom::Selection* aSelection);
 | |
| 
 | |
|   /**
 | |
|    * Determines if this frame is a stacking context.
 | |
|    *
 | |
|    * @param aIsPositioned The precomputed result of IsAbsPosContainingBlock
 | |
|    * on the StyleDisplay().
 | |
|    */
 | |
|   bool IsStackingContext(mozilla::EffectSet* aEffectSet,
 | |
|                          const nsStyleDisplay* aStyleDisplay,
 | |
|                          const nsStylePosition* aStylePosition,
 | |
|                          const nsStyleEffects* aStyleEffects,
 | |
|                          bool aIsPositioned);
 | |
|   bool IsStackingContext();
 | |
| 
 | |
|   virtual bool HonorPrintBackgroundSettings() { return true; }
 | |
| 
 | |
|   /**
 | |
|    * Determine whether the frame is logically empty, which is roughly
 | |
|    * whether the layout would be the same whether or not the frame is
 | |
|    * present.  Placeholder frames should return true.  Block frames
 | |
|    * should be considered empty whenever margins collapse through them,
 | |
|    * even though those margins are relevant.  Text frames containing
 | |
|    * only whitespace that does not contribute to the height of the line
 | |
|    * should return true.
 | |
|    */
 | |
|   virtual bool IsEmpty() = 0;
 | |
|   /**
 | |
|    * Return the same as IsEmpty(). This may only be called after the frame
 | |
|    * has been reflowed and before any further style or content changes.
 | |
|    */
 | |
|   virtual bool CachedIsEmpty();
 | |
|   /**
 | |
|    * Determine whether the frame is logically empty, assuming that all
 | |
|    * its children are empty.
 | |
|    */
 | |
|   virtual bool IsSelfEmpty() = 0;
 | |
| 
 | |
|   /**
 | |
|    * IsGeneratedContentFrame returns whether a frame corresponds to
 | |
|    * generated content
 | |
|    *
 | |
|    * @return whether the frame correspods to generated content
 | |
|    */
 | |
|   bool IsGeneratedContentFrame() const {
 | |
|     return (mState & NS_FRAME_GENERATED_CONTENT) != 0;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * IsPseudoFrame returns whether a frame is a pseudo frame (eg an
 | |
|    * anonymous table-row frame created for a CSS table-cell without an
 | |
|    * enclosing table-row.
 | |
|    *
 | |
|    * @param aParentContent the content node corresponding to the parent frame
 | |
|    * @return whether the frame is a pseudo frame
 | |
|    */
 | |
|   bool IsPseudoFrame(const nsIContent* aParentContent) {
 | |
|     return mContent == aParentContent;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Support for reading and writing properties on the frame.
 | |
|    * These call through to the frame's FrameProperties object, if it
 | |
|    * exists, but avoid creating it if no property is ever set.
 | |
|    */
 | |
|   template<typename T>
 | |
|   FrameProperties::PropertyType<T>
 | |
|   GetProperty(FrameProperties::Descriptor<T> aProperty,
 | |
|               bool* aFoundResult = nullptr) const
 | |
|   {
 | |
|     return mProperties.Get(aProperty, aFoundResult);
 | |
|   }
 | |
| 
 | |
|   template<typename T>
 | |
|   bool HasProperty(FrameProperties::Descriptor<T> aProperty) const
 | |
|   {
 | |
|     return mProperties.Has(aProperty);
 | |
|   }
 | |
| 
 | |
|   // Add a property, or update an existing property for the given descriptor.
 | |
|   template<typename T>
 | |
|   void SetProperty(FrameProperties::Descriptor<T> aProperty,
 | |
|                    FrameProperties::PropertyType<T> aValue)
 | |
|   {
 | |
|     mProperties.Set(aProperty, aValue, this);
 | |
|   }
 | |
| 
 | |
|   // Unconditionally add a property; use ONLY if the descriptor is known
 | |
|   // to NOT already be present.
 | |
|   template<typename T>
 | |
|   void AddProperty(FrameProperties::Descriptor<T> aProperty,
 | |
|                    FrameProperties::PropertyType<T> aValue)
 | |
|   {
 | |
|     mProperties.Add(aProperty, aValue);
 | |
|   }
 | |
| 
 | |
|   template<typename T>
 | |
|   FrameProperties::PropertyType<T>
 | |
|   RemoveProperty(FrameProperties::Descriptor<T> aProperty,
 | |
|                  bool* aFoundResult = nullptr)
 | |
|   {
 | |
|     return mProperties.Remove(aProperty, aFoundResult);
 | |
|   }
 | |
| 
 | |
|   template<typename T>
 | |
|   void DeleteProperty(FrameProperties::Descriptor<T> aProperty)
 | |
|   {
 | |
|     mProperties.Delete(aProperty, this);
 | |
|   }
 | |
| 
 | |
|   void DeleteAllProperties()
 | |
|   {
 | |
|     mProperties.DeleteAll(this);
 | |
|   }
 | |
| 
 | |
|   // nsIFrames themselves are in the nsPresArena, and so are not measured here.
 | |
|   // Instead, this measures heap-allocated things hanging off the nsIFrame, and
 | |
|   // likewise for its descendants.
 | |
|   void AddSizeOfExcludingThisForTree(nsWindowSizes& aWindowSizes) const;
 | |
| 
 | |
|   /**
 | |
|    * Return true if and only if this frame obeys visibility:hidden.
 | |
|    * if it does not, then nsContainerFrame will hide its view even though
 | |
|    * this means children can't be made visible again.
 | |
|    */
 | |
|   virtual bool SupportsVisibilityHidden() { return true; }
 | |
| 
 | |
|   /**
 | |
|    * Returns the clip rect set via the 'clip' property, if the 'clip' property
 | |
|    * applies to this frame; otherwise returns Nothing(). The 'clip' property
 | |
|    * applies to HTML frames if they are absolutely positioned. The 'clip'
 | |
|    * property applies to SVG frames regardless of the value of the 'position'
 | |
|    * property.
 | |
|    *
 | |
|    * The coordinates of the returned rectangle are relative to this frame's
 | |
|    * origin.
 | |
|    */
 | |
|   Maybe<nsRect> GetClipPropClipRect(const nsStyleDisplay* aDisp,
 | |
|                                     const nsStyleEffects* aEffects,
 | |
|                                     const nsSize& aSize) const;
 | |
| 
 | |
|   /**
 | |
|    * Check if this frame is focusable and in the current tab order.
 | |
|    * Tabbable is indicated by a nonnegative tabindex & is a subset of focusable.
 | |
|    * For example, only the selected radio button in a group is in the
 | |
|    * tab order, unless the radio group has no selection in which case
 | |
|    * all of the visible, non-disabled radio buttons in the group are
 | |
|    * in the tab order. On the other hand, all of the visible, non-disabled
 | |
|    * radio buttons are always focusable via clicking or script.
 | |
|    * Also, depending on the pref accessibility.tabfocus some widgets may be
 | |
|    * focusable but removed from the tab order. This is the default on
 | |
|    * Mac OS X, where fewer items are focusable.
 | |
|    * @param  [in, optional] aTabIndex the computed tab index
 | |
|    *         < 0 if not tabbable
 | |
|    *         == 0 if in normal tab order
 | |
|    *         > 0 can be tabbed to in the order specified by this value
 | |
|    * @param  [in, optional] aWithMouse, is this focus query for mouse clicking
 | |
|    * @return whether the frame is focusable via mouse, kbd or script.
 | |
|    */
 | |
|   virtual bool IsFocusable(int32_t *aTabIndex = nullptr, bool aWithMouse = false);
 | |
| 
 | |
|   // BOX LAYOUT METHODS
 | |
|   // These methods have been migrated from nsIBox and are in the process of
 | |
|   // being refactored. DO NOT USE OUTSIDE OF XUL.
 | |
|   bool IsXULBoxFrame() const
 | |
|   {
 | |
|     return IsFrameOfType(nsIFrame::eXULBox);
 | |
|   }
 | |
| 
 | |
|   enum Halignment {
 | |
|     hAlign_Left,
 | |
|     hAlign_Right,
 | |
|     hAlign_Center
 | |
|   };
 | |
| 
 | |
|   enum Valignment {
 | |
|     vAlign_Top,
 | |
|     vAlign_Middle,
 | |
|     vAlign_BaseLine,
 | |
|     vAlign_Bottom
 | |
|   };
 | |
| 
 | |
|   /**
 | |
|    * This calculates the minimum size required for a box based on its state
 | |
|    * @param[in] aBoxLayoutState The desired state to calculate for
 | |
|    * @return The minimum size
 | |
|    */
 | |
|   virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) = 0;
 | |
| 
 | |
|   /**
 | |
|    * This calculates the preferred size of a box based on its state
 | |
|    * @param[in] aBoxLayoutState The desired state to calculate for
 | |
|    * @return The preferred size
 | |
|    */
 | |
|   virtual nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) = 0;
 | |
| 
 | |
|   /**
 | |
|    * This calculates the maximum size for a box based on its state
 | |
|    * @param[in] aBoxLayoutState The desired state to calculate for
 | |
|    * @return The maximum size
 | |
|    */
 | |
|   virtual nsSize GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState) = 0;
 | |
| 
 | |
|   /**
 | |
|    * This returns the minimum size for the scroll area if this frame is
 | |
|    * being scrolled. Usually it's (0,0).
 | |
|    */
 | |
|   virtual nsSize GetXULMinSizeForScrollArea(nsBoxLayoutState& aBoxLayoutState) = 0;
 | |
| 
 | |
|   // Implemented in nsBox, used in nsBoxFrame
 | |
|   uint32_t GetXULOrdinal();
 | |
| 
 | |
|   virtual nscoord GetXULFlex() = 0;
 | |
|   virtual nscoord GetXULBoxAscent(nsBoxLayoutState& aBoxLayoutState) = 0;
 | |
|   virtual bool IsXULCollapsed() = 0;
 | |
|   // This does not alter the overflow area. If the caller is changing
 | |
|   // the box size, the caller is responsible for updating the overflow
 | |
|   // area. It's enough to just call XULLayout or SyncLayout on the
 | |
|   // box. You can pass true to aRemoveOverflowArea as a
 | |
|   // convenience.
 | |
|   virtual void SetXULBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRect,
 | |
|                             bool aRemoveOverflowAreas = false) = 0;
 | |
|   nsresult XULLayout(nsBoxLayoutState& aBoxLayoutState);
 | |
|   // Box methods.  Note that these do NOT just get the CSS border, padding,
 | |
|   // etc.  They also talk to nsITheme.
 | |
|   virtual nsresult GetXULBorderAndPadding(nsMargin& aBorderAndPadding);
 | |
|   virtual nsresult GetXULBorder(nsMargin& aBorder)=0;
 | |
|   virtual nsresult GetXULPadding(nsMargin& aBorderAndPadding)=0;
 | |
|   virtual nsresult GetXULMargin(nsMargin& aMargin)=0;
 | |
|   virtual void SetXULLayoutManager(nsBoxLayout* aLayout) { }
 | |
|   virtual nsBoxLayout* GetXULLayoutManager() { return nullptr; }
 | |
|   nsresult GetXULClientRect(nsRect& aContentRect);
 | |
| 
 | |
|   virtual uint32_t GetXULLayoutFlags()
 | |
|   { return 0; }
 | |
| 
 | |
|   // For nsSprocketLayout
 | |
|   virtual Valignment GetXULVAlign() const = 0;
 | |
|   virtual Halignment GetXULHAlign() const = 0;
 | |
| 
 | |
|   bool IsXULHorizontal() const { return (mState & NS_STATE_IS_HORIZONTAL) != 0; }
 | |
|   bool IsXULNormalDirection() const { return (mState & NS_STATE_IS_DIRECTION_NORMAL) != 0; }
 | |
| 
 | |
|   nsresult XULRedraw(nsBoxLayoutState& aState);
 | |
|   virtual nsresult XULRelayoutChildAtOrdinal(nsIFrame* aChild)=0;
 | |
| 
 | |
|   static bool AddXULPrefSize(nsIFrame* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet);
 | |
|   static bool AddXULMinSize(nsBoxLayoutState& aState, nsIFrame* aBox,
 | |
|                             nsSize& aSize, bool& aWidth, bool& aHeightSet);
 | |
|   static bool AddXULMaxSize(nsIFrame* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet);
 | |
|   static bool AddXULFlex(nsIFrame* aBox, nscoord& aFlex);
 | |
| 
 | |
|   // END OF BOX LAYOUT METHODS
 | |
|   // The above methods have been migrated from nsIBox and are in the process of
 | |
|   // being refactored. DO NOT USE OUTSIDE OF XUL.
 | |
| 
 | |
|   /**
 | |
|    * @return true if this text frame ends with a newline character.  It
 | |
|    * should return false if this is not a text frame.
 | |
|    */
 | |
|   virtual bool HasSignificantTerminalNewline() const;
 | |
| 
 | |
|   struct CaretPosition {
 | |
|     CaretPosition();
 | |
|     ~CaretPosition();
 | |
| 
 | |
|     nsCOMPtr<nsIContent> mResultContent;
 | |
|     int32_t              mContentOffset;
 | |
|   };
 | |
| 
 | |
|   /**
 | |
|    * gets the first or last possible caret position within the frame
 | |
|    *
 | |
|    * @param  [in] aStart
 | |
|    *         true  for getting the first possible caret position
 | |
|    *         false for getting the last possible caret position
 | |
|    * @return The caret position in a CaretPosition.
 | |
|    *         the returned value is a 'best effort' in case errors
 | |
|    *         are encountered rummaging through the frame.
 | |
|    */
 | |
|   CaretPosition GetExtremeCaretPosition(bool aStart);
 | |
| 
 | |
|   /**
 | |
|    * Get a line iterator for this frame, if supported.
 | |
|    *
 | |
|    * @return nullptr if no line iterator is supported.
 | |
|    * @note dispose the line iterator using nsILineIterator::DisposeLineIterator
 | |
|    */
 | |
|   virtual nsILineIterator* GetLineIterator() = 0;
 | |
| 
 | |
|   /**
 | |
|    * If this frame is a next-in-flow, and its prev-in-flow has something on its
 | |
|    * overflow list, pull those frames into the child list of this one.
 | |
|    */
 | |
|   virtual void PullOverflowsFromPrevInFlow() {}
 | |
| 
 | |
|   /**
 | |
|    * Clear the list of child PresShells generated during the last paint
 | |
|    * so that we can begin generating a new one.
 | |
|    */
 | |
|   void ClearPresShellsFromLastPaint() {
 | |
|     PaintedPresShellList()->Clear();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Flag a child PresShell as painted so that it will get its paint count
 | |
|    * incremented during empty transactions.
 | |
|    */
 | |
|   void AddPaintedPresShell(nsIPresShell* shell) {
 | |
|     PaintedPresShellList()->AppendElement(do_GetWeakReference(shell));
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Increment the paint count of all child PresShells that were painted during
 | |
|    * the last repaint.
 | |
|    */
 | |
|   void UpdatePaintCountForPaintedPresShells() {
 | |
|     for (nsWeakPtr& item : *PaintedPresShellList()) {
 | |
|       nsCOMPtr<nsIPresShell> shell = do_QueryReferent(item);
 | |
|       if (shell) {
 | |
|         shell->IncrementPaintCount();
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * @return true if we painted @aShell during the last repaint.
 | |
|    */
 | |
|   bool DidPaintPresShell(nsIPresShell* aShell)
 | |
|   {
 | |
|     for (nsWeakPtr& item : *PaintedPresShellList()) {
 | |
|       nsCOMPtr<nsIPresShell> shell = do_QueryReferent(item);
 | |
|       if (shell == aShell) {
 | |
|         return true;
 | |
|       }
 | |
|     }
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Accessors for the absolute containing block.
 | |
|    */
 | |
|   bool IsAbsoluteContainer() const { return !!(mState & NS_FRAME_HAS_ABSPOS_CHILDREN); }
 | |
|   bool HasAbsolutelyPositionedChildren() const;
 | |
|   nsAbsoluteContainingBlock* GetAbsoluteContainingBlock() const;
 | |
|   void MarkAsAbsoluteContainingBlock();
 | |
|   void MarkAsNotAbsoluteContainingBlock();
 | |
|   // Child frame types override this function to select their own child list name
 | |
|   virtual mozilla::layout::FrameChildListID GetAbsoluteListID() const { return kAbsoluteList; }
 | |
| 
 | |
|   // Checks if we (or any of our descendents) have NS_FRAME_PAINTED_THEBES set, and
 | |
|   // clears this bit if so.
 | |
|   bool CheckAndClearPaintedState();
 | |
| 
 | |
|   // Checks if we (or any of our descendents) have mBuiltDisplayList set, and
 | |
|   // clears this bit if so.
 | |
|   bool CheckAndClearDisplayListState();
 | |
| 
 | |
|   // CSS visibility just doesn't cut it because it doesn't inherit through
 | |
|   // documents. Also if this frame is in a hidden card of a deck then it isn't
 | |
|   // visible either and that isn't expressed using CSS visibility. Also if it
 | |
|   // is in a hidden view (there are a few cases left and they are hopefully
 | |
|   // going away soon).
 | |
|   // If the VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY flag is passed then we
 | |
|   // ignore the chrome/content boundary, otherwise we stop looking when we
 | |
|   // reach it.
 | |
|   enum {
 | |
|     VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY = 0x01
 | |
|   };
 | |
|   bool IsVisibleConsideringAncestors(uint32_t aFlags = 0) const;
 | |
| 
 | |
|   struct FrameWithDistance
 | |
|   {
 | |
|     nsIFrame* mFrame;
 | |
|     nscoord mXDistance;
 | |
|     nscoord mYDistance;
 | |
|   };
 | |
| 
 | |
|   /**
 | |
|    * Finds a frame that is closer to a specified point than a current
 | |
|    * distance.  Distance is measured as for text selection -- a closer x
 | |
|    * distance beats a closer y distance.
 | |
|    *
 | |
|    * Normally, this function will only check the distance between this
 | |
|    * frame's rectangle and the specified point.  SVGTextFrame overrides
 | |
|    * this so that it can manage all of its descendant frames and take
 | |
|    * into account any SVG text layout.
 | |
|    *
 | |
|    * If aPoint is closer to this frame's rectangle than aCurrentBestFrame
 | |
|    * indicates, then aCurrentBestFrame is updated with the distance between
 | |
|    * aPoint and this frame's rectangle, and with a pointer to this frame.
 | |
|    * If aPoint is not closer, then aCurrentBestFrame is left unchanged.
 | |
|    *
 | |
|    * @param aPoint The point to check for its distance to this frame.
 | |
|    * @param aCurrentBestFrame Pointer to a struct that will be updated with
 | |
|    *   a pointer to this frame and its distance to aPoint, if this frame
 | |
|    *   is indeed closer than the current distance in aCurrentBestFrame.
 | |
|    */
 | |
|   virtual void FindCloserFrameForSelection(const nsPoint& aPoint,
 | |
|                                            FrameWithDistance* aCurrentBestFrame);
 | |
| 
 | |
|   /**
 | |
|    * Is this a flex item? (i.e. a non-abs-pos child of a flex container)
 | |
|    */
 | |
|   inline bool IsFlexItem() const;
 | |
|   /**
 | |
|    * Is this a flex or grid item? (i.e. a non-abs-pos child of a flex/grid container)
 | |
|    */
 | |
|   inline bool IsFlexOrGridItem() const;
 | |
|   inline bool IsFlexOrGridContainer() const;
 | |
| 
 | |
|   /**
 | |
|    * @return true if this frame is used as a table caption.
 | |
|    */
 | |
|   inline bool IsTableCaption() const;
 | |
| 
 | |
|   inline bool IsBlockInside() const;
 | |
|   inline bool IsBlockOutside() const;
 | |
|   inline bool IsInlineOutside() const;
 | |
|   inline mozilla::StyleDisplay GetDisplay() const;
 | |
|   inline bool IsFloating() const;
 | |
|   inline bool IsAbsPosContainingBlock() const;
 | |
|   inline bool IsFixedPosContainingBlock() const;
 | |
|   inline bool IsRelativelyPositioned() const;
 | |
|   inline bool IsAbsolutelyPositioned(const nsStyleDisplay* aStyleDisplay = nullptr) const;
 | |
| 
 | |
|   /**
 | |
|    * Returns the vertical-align value to be used for layout, if it is one
 | |
|    * of the enumerated values.  If this is an SVG text frame, it returns a value
 | |
|    * that corresponds to the value of dominant-baseline.  If the
 | |
|    * vertical-align property has length or percentage value, this returns
 | |
|    * eInvalidVerticalAlign.
 | |
|    */
 | |
|   uint8_t VerticalAlignEnum() const;
 | |
|   enum { eInvalidVerticalAlign = 0xFF };
 | |
| 
 | |
|   void CreateOwnLayerIfNeeded(nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
 | |
|                               bool* aCreatedContainerItem = nullptr);
 | |
| 
 | |
|   /**
 | |
|    * Adds the NS_FRAME_IN_POPUP state bit to aFrame, and
 | |
|    * all descendant frames (including cross-doc ones).
 | |
|    */
 | |
|   static void AddInPopupStateBitToDescendants(nsIFrame* aFrame);
 | |
|   /**
 | |
|    * Removes the NS_FRAME_IN_POPUP state bit from aFrame and
 | |
|    * all descendant frames (including cross-doc ones), unless
 | |
|    * the frame is a popup itself.
 | |
|    */
 | |
|   static void RemoveInPopupStateBitFromDescendants(nsIFrame* aFrame);
 | |
| 
 | |
|   /**
 | |
|    * Sorts the given nsFrameList, so that for every two adjacent frames in the
 | |
|    * list, the former is less than or equal to the latter, according to the
 | |
|    * templated IsLessThanOrEqual method.
 | |
|    *
 | |
|    * Note: this method uses a stable merge-sort algorithm.
 | |
|    */
 | |
|   template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
 | |
|   static void SortFrameList(nsFrameList& aFrameList);
 | |
| 
 | |
|   /**
 | |
|    * Returns true if the given frame list is already sorted, according to the
 | |
|    * templated IsLessThanOrEqual function.
 | |
|    */
 | |
|   template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
 | |
|   static bool IsFrameListSorted(nsFrameList& aFrameList);
 | |
| 
 | |
|   /**
 | |
|    * Return true if aFrame is in an {ib} split and is NOT one of the
 | |
|    * continuations of the first inline in it.
 | |
|    */
 | |
|   bool FrameIsNonFirstInIBSplit() const {
 | |
|     return (GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) &&
 | |
|       FirstContinuation()->GetProperty(nsIFrame::IBSplitPrevSibling());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return true if aFrame is in an {ib} split and is NOT one of the
 | |
|    * continuations of the last inline in it.
 | |
|    */
 | |
|   bool FrameIsNonLastInIBSplit() const {
 | |
|     return (GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) &&
 | |
|       FirstContinuation()->GetProperty(nsIFrame::IBSplitSibling());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return whether this is a frame whose width is used when computing
 | |
|    * the font size inflation of its descendants.
 | |
|    */
 | |
|   bool IsContainerForFontSizeInflation() const {
 | |
|     return GetStateBits() & NS_FRAME_FONT_INFLATION_CONTAINER;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return whether this frame keeps track of overflow areas. (Frames for
 | |
|    * non-display SVG elements -- e.g. <clipPath> -- do not maintain overflow
 | |
|    * areas, because they're never painted.)
 | |
|    */
 | |
|   bool FrameMaintainsOverflow() const {
 | |
|     return !HasAllStateBits(NS_FRAME_SVG_LAYOUT | NS_FRAME_IS_NONDISPLAY);
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * @param aStyleDisplay:  If the caller has this->StyleDisplay(), providing
 | |
|    *   it here will improve performance.
 | |
|    */
 | |
|   bool BackfaceIsHidden(const nsStyleDisplay* aStyleDisplay) const {
 | |
|     MOZ_ASSERT(aStyleDisplay == StyleDisplay());
 | |
|     return aStyleDisplay->BackfaceIsHidden();
 | |
|   }
 | |
|   bool BackfaceIsHidden() const {
 | |
|     return StyleDisplay()->BackfaceIsHidden();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns true if the frame is scrolled out of view.
 | |
|    */
 | |
|   bool IsScrolledOutOfView() const;
 | |
| 
 | |
|   /**
 | |
|    * Computes a 2D matrix from the -moz-window-transform and
 | |
|    * -moz-window-transform-origin properties on aFrame.
 | |
|    * Values that don't result in a 2D matrix will be ignored and an identity
 | |
|    * matrix will be returned instead.
 | |
|    */
 | |
|   Matrix ComputeWidgetTransform();
 | |
| 
 | |
|   /**
 | |
|    * Applies the values from the -moz-window-* properties to the widget.
 | |
|    */
 | |
|   virtual void UpdateWidgetProperties();
 | |
| 
 | |
|   /**
 | |
|    * @return true iff this frame has one or more associated image requests.
 | |
|    * @see mozilla::css::ImageLoader.
 | |
|    */
 | |
|   bool HasImageRequest() const { return mHasImageRequest; }
 | |
| 
 | |
|   /**
 | |
|    * Update this frame's image request state.
 | |
|    */
 | |
|   void SetHasImageRequest(bool aHasRequest) { mHasImageRequest = aHasRequest; }
 | |
| 
 | |
|   /**
 | |
|    * Whether this frame has a first-letter child.  If it does, the frame is
 | |
|    * actually an nsContainerFrame and the first-letter frame can be gotten by
 | |
|    * walking up to the nearest ancestor blockframe and getting its first
 | |
|    * continuation's nsContainerFrame::FirstLetterProperty() property.  This will
 | |
|    * only return true for the first continuation of the first-letter's parent.
 | |
|    */
 | |
|   bool HasFirstLetterChild() const { return mHasFirstLetterChild; }
 | |
| 
 | |
|   /**
 | |
|    * Whether this frame's parent is a wrapper anonymous box.  See documentation
 | |
|    * for mParentIsWrapperAnonBox.
 | |
|    */
 | |
|   bool ParentIsWrapperAnonBox() const { return mParentIsWrapperAnonBox; }
 | |
|   void SetParentIsWrapperAnonBox() { mParentIsWrapperAnonBox = true; }
 | |
| 
 | |
|   /**
 | |
|    * Whether this is a wrapper anonymous box needing a restyle.
 | |
|    */
 | |
|   bool IsWrapperAnonBoxNeedingRestyle() const {
 | |
|     return mIsWrapperBoxNeedingRestyle;
 | |
|   }
 | |
|   void SetIsWrapperAnonBoxNeedingRestyle(bool aNeedsRestyle) {
 | |
|     mIsWrapperBoxNeedingRestyle = aNeedsRestyle;
 | |
|   }
 | |
| 
 | |
|   bool MayHaveTransformAnimation() const {
 | |
|     return mMayHaveTransformAnimation;
 | |
|   }
 | |
|   void SetMayHaveTransformAnimation() {
 | |
|     mMayHaveTransformAnimation = true;
 | |
|   }
 | |
|   bool MayHaveOpacityAnimation() const {
 | |
|     return mMayHaveOpacityAnimation;
 | |
|   }
 | |
|   void SetMayHaveOpacityAnimation() {
 | |
|     mMayHaveOpacityAnimation = true;
 | |
|   }
 | |
| 
 | |
|   // Returns true if this frame is visible or may have visible descendants.
 | |
|   bool IsVisibleOrMayHaveVisibleDescendants() const {
 | |
|     return !mAllDescendantsAreInvisible || StyleVisibility()->IsVisible();
 | |
|   }
 | |
|   // Update mAllDescendantsAreInvisible flag for this frame and ancestors.
 | |
|   void UpdateVisibleDescendantsState();
 | |
| 
 | |
|   /**
 | |
|    * If this returns true, the frame it's called on should get the
 | |
|    * NS_FRAME_HAS_DIRTY_CHILDREN bit set on it by the caller; either directly
 | |
|    * if it's already in reflow, or via calling FrameNeedsReflow() to schedule a
 | |
|    * reflow.
 | |
|    */
 | |
|   virtual bool RenumberFrameAndDescendants(int32_t* aOrdinal,
 | |
|                                            int32_t aDepth,
 | |
|                                            int32_t aIncrement,
 | |
|                                            bool aForCounting) { return false; }
 | |
| 
 | |
|   /**
 | |
|    * Helper function - computes the content-box inline size for aCoord.
 | |
|    */
 | |
|   nscoord ComputeISizeValue(gfxContext*         aRenderingContext,
 | |
|                             nscoord             aContainingBlockISize,
 | |
|                             nscoord             aContentEdgeToBoxSizing,
 | |
|                             nscoord             aBoxSizingToMarginEdge,
 | |
|                             const nsStyleCoord& aCoord,
 | |
|                             ComputeSizeFlags    aFlags = eDefault);
 | |
| 
 | |
|   DisplayItemDataArray& DisplayItemData() { return mDisplayItemData; }
 | |
| 
 | |
|   void AddDisplayItem(nsDisplayItem* aItem);
 | |
|   bool RemoveDisplayItem(nsDisplayItem* aItem);
 | |
|   void RemoveDisplayItemDataForDeletion();
 | |
|   bool HasDisplayItems();
 | |
|   bool HasDisplayItem(nsDisplayItem* aItem);
 | |
| 
 | |
|   bool ForceDescendIntoIfVisible() { return mForceDescendIntoIfVisible; }
 | |
|   void SetForceDescendIntoIfVisible(bool aForce) { mForceDescendIntoIfVisible = aForce; }
 | |
| 
 | |
|   bool BuiltDisplayList() { return mBuiltDisplayList; }
 | |
|   void SetBuiltDisplayList(bool aBuilt) { mBuiltDisplayList = aBuilt; }
 | |
| 
 | |
|   bool IsFrameModified() { return mFrameIsModified; }
 | |
|   void SetFrameIsModified(bool aFrameIsModified) { mFrameIsModified = aFrameIsModified; }
 | |
| 
 | |
|   bool HasOverrideDirtyRegion() { return mHasOverrideDirtyRegion; }
 | |
|   void SetHasOverrideDirtyRegion(bool aHasDirtyRegion) { mHasOverrideDirtyRegion = aHasDirtyRegion; }
 | |
| 
 | |
|   bool MayHaveWillChangeBudget() { return mMayHaveWillChangeBudget; }
 | |
|   void SetMayHaveWillChangeBudget(bool aHasBudget) { mMayHaveWillChangeBudget = aHasBudget; }
 | |
| 
 | |
|   /**
 | |
|    * Returns the set of flags indicating the properties of the frame that the
 | |
|    * compositor might care about for hit-testing purposes. Note that this function
 | |
|    * must be called during Gecko display list construction time (i.e while the
 | |
|    * frame tree is being traversed) because that is when the display list builder
 | |
|    * has the necessary state set up correctly.
 | |
|    */
 | |
|   mozilla::gfx::CompositorHitTestInfo GetCompositorHitTestInfo(nsDisplayListBuilder* aBuilder);
 | |
| 
 | |
| protected:
 | |
|   static void DestroyAnonymousContent(nsPresContext* aPresContext,
 | |
|                                       already_AddRefed<nsIContent>&& aContent);
 | |
| 
 | |
|   /**
 | |
|    * Reparent this frame's view if it has one.
 | |
|    */
 | |
|   void ReparentFrameViewTo(nsViewManager* aViewManager,
 | |
|                            nsView*        aNewParentView,
 | |
|                            nsView*        aOldParentView);
 | |
| 
 | |
|   /**
 | |
|    * To be overridden by frame classes that have a varying IsLeaf() state and
 | |
|    * is indicating that with DynamicLeaf in nsFrameIdList.h.
 | |
|    * @see IsLeaf()
 | |
|    */
 | |
|   virtual bool IsLeafDynamic() const { return false; }
 | |
| 
 | |
|   // Members
 | |
|   nsRect                 mRect;
 | |
|   nsCOMPtr<nsIContent>   mContent;
 | |
|   RefPtr<ComputedStyle> mComputedStyle;
 | |
| private:
 | |
|   nsContainerFrame* mParent;
 | |
|   nsIFrame*        mNextSibling;  // doubly-linked list of frames
 | |
|   nsIFrame*        mPrevSibling;  // Do not touch outside SetNextSibling!
 | |
| 
 | |
|   DisplayItemDataArray mDisplayItemData;
 | |
| 
 | |
|   void MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder);
 | |
| 
 | |
|   static void DestroyPaintedPresShellList(nsTArray<nsWeakPtr>* list) {
 | |
|     list->Clear();
 | |
|     delete list;
 | |
|   }
 | |
| 
 | |
|   // Stores weak references to all the PresShells that were painted during
 | |
|   // the last paint event so that we can increment their paint count during
 | |
|   // empty transactions
 | |
|   NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(PaintedPresShellsProperty,
 | |
|                                       nsTArray<nsWeakPtr>,
 | |
|                                       DestroyPaintedPresShellList)
 | |
| 
 | |
|   nsTArray<nsWeakPtr>* PaintedPresShellList() {
 | |
|     nsTArray<nsWeakPtr>* list = GetProperty(PaintedPresShellsProperty());
 | |
| 
 | |
|     if (!list) {
 | |
|       list = new nsTArray<nsWeakPtr>();
 | |
|       SetProperty(PaintedPresShellsProperty(), list);
 | |
|     }
 | |
| 
 | |
|     return list;
 | |
|   }
 | |
| 
 | |
| protected:
 | |
|   /**
 | |
|    * Copies aRootElemWM to mWritingMode on 'this' and all its ancestors.
 | |
|    */
 | |
|   inline void PropagateRootElementWritingMode(mozilla::WritingMode aRootElemWM);
 | |
| 
 | |
|   void MarkInReflow() {
 | |
| #ifdef DEBUG_dbaron_off
 | |
|     // bug 81268
 | |
|     NS_ASSERTION(!(mState & NS_FRAME_IN_REFLOW), "frame is already in reflow");
 | |
| #endif
 | |
|     AddStateBits(NS_FRAME_IN_REFLOW);
 | |
|   }
 | |
| 
 | |
|   nsFrameState     mState;
 | |
| 
 | |
|   /**
 | |
|    * List of properties attached to the frame.
 | |
|    */
 | |
|   FrameProperties  mProperties;
 | |
| 
 | |
|   // When there is an overflow area only slightly larger than mRect,
 | |
|   // we store a set of four 1-byte deltas from the edges of mRect
 | |
|   // rather than allocating a whole separate rectangle property.
 | |
|   // Note that these are unsigned values, all measured "outwards"
 | |
|   // from the edges of mRect, so /mLeft/ and /mTop/ are reversed from
 | |
|   // our normal coordinate system.
 | |
|   // If mOverflow.mType == NS_FRAME_OVERFLOW_LARGE, then the
 | |
|   // delta values are not meaningful and the overflow area is stored
 | |
|   // as a separate rect property.
 | |
|   struct VisualDeltas {
 | |
|     uint8_t mLeft;
 | |
|     uint8_t mTop;
 | |
|     uint8_t mRight;
 | |
|     uint8_t mBottom;
 | |
|     bool operator==(const VisualDeltas& aOther) const
 | |
|     {
 | |
|       return mLeft == aOther.mLeft && mTop == aOther.mTop &&
 | |
|              mRight == aOther.mRight && mBottom == aOther.mBottom;
 | |
|     }
 | |
|     bool operator!=(const VisualDeltas& aOther) const
 | |
|     {
 | |
|       return !(*this == aOther);
 | |
|     }
 | |
|   };
 | |
|   union {
 | |
|     uint32_t     mType;
 | |
|     VisualDeltas mVisualDeltas;
 | |
|   } mOverflow;
 | |
| 
 | |
|   /** @see GetWritingMode() */
 | |
|   mozilla::WritingMode mWritingMode;
 | |
| 
 | |
|   /** The ClassID of the concrete class of this instance. */
 | |
|   ClassID mClass; // 1 byte
 | |
| 
 | |
|   bool mMayHaveRoundedCorners : 1;
 | |
| 
 | |
|   /**
 | |
|    * True iff this frame has one or more associated image requests.
 | |
|    * @see mozilla::css::ImageLoader.
 | |
|    */
 | |
|   bool mHasImageRequest : 1;
 | |
| 
 | |
|   /**
 | |
|    * True if this frame has a continuation that has a first-letter frame, or its
 | |
|    * placeholder, as a child.  In that case this frame has a blockframe ancestor
 | |
|    * that has the first-letter frame hanging off it in the
 | |
|    * nsContainerFrame::FirstLetterProperty() property.
 | |
|    */
 | |
|   bool mHasFirstLetterChild : 1;
 | |
| 
 | |
|   /**
 | |
|    * True if this frame's parent is a wrapper anonymous box (e.g. a table
 | |
|    * anonymous box as specified at
 | |
|    * <https://www.w3.org/TR/CSS21/tables.html#anonymous-boxes>).
 | |
|    *
 | |
|    * We could compute this information directly when we need it, but it wouldn't
 | |
|    * be all that cheap, and since this information is immutable for the lifetime
 | |
|    * of the frame we might as well cache it.
 | |
|    *
 | |
|    * Note that our parent may itself have mParentIsWrapperAnonBox set to true.
 | |
|    */
 | |
|   bool mParentIsWrapperAnonBox : 1;
 | |
| 
 | |
|   /**
 | |
|    * True if this is a wrapper anonymous box needing a restyle.  This is used to
 | |
|    * track, during stylo post-traversal, whether we've already recomputed the
 | |
|    * style of this anonymous box, if we end up seeing it twice.
 | |
|    */
 | |
|   bool mIsWrapperBoxNeedingRestyle : 1;
 | |
| 
 | |
|   /**
 | |
|    * This bit is used in nsTextFrame::CharacterDataChanged() as an optimization
 | |
|    * to skip redundant reflow-requests when the character data changes multiple
 | |
|    * times between reflows. If this flag is set, then it implies that the
 | |
|    * NS_FRAME_IS_DIRTY state bit is also set (and that intrinsic sizes have
 | |
|    * been marked as dirty on our ancestor chain).
 | |
|    *
 | |
|    * XXXdholbert This bit is *only* used on nsTextFrame, but it lives here on
 | |
|    * nsIFrame simply because this is where we've got unused state bits
 | |
|    * available in a gap. If bits become more scarce, we should perhaps consider
 | |
|    * expanding the range of frame-specific state bits in nsFrameStateBits.h and
 | |
|    * moving this to be one of those (e.g. by swapping one of the adjacent
 | |
|    * general-purpose bits to take the place of this bool:1 here, so we can grow
 | |
|    * that range of frame-specific bits by 1).
 | |
|    */
 | |
|   bool mReflowRequestedForCharDataChange : 1;
 | |
| 
 | |
|   /**
 | |
|    * This bit is used during BuildDisplayList to mark frames that need to
 | |
|    * have display items rebuilt. We will descend into them if they are
 | |
|    * currently visible, even if they don't intersect the dirty area.
 | |
|    */
 | |
|   bool mForceDescendIntoIfVisible : 1;
 | |
| 
 | |
|   /**
 | |
|    * True if we have built display items for this frame since
 | |
|    * the last call to CheckAndClearDisplayListState, false
 | |
|    * otherwise. Used for the reftest harness to verify minimal
 | |
|    * display list building.
 | |
|    */
 | |
|   bool mBuiltDisplayList : 1;
 | |
| 
 | |
|   bool mFrameIsModified : 1;
 | |
| 
 | |
|   bool mHasOverrideDirtyRegion : 1;
 | |
| 
 | |
|   /**
 | |
|    * True if frame has will-change, and currently has display
 | |
|    * items consuming some of the will-change budget.
 | |
|    */
 | |
|   bool mMayHaveWillChangeBudget : 1;
 | |
| 
 | |
| private:
 | |
|   /**
 | |
|    * True if this is the primary frame for mContent.
 | |
|    */
 | |
|   bool mIsPrimaryFrame : 1;
 | |
| 
 | |
|   bool mMayHaveTransformAnimation : 1;
 | |
|   bool mMayHaveOpacityAnimation : 1;
 | |
| 
 | |
|   /**
 | |
|    * True if we are certain that all descendants are not visible.
 | |
|    *
 | |
|    * This flag is conservative in that it might sometimes be false even if, in
 | |
|    * fact, all descendants are invisible.
 | |
|    * For example; an element is visibility:visible and has a visibility:hidden
 | |
|    * child. This flag is stil false in such case.
 | |
|    */
 | |
|   bool mAllDescendantsAreInvisible : 1;
 | |
| 
 | |
| protected:
 | |
| 
 | |
|   // There is a 1-bit gap left here.
 | |
| 
 | |
|   // Helpers
 | |
|   /**
 | |
|    * Can we stop inside this frame when we're skipping non-rendered whitespace?
 | |
|    * @param  aForward [in] Are we moving forward (or backward) in content order.
 | |
|    * @param  aOffset [in/out] At what offset into the frame to start looking.
 | |
|    *         on output - what offset was reached (whether or not we found a place to stop).
 | |
|    * @return STOP: An appropriate offset was found within this frame,
 | |
|    *         and is given by aOffset.
 | |
|    *         CONTINUE: Not found within this frame, need to try the next frame.
 | |
|    *         see enum FrameSearchResult for more details.
 | |
|    */
 | |
|   virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) = 0;
 | |
| 
 | |
|   /**
 | |
|    * Search the frame for the next character
 | |
|    * @param  aForward [in] Are we moving forward (or backward) in content order.
 | |
|    * @param  aOffset [in/out] At what offset into the frame to start looking.
 | |
|    *         on output - what offset was reached (whether or not we found a place to stop).
 | |
|    * @param  aOptions [in] Options, see the comment in
 | |
|    *         PeekOffsetCharacterOptions for the detail.
 | |
|    * @return STOP: An appropriate offset was found within this frame,
 | |
|    *         and is given by aOffset.
 | |
|    *         CONTINUE: Not found within this frame, need to try the next frame.
 | |
|    *         see enum FrameSearchResult for more details.
 | |
|    */
 | |
|   virtual FrameSearchResult
 | |
|   PeekOffsetCharacter(bool aForward, int32_t* aOffset,
 | |
|                       PeekOffsetCharacterOptions aOptions =
 | |
|                         PeekOffsetCharacterOptions()) = 0;
 | |
|   static_assert(sizeof(PeekOffsetCharacterOptions) <= sizeof(intptr_t),
 | |
|                 "aOptions should be changed to const reference");
 | |
| 
 | |
|   /**
 | |
|    * Search the frame for the next word boundary
 | |
|    * @param  aForward [in] Are we moving forward (or backward) in content order.
 | |
|    * @param  aWordSelectEatSpace [in] true: look for non-whitespace following
 | |
|    *         whitespace (in the direction of movement).
 | |
|    *         false: look for whitespace following non-whitespace (in the
 | |
|    *         direction  of movement).
 | |
|    * @param  aIsKeyboardSelect [in] Was the action initiated by a keyboard operation?
 | |
|    *         If true, punctuation immediately following a word is considered part
 | |
|    *         of that word. Otherwise, a sequence of punctuation is always considered
 | |
|    *         as a word on its own.
 | |
|    * @param  aOffset [in/out] At what offset into the frame to start looking.
 | |
|    *         on output - what offset was reached (whether or not we found a place to stop).
 | |
|    * @param  aState [in/out] the state that is carried from frame to frame
 | |
|    * @return true: An appropriate offset was found within this frame,
 | |
|    *         and is given by aOffset.
 | |
|    *         false: Not found within this frame, need to try the next frame.
 | |
|    */
 | |
|   struct PeekWordState {
 | |
|     // true when we're still at the start of the search, i.e., we can't return
 | |
|     // this point as a valid offset!
 | |
|     bool mAtStart;
 | |
|     // true when we've encountered at least one character of the pre-boundary type
 | |
|     // (whitespace if aWordSelectEatSpace is true, non-whitespace otherwise)
 | |
|     bool mSawBeforeType;
 | |
|     // true when the last character encountered was punctuation
 | |
|     bool mLastCharWasPunctuation;
 | |
|     // true when the last character encountered was whitespace
 | |
|     bool mLastCharWasWhitespace;
 | |
|     // true when we've seen non-punctuation since the last whitespace
 | |
|     bool mSeenNonPunctuationSinceWhitespace;
 | |
|     // text that's *before* the current frame when aForward is true, *after*
 | |
|     // the current frame when aForward is false. Only includes the text
 | |
|     // on the current line.
 | |
|     nsAutoString mContext;
 | |
| 
 | |
|     PeekWordState() : mAtStart(true), mSawBeforeType(false),
 | |
|         mLastCharWasPunctuation(false), mLastCharWasWhitespace(false),
 | |
|         mSeenNonPunctuationSinceWhitespace(false) {}
 | |
|     void SetSawBeforeType() { mSawBeforeType = true; }
 | |
|     void Update(bool aAfterPunctuation, bool aAfterWhitespace) {
 | |
|       mLastCharWasPunctuation = aAfterPunctuation;
 | |
|       mLastCharWasWhitespace = aAfterWhitespace;
 | |
|       if (aAfterWhitespace) {
 | |
|         mSeenNonPunctuationSinceWhitespace = false;
 | |
|       } else if (!aAfterPunctuation) {
 | |
|         mSeenNonPunctuationSinceWhitespace = true;
 | |
|       }
 | |
|       mAtStart = false;
 | |
|     }
 | |
|   };
 | |
|   virtual FrameSearchResult PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
 | |
|                                 int32_t* aOffset, PeekWordState* aState) = 0;
 | |
| 
 | |
|   /**
 | |
|    * Search for the first paragraph boundary before or after the given position
 | |
|    * @param  aPos See description in nsFrameSelection.h. The following fields are
 | |
|    *              used by this method:
 | |
|    *              Input: mDirection
 | |
|    *              Output: mResultContent, mContentOffset
 | |
|    */
 | |
|   nsresult PeekOffsetParagraph(nsPeekOffsetStruct *aPos);
 | |
| 
 | |
| private:
 | |
|   // Get a pointer to the overflow areas property attached to the frame.
 | |
|   nsOverflowAreas* GetOverflowAreasProperty() const {
 | |
|     MOZ_ASSERT(mOverflow.mType == NS_FRAME_OVERFLOW_LARGE);
 | |
|     nsOverflowAreas* overflow = GetProperty(OverflowAreasProperty());
 | |
|     MOZ_ASSERT(overflow);
 | |
|     return overflow;
 | |
|   }
 | |
| 
 | |
|   nsRect GetVisualOverflowFromDeltas() const {
 | |
|     MOZ_ASSERT(mOverflow.mType != NS_FRAME_OVERFLOW_LARGE,
 | |
|                "should not be called when overflow is in a property");
 | |
|     // Calculate the rect using deltas from the frame's border rect.
 | |
|     // Note that the mOverflow.mDeltas fields are unsigned, but we will often
 | |
|     // need to return negative values for the left and top, so take care
 | |
|     // to cast away the unsigned-ness.
 | |
|     return nsRect(-(int32_t)mOverflow.mVisualDeltas.mLeft,
 | |
|                   -(int32_t)mOverflow.mVisualDeltas.mTop,
 | |
|                   mRect.Width() + mOverflow.mVisualDeltas.mRight +
 | |
|                                   mOverflow.mVisualDeltas.mLeft,
 | |
|                   mRect.Height() + mOverflow.mVisualDeltas.mBottom +
 | |
|                                    mOverflow.mVisualDeltas.mTop);
 | |
|   }
 | |
|   /**
 | |
|    * Returns true if any overflow changed.
 | |
|    */
 | |
|   bool SetOverflowAreas(const nsOverflowAreas& aOverflowAreas);
 | |
| 
 | |
|   // Helper-functions for SortFrameList():
 | |
|   template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
 | |
|   static nsIFrame* SortedMerge(nsIFrame *aLeft, nsIFrame *aRight);
 | |
| 
 | |
|   template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
 | |
|   static nsIFrame* MergeSort(nsIFrame *aSource);
 | |
| 
 | |
|   bool HasOpacityInternal(float aThreshold,
 | |
|                           mozilla::EffectSet* aEffectSet = nullptr) const;
 | |
| 
 | |
|   // Maps mClass to LayoutFrameType.
 | |
|   static const mozilla::LayoutFrameType sLayoutFrameTypes[
 | |
| #define FRAME_ID(...) 1 +
 | |
| #define ABSTRACT_FRAME_ID(...)
 | |
| #include "nsFrameIdList.h"
 | |
| #undef FRAME_ID
 | |
| #undef ABSTRACT_FRAME_ID
 | |
|   0];
 | |
| 
 | |
|   enum FrameClassBits {
 | |
|     eFrameClassBitsNone        = 0x0,
 | |
|     eFrameClassBitsLeaf        = 0x1,
 | |
|     eFrameClassBitsDynamicLeaf = 0x2,
 | |
|   };
 | |
|   // Maps mClass to IsLeaf() flags.
 | |
|   static const FrameClassBits sFrameClassBits[
 | |
| #define FRAME_ID(...) 1 +
 | |
| #define ABSTRACT_FRAME_ID(...)
 | |
| #include "nsFrameIdList.h"
 | |
| #undef FRAME_ID
 | |
| #undef ABSTRACT_FRAME_ID
 | |
|   0];
 | |
| 
 | |
| #ifdef DEBUG_FRAME_DUMP
 | |
| public:
 | |
|   static void IndentBy(FILE* out, int32_t aIndent) {
 | |
|     while (--aIndent >= 0) fputs("  ", out);
 | |
|   }
 | |
|   void ListTag(FILE* out) const {
 | |
|     ListTag(out, this);
 | |
|   }
 | |
|   static void ListTag(FILE* out, const nsIFrame* aFrame) {
 | |
|     nsAutoCString t;
 | |
|     ListTag(t, aFrame);
 | |
|     fputs(t.get(), out);
 | |
|   }
 | |
|   static void ListTag(FILE* out, const nsFrameList& aFrameList) {
 | |
|     for (nsIFrame* frame : aFrameList) {
 | |
|       ListTag(out, frame);
 | |
|     }
 | |
|   }
 | |
|   void ListTag(nsACString& aTo) const;
 | |
|   nsAutoCString ListTag() const {
 | |
|     nsAutoCString tag;
 | |
|     ListTag(tag);
 | |
|     return tag;
 | |
|   }
 | |
|   static void ListTag(nsACString& aTo, const nsIFrame* aFrame);
 | |
|   void ListGeneric(nsACString& aTo, const char* aPrefix = "", uint32_t aFlags = 0) const;
 | |
|   enum {
 | |
|     TRAVERSE_SUBDOCUMENT_FRAMES = 0x01
 | |
|   };
 | |
|   virtual void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const;
 | |
|   /**
 | |
|    * lists the frames beginning from the root frame
 | |
|    * - calls root frame's List(...)
 | |
|    */
 | |
|   static void RootFrameList(nsPresContext* aPresContext,
 | |
|                             FILE* out = stderr, const char* aPrefix = "");
 | |
|   virtual void DumpFrameTree() const;
 | |
|   void DumpFrameTreeLimited() const;
 | |
| 
 | |
|   virtual nsresult  GetFrameName(nsAString& aResult) const = 0;
 | |
| #endif
 | |
| };
 | |
| 
 | |
| //----------------------------------------------------------------------
 | |
| 
 | |
| /**
 | |
|  * AutoWeakFrame can be used to keep a reference to a nsIFrame in a safe way.
 | |
|  * Whenever an nsIFrame object is deleted, the AutoWeakFrames pointing
 | |
|  * to it will be cleared.  AutoWeakFrame is for variables on the stack or
 | |
|  * in static storage only, there is also a WeakFrame below for heap uses.
 | |
|  *
 | |
|  * Create AutoWeakFrame object when it is sure that nsIFrame object
 | |
|  * is alive and after some operations which may destroy the nsIFrame
 | |
|  * (for example any DOM modifications) use IsAlive() or GetFrame() methods to
 | |
|  * check whether it is safe to continue to use the nsIFrame object.
 | |
|  *
 | |
|  * @note The usage of this class should be kept to a minimum.
 | |
|  */
 | |
| class WeakFrame;
 | |
| class MOZ_NONHEAP_CLASS AutoWeakFrame
 | |
| {
 | |
| public:
 | |
|   explicit AutoWeakFrame()
 | |
|     : mPrev(nullptr), mFrame(nullptr) {}
 | |
| 
 | |
|   AutoWeakFrame(const AutoWeakFrame& aOther)
 | |
|     : mPrev(nullptr), mFrame(nullptr)
 | |
|   {
 | |
|     Init(aOther.GetFrame());
 | |
|   }
 | |
| 
 | |
|   MOZ_IMPLICIT AutoWeakFrame(const WeakFrame& aOther);
 | |
| 
 | |
|   MOZ_IMPLICIT AutoWeakFrame(nsIFrame* aFrame)
 | |
|     : mPrev(nullptr), mFrame(nullptr)
 | |
|   {
 | |
|     Init(aFrame);
 | |
|   }
 | |
| 
 | |
|   AutoWeakFrame& operator=(AutoWeakFrame& aOther) {
 | |
|     Init(aOther.GetFrame());
 | |
|     return *this;
 | |
|   }
 | |
| 
 | |
|   AutoWeakFrame& operator=(nsIFrame* aFrame) {
 | |
|     Init(aFrame);
 | |
|     return *this;
 | |
|   }
 | |
| 
 | |
|   nsIFrame* operator->()
 | |
|   {
 | |
|     return mFrame;
 | |
|   }
 | |
| 
 | |
|   operator nsIFrame*()
 | |
|   {
 | |
|     return mFrame;
 | |
|   }
 | |
| 
 | |
|   void Clear(nsIPresShell* aShell) {
 | |
|     if (aShell) {
 | |
|       aShell->RemoveAutoWeakFrame(this);
 | |
|     }
 | |
|     mFrame = nullptr;
 | |
|     mPrev = nullptr;
 | |
|   }
 | |
| 
 | |
|   bool IsAlive() { return !!mFrame; }
 | |
| 
 | |
|   nsIFrame* GetFrame() const { return mFrame; }
 | |
| 
 | |
|   AutoWeakFrame* GetPreviousWeakFrame() { return mPrev; }
 | |
| 
 | |
|   void SetPreviousWeakFrame(AutoWeakFrame* aPrev) { mPrev = aPrev; }
 | |
| 
 | |
|   ~AutoWeakFrame()
 | |
|   {
 | |
|     Clear(mFrame ? mFrame->PresContext()->GetPresShell() : nullptr);
 | |
|   }
 | |
| private:
 | |
|   // Not available for the heap!
 | |
|   void* operator new(size_t) = delete;
 | |
|   void* operator new[](size_t) = delete;
 | |
|   void operator delete(void*) = delete;
 | |
|   void operator delete[](void*) = delete;
 | |
| 
 | |
|   void Init(nsIFrame* aFrame);
 | |
| 
 | |
|   AutoWeakFrame*  mPrev;
 | |
|   nsIFrame*       mFrame;
 | |
| };
 | |
| 
 | |
| // Use nsIFrame's fast-path to avoid QueryFrame:
 | |
| inline do_QueryFrameHelper<nsIFrame>
 | |
| do_QueryFrame(AutoWeakFrame& s)
 | |
| {
 | |
|   return do_QueryFrameHelper<nsIFrame>(s.GetFrame());
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @see AutoWeakFrame
 | |
|  */
 | |
| class MOZ_HEAP_CLASS WeakFrame
 | |
| {
 | |
| public:
 | |
|   WeakFrame() : mFrame(nullptr) {}
 | |
| 
 | |
|   WeakFrame(const WeakFrame& aOther) : mFrame(nullptr)
 | |
|   {
 | |
|     Init(aOther.GetFrame());
 | |
|   }
 | |
| 
 | |
|   MOZ_IMPLICIT WeakFrame(const AutoWeakFrame& aOther) : mFrame(nullptr)
 | |
|   {
 | |
|     Init(aOther.GetFrame());
 | |
|   }
 | |
| 
 | |
|   MOZ_IMPLICIT WeakFrame(nsIFrame* aFrame) : mFrame(nullptr)
 | |
|   {
 | |
|     Init(aFrame);
 | |
|   }
 | |
| 
 | |
|   ~WeakFrame()
 | |
|   {
 | |
|     Clear(mFrame ? mFrame->PresContext()->GetPresShell() : nullptr);
 | |
|   }
 | |
| 
 | |
|   WeakFrame& operator=(WeakFrame& aOther) {
 | |
|     Init(aOther.GetFrame());
 | |
|     return *this;
 | |
|   }
 | |
| 
 | |
|   WeakFrame& operator=(nsIFrame* aFrame) {
 | |
|     Init(aFrame);
 | |
|     return *this;
 | |
|   }
 | |
| 
 | |
|   nsIFrame* operator->() { return mFrame; }
 | |
|   operator nsIFrame*() { return mFrame; }
 | |
| 
 | |
|   void Clear(nsIPresShell* aShell) {
 | |
|     if (aShell) {
 | |
|       aShell->RemoveWeakFrame(this);
 | |
|     }
 | |
|     mFrame = nullptr;
 | |
|   }
 | |
| 
 | |
|   bool IsAlive() { return !!mFrame; }
 | |
|   nsIFrame* GetFrame() const { return mFrame; }
 | |
| 
 | |
| private:
 | |
|   void Init(nsIFrame* aFrame);
 | |
| 
 | |
|   nsIFrame* mFrame;
 | |
| };
 | |
| 
 | |
| // Use nsIFrame's fast-path to avoid QueryFrame:
 | |
| inline do_QueryFrameHelper<nsIFrame>
 | |
| do_QueryFrame(WeakFrame& s)
 | |
| {
 | |
|   return do_QueryFrameHelper<nsIFrame>(s.GetFrame());
 | |
| }
 | |
| 
 | |
| inline bool
 | |
| nsFrameList::ContinueRemoveFrame(nsIFrame* aFrame)
 | |
| {
 | |
|   MOZ_ASSERT(!aFrame->GetPrevSibling() || !aFrame->GetNextSibling(),
 | |
|              "Forgot to call StartRemoveFrame?");
 | |
|   if (aFrame == mLastChild) {
 | |
|     MOZ_ASSERT(!aFrame->GetNextSibling(), "broken frame list");
 | |
|     nsIFrame* prevSibling = aFrame->GetPrevSibling();
 | |
|     if (!prevSibling) {
 | |
|       MOZ_ASSERT(aFrame == mFirstChild, "broken frame list");
 | |
|       mFirstChild = mLastChild = nullptr;
 | |
|       return true;
 | |
|     }
 | |
|     MOZ_ASSERT(prevSibling->GetNextSibling() == aFrame, "Broken frame linkage");
 | |
|     prevSibling->SetNextSibling(nullptr);
 | |
|     mLastChild = prevSibling;
 | |
|     return true;
 | |
|   }
 | |
|   if (aFrame == mFirstChild) {
 | |
|     MOZ_ASSERT(!aFrame->GetPrevSibling(), "broken frame list");
 | |
|     mFirstChild = aFrame->GetNextSibling();
 | |
|     aFrame->SetNextSibling(nullptr);
 | |
|     MOZ_ASSERT(mFirstChild, "broken frame list");
 | |
|     return true;
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| inline bool
 | |
| nsFrameList::StartRemoveFrame(nsIFrame* aFrame)
 | |
| {
 | |
|   if (aFrame->GetPrevSibling() && aFrame->GetNextSibling()) {
 | |
|     UnhookFrameFromSiblings(aFrame);
 | |
|     return true;
 | |
|   }
 | |
|   return ContinueRemoveFrame(aFrame);
 | |
| }
 | |
| 
 | |
| inline void
 | |
| nsFrameList::Enumerator::Next()
 | |
| {
 | |
|   NS_ASSERTION(!AtEnd(), "Should have checked AtEnd()!");
 | |
|   mFrame = mFrame->GetNextSibling();
 | |
| }
 | |
| 
 | |
| inline
 | |
| nsFrameList::FrameLinkEnumerator::
 | |
| FrameLinkEnumerator(const nsFrameList& aList, nsIFrame* aPrevFrame)
 | |
|   : Enumerator(aList)
 | |
| {
 | |
|   mPrev = aPrevFrame;
 | |
|   mFrame = aPrevFrame ? aPrevFrame->GetNextSibling() : aList.FirstChild();
 | |
| }
 | |
| 
 | |
| inline void
 | |
| nsFrameList::FrameLinkEnumerator::Next()
 | |
| {
 | |
|   mPrev = mFrame;
 | |
|   Enumerator::Next();
 | |
| }
 | |
| 
 | |
| // Operators of nsFrameList::Iterator
 | |
| // ---------------------------------------------------
 | |
| 
 | |
| inline nsFrameList::Iterator&
 | |
| nsFrameList::Iterator::operator++()
 | |
| {
 | |
|   mCurrent = mCurrent->GetNextSibling();
 | |
|   return *this;
 | |
| }
 | |
| 
 | |
| inline nsFrameList::Iterator&
 | |
| nsFrameList::Iterator::operator--()
 | |
| {
 | |
|   if (!mCurrent) {
 | |
|     mCurrent = mList.LastChild();
 | |
|   } else {
 | |
|     mCurrent = mCurrent->GetPrevSibling();
 | |
|   }
 | |
|   return *this;
 | |
| }
 | |
| 
 | |
| // Helper-functions for nsIFrame::SortFrameList()
 | |
| // ---------------------------------------------------
 | |
| 
 | |
| template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
 | |
| /* static */ nsIFrame*
 | |
| nsIFrame::SortedMerge(nsIFrame *aLeft, nsIFrame *aRight)
 | |
| {
 | |
|   MOZ_ASSERT(aLeft && aRight, "SortedMerge must have non-empty lists");
 | |
| 
 | |
|   nsIFrame *result;
 | |
|   // Unroll first iteration to avoid null-check 'result' inside the loop.
 | |
|   if (IsLessThanOrEqual(aLeft, aRight)) {
 | |
|     result = aLeft;
 | |
|     aLeft = aLeft->GetNextSibling();
 | |
|     if (!aLeft) {
 | |
|       result->SetNextSibling(aRight);
 | |
|       return result;
 | |
|     }
 | |
|   }
 | |
|   else {
 | |
|     result = aRight;
 | |
|     aRight = aRight->GetNextSibling();
 | |
|     if (!aRight) {
 | |
|       result->SetNextSibling(aLeft);
 | |
|       return result;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   nsIFrame *last = result;
 | |
|   for (;;) {
 | |
|     if (IsLessThanOrEqual(aLeft, aRight)) {
 | |
|       last->SetNextSibling(aLeft);
 | |
|       last = aLeft;
 | |
|       aLeft = aLeft->GetNextSibling();
 | |
|       if (!aLeft) {
 | |
|         last->SetNextSibling(aRight);
 | |
|         return result;
 | |
|       }
 | |
|     }
 | |
|     else {
 | |
|       last->SetNextSibling(aRight);
 | |
|       last = aRight;
 | |
|       aRight = aRight->GetNextSibling();
 | |
|       if (!aRight) {
 | |
|         last->SetNextSibling(aLeft);
 | |
|         return result;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
 | |
| /* static */ nsIFrame*
 | |
| nsIFrame::MergeSort(nsIFrame *aSource)
 | |
| {
 | |
|   MOZ_ASSERT(aSource, "MergeSort null arg");
 | |
| 
 | |
|   nsIFrame *sorted[32] = { nullptr };
 | |
|   nsIFrame **fill = &sorted[0];
 | |
|   nsIFrame **left;
 | |
|   nsIFrame *rest = aSource;
 | |
| 
 | |
|   do {
 | |
|     nsIFrame *current = rest;
 | |
|     rest = rest->GetNextSibling();
 | |
|     current->SetNextSibling(nullptr);
 | |
| 
 | |
|     // Merge it with sorted[0] if present; then merge the result with sorted[1] etc.
 | |
|     // sorted[0] is a list of length 1 (or nullptr).
 | |
|     // sorted[1] is a list of length 2 (or nullptr).
 | |
|     // sorted[2] is a list of length 4 (or nullptr). etc.
 | |
|     for (left = &sorted[0]; left != fill && *left; ++left) {
 | |
|       current = SortedMerge<IsLessThanOrEqual>(*left, current);
 | |
|       *left = nullptr;
 | |
|     }
 | |
| 
 | |
|     // Fill the empty slot that we couldn't merge with the last result.
 | |
|     *left = current;
 | |
| 
 | |
|     if (left == fill)
 | |
|       ++fill;
 | |
|   } while (rest);
 | |
| 
 | |
|   // Collect and merge the results.
 | |
|   nsIFrame *result = nullptr;
 | |
|   for (left = &sorted[0]; left != fill; ++left) {
 | |
|     if (*left) {
 | |
|       result = result ? SortedMerge<IsLessThanOrEqual>(*left, result) : *left;
 | |
|     }
 | |
|   }
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
 | |
| /* static */ void
 | |
| nsIFrame::SortFrameList(nsFrameList& aFrameList)
 | |
| {
 | |
|   nsIFrame* head = MergeSort<IsLessThanOrEqual>(aFrameList.FirstChild());
 | |
|   aFrameList = nsFrameList(head, nsLayoutUtils::GetLastSibling(head));
 | |
|   MOZ_ASSERT(IsFrameListSorted<IsLessThanOrEqual>(aFrameList),
 | |
|              "After we sort a frame list, it should be in sorted order...");
 | |
| }
 | |
| 
 | |
| template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
 | |
| /* static */ bool
 | |
| nsIFrame::IsFrameListSorted(nsFrameList& aFrameList)
 | |
| {
 | |
|   if (aFrameList.IsEmpty()) {
 | |
|     // empty lists are trivially sorted.
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   // We'll walk through the list with two iterators, one trailing behind the
 | |
|   // other. The list is sorted IFF trailingIter <= iter, across the whole list.
 | |
|   nsFrameList::Enumerator trailingIter(aFrameList);
 | |
|   nsFrameList::Enumerator iter(aFrameList);
 | |
|   iter.Next(); // Skip |iter| past first frame. (List is nonempty, so we can.)
 | |
| 
 | |
|   // Now, advance the iterators in parallel, comparing each adjacent pair.
 | |
|   while (!iter.AtEnd()) {
 | |
|     MOZ_ASSERT(!trailingIter.AtEnd(), "trailing iter shouldn't finish first");
 | |
|     if (!IsLessThanOrEqual(trailingIter.get(), iter.get())) {
 | |
|       return false;
 | |
|     }
 | |
|     trailingIter.Next();
 | |
|     iter.Next();
 | |
|   }
 | |
| 
 | |
|   // We made it to the end without returning early, so the list is sorted.
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| // Needs to be defined here rather than nsIFrameInlines.h, because it is used
 | |
| // within this header.
 | |
| nsPoint
 | |
| nsIFrame::GetNormalPosition(bool* aHasProperty) const
 | |
| {
 | |
|   nsPoint* normalPosition = GetProperty(NormalPositionProperty());
 | |
|   if (normalPosition) {
 | |
|     if (aHasProperty) {
 | |
|       *aHasProperty = true;
 | |
|     }
 | |
|     return *normalPosition;
 | |
|   }
 | |
|   if (aHasProperty) {
 | |
|     *aHasProperty = false;
 | |
|   }
 | |
|   return GetPosition();
 | |
| }
 | |
| 
 | |
| #endif /* nsIFrame_h___ */
 |