forked from mirrors/gecko-dev
		
	 f5a42005e2
			
		
	
	
		f5a42005e2
		
	
	
	
	
		
			
			Changed from returning `bool` & taking an out parameter. Differential Revision: https://phabricator.services.mozilla.com/D168998
		
			
				
	
	
		
			652 lines
		
	
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			652 lines
		
	
	
	
		
			25 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/. */
 | |
| 
 | |
| /* rendering object for CSS "display: grid | inline-grid" */
 | |
| 
 | |
| #ifndef nsGridContainerFrame_h___
 | |
| #define nsGridContainerFrame_h___
 | |
| 
 | |
| #include "mozilla/CSSOrderAwareFrameIterator.h"
 | |
| #include "mozilla/MathAlgorithms.h"
 | |
| #include "mozilla/Maybe.h"
 | |
| #include "mozilla/HashTable.h"
 | |
| #include "nsContainerFrame.h"
 | |
| #include "nsILineIterator.h"
 | |
| 
 | |
| namespace mozilla {
 | |
| class PresShell;
 | |
| namespace dom {
 | |
| class Grid;
 | |
| }
 | |
| }  // namespace mozilla
 | |
| 
 | |
| /**
 | |
|  * Factory function.
 | |
|  * @return a newly allocated nsGridContainerFrame (infallible)
 | |
|  */
 | |
| nsContainerFrame* NS_NewGridContainerFrame(mozilla::PresShell* aPresShell,
 | |
|                                            mozilla::ComputedStyle* aStyle);
 | |
| 
 | |
| namespace mozilla {
 | |
| 
 | |
| /**
 | |
|  * The number of implicit / explicit tracks and their sizes.
 | |
|  */
 | |
| struct ComputedGridTrackInfo {
 | |
|   ComputedGridTrackInfo(
 | |
|       uint32_t aNumLeadingImplicitTracks, uint32_t aNumExplicitTracks,
 | |
|       uint32_t aStartFragmentTrack, uint32_t aEndFragmentTrack,
 | |
|       nsTArray<nscoord>&& aPositions, nsTArray<nscoord>&& aSizes,
 | |
|       nsTArray<uint32_t>&& aStates, nsTArray<bool>&& aRemovedRepeatTracks,
 | |
|       uint32_t aRepeatFirstTrack,
 | |
|       nsTArray<nsTArray<StyleCustomIdent>>&& aResolvedLineNames,
 | |
|       bool aIsSubgrid, bool aIsMasonry)
 | |
|       : mNumLeadingImplicitTracks(aNumLeadingImplicitTracks),
 | |
|         mNumExplicitTracks(aNumExplicitTracks),
 | |
|         mStartFragmentTrack(aStartFragmentTrack),
 | |
|         mEndFragmentTrack(aEndFragmentTrack),
 | |
|         mPositions(std::move(aPositions)),
 | |
|         mSizes(std::move(aSizes)),
 | |
|         mStates(std::move(aStates)),
 | |
|         mRemovedRepeatTracks(std::move(aRemovedRepeatTracks)),
 | |
|         mResolvedLineNames(std::move(aResolvedLineNames)),
 | |
|         mRepeatFirstTrack(aRepeatFirstTrack),
 | |
|         mIsSubgrid(aIsSubgrid),
 | |
|         mIsMasonry(aIsMasonry) {}
 | |
|   uint32_t mNumLeadingImplicitTracks;
 | |
|   uint32_t mNumExplicitTracks;
 | |
|   uint32_t mStartFragmentTrack;
 | |
|   uint32_t mEndFragmentTrack;
 | |
|   nsTArray<nscoord> mPositions;
 | |
|   nsTArray<nscoord> mSizes;
 | |
|   nsTArray<uint32_t> mStates;
 | |
|   // Indicates if a track has been collapsed. This will be populated for each
 | |
|   // track in the repeat(auto-fit) and repeat(auto-fill), even if there are no
 | |
|   // collapsed tracks.
 | |
|   nsTArray<bool> mRemovedRepeatTracks;
 | |
|   // Contains lists of all line name lists, including the name lists inside
 | |
|   // repeats. When a repeat(auto) track exists, the internal track names will
 | |
|   // appear once each in this array.
 | |
|   nsTArray<nsTArray<StyleCustomIdent>> mResolvedLineNames;
 | |
|   uint32_t mRepeatFirstTrack;
 | |
|   bool mIsSubgrid;
 | |
|   bool mIsMasonry;
 | |
| };
 | |
| 
 | |
| struct ComputedGridLineInfo {
 | |
|   explicit ComputedGridLineInfo(
 | |
|       nsTArray<nsTArray<RefPtr<nsAtom>>>&& aNames,
 | |
|       const nsTArray<RefPtr<nsAtom>>& aNamesBefore,
 | |
|       const nsTArray<RefPtr<nsAtom>>& aNamesAfter,
 | |
|       nsTArray<RefPtr<nsAtom>>&& aNamesFollowingRepeat)
 | |
|       : mNames(std::move(aNames)),
 | |
|         mNamesBefore(aNamesBefore.Clone()),
 | |
|         mNamesAfter(aNamesAfter.Clone()),
 | |
|         mNamesFollowingRepeat(std::move(aNamesFollowingRepeat)) {}
 | |
|   nsTArray<nsTArray<RefPtr<nsAtom>>> mNames;
 | |
|   nsTArray<RefPtr<nsAtom>> mNamesBefore;
 | |
|   nsTArray<RefPtr<nsAtom>> mNamesAfter;
 | |
|   nsTArray<RefPtr<nsAtom>> mNamesFollowingRepeat;
 | |
| };
 | |
| }  // namespace mozilla
 | |
| 
 | |
| class nsGridContainerFrame final : public nsContainerFrame,
 | |
|                                    public nsILineIterator {
 | |
|  public:
 | |
|   NS_DECL_FRAMEARENA_HELPERS(nsGridContainerFrame)
 | |
|   NS_DECL_QUERYFRAME
 | |
|   using ComputedGridTrackInfo = mozilla::ComputedGridTrackInfo;
 | |
|   using ComputedGridLineInfo = mozilla::ComputedGridLineInfo;
 | |
|   using LogicalAxis = mozilla::LogicalAxis;
 | |
|   using BaselineSharingGroup = mozilla::BaselineSharingGroup;
 | |
|   using NamedArea = mozilla::StyleNamedArea;
 | |
| 
 | |
|   template <typename T>
 | |
|   using PerBaseline = mozilla::EnumeratedArray<BaselineSharingGroup,
 | |
|                                                BaselineSharingGroup(2), T>;
 | |
| 
 | |
|   template <typename T>
 | |
|   using PerLogicalAxis =
 | |
|       mozilla::EnumeratedArray<LogicalAxis, LogicalAxis(2), T>;
 | |
| 
 | |
|   // nsIFrame overrides
 | |
|   void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
 | |
|               const ReflowInput& aReflowInput,
 | |
|               nsReflowStatus& aStatus) override;
 | |
|   void Init(nsIContent* aContent, nsContainerFrame* aParent,
 | |
|             nsIFrame* aPrevInFlow) override;
 | |
|   void DidSetComputedStyle(ComputedStyle* aOldStyle) override;
 | |
|   nscoord GetMinISize(gfxContext* aRenderingContext) override;
 | |
|   nscoord GetPrefISize(gfxContext* aRenderingContext) override;
 | |
|   void MarkIntrinsicISizesDirty() override;
 | |
|   bool IsFrameOfType(uint32_t aFlags) const override {
 | |
|     return nsContainerFrame::IsFrameOfType(
 | |
|         aFlags & ~nsIFrame::eCanContainOverflowContainers);
 | |
|   }
 | |
| 
 | |
|   void BuildDisplayList(nsDisplayListBuilder* aBuilder,
 | |
|                         const nsDisplayListSet& aLists) override;
 | |
| 
 | |
|   Maybe<nscoord> GetNaturalBaselineBOffset(
 | |
|       mozilla::WritingMode aWM,
 | |
|       BaselineSharingGroup aBaselineGroup) const override {
 | |
|     if (StyleDisplay()->IsContainLayout() ||
 | |
|         HasAnyStateBits(NS_STATE_GRID_SYNTHESIZE_BASELINE)) {
 | |
|       return Nothing{};
 | |
|     }
 | |
|     return mozilla::Some(GetBBaseline(aBaselineGroup));
 | |
|   }
 | |
| 
 | |
| #ifdef DEBUG_FRAME_DUMP
 | |
|   nsresult GetFrameName(nsAString& aResult) const override;
 | |
|   void ExtraContainerFrameInfo(nsACString& aTo) const override;
 | |
| #endif
 | |
| 
 | |
|   // nsContainerFrame overrides
 | |
|   bool DrainSelfOverflowList() override;
 | |
|   void AppendFrames(ChildListID aListID, nsFrameList&& aFrameList) override;
 | |
|   void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
 | |
|                     const nsLineList::iterator* aPrevFrameLine,
 | |
|                     nsFrameList&& aFrameList) override;
 | |
|   void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override;
 | |
|   mozilla::StyleAlignFlags CSSAlignmentForAbsPosChild(
 | |
|       const ReflowInput& aChildRI, LogicalAxis aLogicalAxis) const override;
 | |
| 
 | |
| #ifdef DEBUG
 | |
|   void SetInitialChildList(ChildListID aListID,
 | |
|                            nsFrameList&& aChildList) override;
 | |
| #endif
 | |
| 
 | |
|   /**
 | |
|    * Return the containing block for aChild which MUST be an abs.pos. child
 | |
|    * of a grid container and that container must have been reflowed.
 | |
|    */
 | |
|   static const nsRect& GridItemCB(nsIFrame* aChild);
 | |
| 
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridItemContainingBlockRect, nsRect)
 | |
| 
 | |
|   /**
 | |
|    * These properties are created by a call to
 | |
|    * nsGridContainerFrame::GetGridFrameWithComputedInfo, typically from
 | |
|    * Element::GetGridFragments.
 | |
|    */
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridColTrackInfo, ComputedGridTrackInfo)
 | |
|   const ComputedGridTrackInfo* GetComputedTemplateColumns() {
 | |
|     const ComputedGridTrackInfo* info = GetProperty(GridColTrackInfo());
 | |
|     MOZ_ASSERT(info, "Property generation wasn't requested.");
 | |
|     return info;
 | |
|   }
 | |
| 
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridRowTrackInfo, ComputedGridTrackInfo)
 | |
|   const ComputedGridTrackInfo* GetComputedTemplateRows() {
 | |
|     const ComputedGridTrackInfo* info = GetProperty(GridRowTrackInfo());
 | |
|     MOZ_ASSERT(info, "Property generation wasn't requested.");
 | |
|     return info;
 | |
|   }
 | |
| 
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridColumnLineInfo, ComputedGridLineInfo)
 | |
|   const ComputedGridLineInfo* GetComputedTemplateColumnLines() {
 | |
|     const ComputedGridLineInfo* info = GetProperty(GridColumnLineInfo());
 | |
|     MOZ_ASSERT(info, "Property generation wasn't requested.");
 | |
|     return info;
 | |
|   }
 | |
| 
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridRowLineInfo, ComputedGridLineInfo)
 | |
|   const ComputedGridLineInfo* GetComputedTemplateRowLines() {
 | |
|     const ComputedGridLineInfo* info = GetProperty(GridRowLineInfo());
 | |
|     MOZ_ASSERT(info, "Property generation wasn't requested.");
 | |
|     return info;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * This property is set by the creation of a dom::Grid object, and cleared
 | |
|    * during GC unlink. Since the Grid object manages the lifecycle, the property
 | |
|    * itself is set without a destructor. The property is also cleared whenever
 | |
|    * new grid computed info is generated during reflow, ensuring that we aren't
 | |
|    * holding a stale dom::Grid object.
 | |
|    */
 | |
|   NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(GridFragmentInfo, mozilla::dom::Grid)
 | |
|   mozilla::dom::Grid* GetGridFragmentInfo() {
 | |
|     return GetProperty(GridFragmentInfo());
 | |
|   }
 | |
| 
 | |
|   struct AtomKey {
 | |
|     RefPtr<nsAtom> mKey;
 | |
| 
 | |
|     explicit AtomKey(nsAtom* aAtom) : mKey(aAtom) {}
 | |
| 
 | |
|     using Lookup = nsAtom*;
 | |
| 
 | |
|     static mozilla::HashNumber hash(const Lookup& aKey) { return aKey->hash(); }
 | |
| 
 | |
|     static bool match(const AtomKey& aFirst, const Lookup& aSecond) {
 | |
|       return aFirst.mKey == aSecond;
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   using ImplicitNamedAreas = mozilla::HashMap<AtomKey, NamedArea, AtomKey>;
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(ImplicitNamedAreasProperty,
 | |
|                                       ImplicitNamedAreas)
 | |
|   ImplicitNamedAreas* GetImplicitNamedAreas() const {
 | |
|     return GetProperty(ImplicitNamedAreasProperty());
 | |
|   }
 | |
| 
 | |
|   using ExplicitNamedAreas = mozilla::StyleOwnedSlice<NamedArea>;
 | |
|   NS_DECLARE_FRAME_PROPERTY_DELETABLE(ExplicitNamedAreasProperty,
 | |
|                                       ExplicitNamedAreas)
 | |
|   ExplicitNamedAreas* GetExplicitNamedAreas() const {
 | |
|     return GetProperty(ExplicitNamedAreasProperty());
 | |
|   }
 | |
| 
 | |
|   using nsContainerFrame::IsMasonry;
 | |
| 
 | |
|   /** Return true if this frame has masonry layout in any axis. */
 | |
|   bool IsMasonry() const {
 | |
|     return HasAnyStateBits(NS_STATE_GRID_IS_ROW_MASONRY |
 | |
|                            NS_STATE_GRID_IS_COL_MASONRY);
 | |
|   }
 | |
| 
 | |
|   /** Return true if this frame is subgridded in its aAxis. */
 | |
|   bool IsSubgrid(LogicalAxis aAxis) const {
 | |
|     return HasAnyStateBits(aAxis == mozilla::eLogicalAxisBlock
 | |
|                                ? NS_STATE_GRID_IS_ROW_SUBGRID
 | |
|                                : NS_STATE_GRID_IS_COL_SUBGRID);
 | |
|   }
 | |
|   bool IsColSubgrid() const { return IsSubgrid(mozilla::eLogicalAxisInline); }
 | |
|   bool IsRowSubgrid() const { return IsSubgrid(mozilla::eLogicalAxisBlock); }
 | |
|   /** Return true if this frame is subgridded in any axis. */
 | |
|   bool IsSubgrid() const {
 | |
|     return HasAnyStateBits(NS_STATE_GRID_IS_ROW_SUBGRID |
 | |
|                            NS_STATE_GRID_IS_COL_SUBGRID);
 | |
|   }
 | |
| 
 | |
|   /** Return true if this frame has an item that is subgridded in our aAxis. */
 | |
|   bool HasSubgridItems(LogicalAxis aAxis) const {
 | |
|     return HasAnyStateBits(aAxis == mozilla::eLogicalAxisBlock
 | |
|                                ? NS_STATE_GRID_HAS_ROW_SUBGRID_ITEM
 | |
|                                : NS_STATE_GRID_HAS_COL_SUBGRID_ITEM);
 | |
|   }
 | |
|   /** Return true if this frame has any subgrid items. */
 | |
|   bool HasSubgridItems() const {
 | |
|     return HasAnyStateBits(NS_STATE_GRID_HAS_ROW_SUBGRID_ITEM |
 | |
|                            NS_STATE_GRID_HAS_COL_SUBGRID_ITEM);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return a container grid frame for the supplied frame, if available.
 | |
|    * @return nullptr if aFrame has no grid container.
 | |
|    */
 | |
|   static nsGridContainerFrame* GetGridContainerFrame(nsIFrame* aFrame);
 | |
| 
 | |
|   /**
 | |
|    * Return a container grid frame, and ensure it has computed grid info
 | |
|    * @return nullptr if aFrame has no grid container, or frame was destroyed
 | |
|    * @note this might destroy layout/style data since it may flush layout
 | |
|    */
 | |
|   MOZ_CAN_RUN_SCRIPT_BOUNDARY
 | |
|   static nsGridContainerFrame* GetGridFrameWithComputedInfo(nsIFrame* aFrame);
 | |
| 
 | |
|   struct Subgrid;
 | |
|   struct UsedTrackSizes;
 | |
|   struct TrackSize;
 | |
|   struct GridItemInfo;
 | |
|   struct GridReflowInput;
 | |
|   struct FindItemInGridOrderResult {
 | |
|     // The first(last) item in (reverse) grid order.
 | |
|     const GridItemInfo* mItem;
 | |
|     // Does the above item span the first(last) track?
 | |
|     bool mIsInEdgeTrack;
 | |
|   };
 | |
| 
 | |
|   /** Return our parent grid container; |this| MUST be a subgrid. */
 | |
|   nsGridContainerFrame* ParentGridContainerForSubgrid() const;
 | |
| 
 | |
|   // https://drafts.csswg.org/css-sizing/#constraints
 | |
|   enum class SizingConstraint {
 | |
|     MinContent,   // sizing under min-content constraint
 | |
|     MaxContent,   // sizing under max-content constraint
 | |
|     NoConstraint  // no constraint, used during Reflow
 | |
|   };
 | |
| 
 | |
|  protected:
 | |
|   typedef mozilla::LogicalPoint LogicalPoint;
 | |
|   typedef mozilla::LogicalRect LogicalRect;
 | |
|   typedef mozilla::LogicalSize LogicalSize;
 | |
|   typedef mozilla::WritingMode WritingMode;
 | |
|   struct Grid;
 | |
|   struct GridArea;
 | |
|   class LineNameMap;
 | |
|   struct LineRange;
 | |
|   struct SharedGridData;
 | |
|   struct SubgridFallbackTrackSizingFunctions;
 | |
|   struct TrackSizingFunctions;
 | |
|   struct Tracks;
 | |
|   struct TranslatedLineRange;
 | |
|   friend nsContainerFrame* NS_NewGridContainerFrame(
 | |
|       mozilla::PresShell* aPresShell, ComputedStyle* aStyle);
 | |
|   explicit nsGridContainerFrame(ComputedStyle* aStyle,
 | |
|                                 nsPresContext* aPresContext)
 | |
|       : nsContainerFrame(aStyle, aPresContext, kClassID),
 | |
|         mCachedMinISize(NS_INTRINSIC_ISIZE_UNKNOWN),
 | |
|         mCachedPrefISize(NS_INTRINSIC_ISIZE_UNKNOWN) {
 | |
|     for (auto& perAxisBaseline : mBaseline) {
 | |
|       for (auto& baseline : perAxisBaseline) {
 | |
|         baseline = NS_INTRINSIC_ISIZE_UNKNOWN;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * XXX temporary - move the ImplicitNamedAreas stuff to the style system.
 | |
|    * The implicit area names that come from x-start .. x-end lines in
 | |
|    * grid-template-columns / grid-template-rows are stored in this frame
 | |
|    * property when needed, as a ImplicitNamedAreas* value.
 | |
|    */
 | |
|   void InitImplicitNamedAreas(const nsStylePosition* aStyle);
 | |
| 
 | |
|   using LineNameList =
 | |
|       const mozilla::StyleOwnedSlice<mozilla::StyleCustomIdent>;
 | |
|   void AddImplicitNamedAreas(mozilla::Span<LineNameList>);
 | |
| 
 | |
|   /**
 | |
|    * Reflow and place our children.
 | |
|    * @return the consumed size of all of this grid container's continuations
 | |
|    *         so far including this frame
 | |
|    */
 | |
|   nscoord ReflowChildren(GridReflowInput& aState,
 | |
|                          const LogicalRect& aContentArea,
 | |
|                          const nsSize& aContainerSize,
 | |
|                          ReflowOutput& aDesiredSize, nsReflowStatus& aStatus);
 | |
| 
 | |
|   /**
 | |
|    * Helper for GetMinISize / GetPrefISize.
 | |
|    */
 | |
|   nscoord IntrinsicISize(gfxContext* aRenderingContext,
 | |
|                          mozilla::IntrinsicISizeType aConstraint);
 | |
| 
 | |
|   nscoord GetBBaseline(BaselineSharingGroup aBaselineGroup) const {
 | |
|     return mBaseline[mozilla::eLogicalAxisBlock][aBaselineGroup];
 | |
|   }
 | |
|   nscoord GetIBaseline(BaselineSharingGroup aBaselineGroup) const {
 | |
|     return mBaseline[mozilla::eLogicalAxisInline][aBaselineGroup];
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Calculate this grid container's baselines.
 | |
|    * @param aBaselineSet which baseline(s) to derive from a baseline-group or
 | |
|    * items; a baseline not included is synthesized from the border-box instead.
 | |
|    * @param aFragmentStartTrack is the first track in this fragment in the same
 | |
|    * axis as aMajor.  Pass zero if that's not the axis we're fragmenting in.
 | |
|    * @param aFirstExcludedTrack should be the first track in the next fragment
 | |
|    * or one beyond the final track in the last fragment, in aMajor's axis.
 | |
|    * Pass the number of tracks if that's not the axis we're fragmenting in.
 | |
|    */
 | |
|   enum BaselineSet : uint32_t {
 | |
|     eNone = 0x0,
 | |
|     eFirst = 0x1,
 | |
|     eLast = 0x2,
 | |
|     eBoth = eFirst | eLast,
 | |
|   };
 | |
|   void CalculateBaselines(BaselineSet aBaselineSet,
 | |
|                           mozilla::CSSOrderAwareFrameIterator* aIter,
 | |
|                           const nsTArray<GridItemInfo>* aGridItems,
 | |
|                           const Tracks& aTracks, uint32_t aFragmentStartTrack,
 | |
|                           uint32_t aFirstExcludedTrack, WritingMode aWM,
 | |
|                           const nsSize& aCBPhysicalSize,
 | |
|                           nscoord aCBBorderPaddingStart,
 | |
|                           nscoord aCBBorderPaddingStartEnd, nscoord aCBSize);
 | |
| 
 | |
|   /**
 | |
|    * Synthesize a Grid container baseline for aGroup.
 | |
|    */
 | |
|   nscoord SynthesizeBaseline(const FindItemInGridOrderResult& aItem,
 | |
|                              LogicalAxis aAxis, BaselineSharingGroup aGroup,
 | |
|                              const nsSize& aCBPhysicalSize, nscoord aCBSize,
 | |
|                              WritingMode aCBWM);
 | |
|   /**
 | |
|    * Find the first item in Grid Order in this fragment.
 | |
|    * https://drafts.csswg.org/css-grid/#grid-order
 | |
|    * @param aFragmentStartTrack is the first track in this fragment in the same
 | |
|    * axis as aMajor.  Pass zero if that's not the axis we're fragmenting in.
 | |
|    */
 | |
|   static FindItemInGridOrderResult FindFirstItemInGridOrder(
 | |
|       mozilla::CSSOrderAwareFrameIterator& aIter,
 | |
|       const nsTArray<GridItemInfo>& aGridItems, LineRange GridArea::*aMajor,
 | |
|       LineRange GridArea::*aMinor, uint32_t aFragmentStartTrack);
 | |
|   /**
 | |
|    * Find the last item in Grid Order in this fragment.
 | |
|    * @param aFragmentStartTrack is the first track in this fragment in the same
 | |
|    * axis as aMajor.  Pass zero if that's not the axis we're fragmenting in.
 | |
|    * @param aFirstExcludedTrack should be the first track in the next fragment
 | |
|    * or one beyond the final track in the last fragment, in aMajor's axis.
 | |
|    * Pass the number of tracks if that's not the axis we're fragmenting in.
 | |
|    */
 | |
|   static FindItemInGridOrderResult FindLastItemInGridOrder(
 | |
|       mozilla::ReverseCSSOrderAwareFrameIterator& aIter,
 | |
|       const nsTArray<GridItemInfo>& aGridItems, LineRange GridArea::*aMajor,
 | |
|       LineRange GridArea::*aMinor, uint32_t aFragmentStartTrack,
 | |
|       uint32_t aFirstExcludedTrack);
 | |
| 
 | |
|   /**
 | |
|    * Update our NS_STATE_GRID_IS_COL/ROW_SUBGRID bits and related subgrid state
 | |
|    * on our entire continuation chain based on the current style.
 | |
|    * This is needed because grid-template-columns/rows style changes only
 | |
|    * trigger a reflow so we need to update this dynamically.
 | |
|    */
 | |
|   void UpdateSubgridFrameState();
 | |
| 
 | |
|   /**
 | |
|    * Return the NS_STATE_GRID_IS_COL/ROW_SUBGRID and
 | |
|    * NS_STATE_GRID_IS_ROW/COL_MASONRY bits we ought to have.
 | |
|    */
 | |
|   nsFrameState ComputeSelfSubgridMasonryBits() const;
 | |
| 
 | |
|   /** Helper for ComputeSelfSubgridMasonryBits(). */
 | |
|   bool WillHaveAtLeastOneTrackInAxis(LogicalAxis aAxis) const;
 | |
| 
 | |
|  private:
 | |
|   // Helpers for ReflowChildren
 | |
|   struct Fragmentainer {
 | |
|     /**
 | |
|      * The distance from the first grid container fragment's block-axis content
 | |
|      * edge to the fragmentainer end.
 | |
|      */
 | |
|     nscoord mToFragmentainerEnd;
 | |
|     /**
 | |
|      * True if the current fragment is at the start of the fragmentainer.
 | |
|      */
 | |
|     bool mIsTopOfPage;
 | |
|     /**
 | |
|      * Is there a Class C break opportunity at the start content edge?
 | |
|      */
 | |
|     bool mCanBreakAtStart;
 | |
|     /**
 | |
|      * Is there a Class C break opportunity at the end content edge?
 | |
|      */
 | |
|     bool mCanBreakAtEnd;
 | |
|     /**
 | |
|      * Is the grid container's block-size unconstrained?
 | |
|      */
 | |
|     bool mIsAutoBSize;
 | |
|   };
 | |
| 
 | |
|   mozilla::Maybe<nsGridContainerFrame::Fragmentainer> GetNearestFragmentainer(
 | |
|       const GridReflowInput& aState) const;
 | |
| 
 | |
|   // @return the consumed size of all continuations so far including this frame
 | |
|   nscoord ReflowInFragmentainer(GridReflowInput& aState,
 | |
|                                 const LogicalRect& aContentArea,
 | |
|                                 ReflowOutput& aDesiredSize,
 | |
|                                 nsReflowStatus& aStatus,
 | |
|                                 Fragmentainer& aFragmentainer,
 | |
|                                 const nsSize& aContainerSize);
 | |
| 
 | |
|   // Helper for ReflowInFragmentainer
 | |
|   // @return the consumed size of all continuations so far including this frame
 | |
|   nscoord ReflowRowsInFragmentainer(
 | |
|       GridReflowInput& aState, const LogicalRect& aContentArea,
 | |
|       ReflowOutput& aDesiredSize, nsReflowStatus& aStatus,
 | |
|       Fragmentainer& aFragmentainer, const nsSize& aContainerSize,
 | |
|       const nsTArray<const GridItemInfo*>& aItems, uint32_t aStartRow,
 | |
|       uint32_t aEndRow, nscoord aBSize, nscoord aAvailableSize);
 | |
| 
 | |
|   // Helper for ReflowChildren / ReflowInFragmentainer
 | |
|   void ReflowInFlowChild(nsIFrame* aChild, const GridItemInfo* aGridItemInfo,
 | |
|                          nsSize aContainerSize,
 | |
|                          const mozilla::Maybe<nscoord>& aStretchBSize,
 | |
|                          const Fragmentainer* aFragmentainer,
 | |
|                          const GridReflowInput& aState,
 | |
|                          const LogicalRect& aContentArea,
 | |
|                          ReflowOutput& aDesiredSize, nsReflowStatus& aStatus);
 | |
| 
 | |
|   /**
 | |
|    * Places and reflows items when we have masonry layout.
 | |
|    * It handles unconstrained reflow and also fragmentation when the row axis
 | |
|    * is the masonry axis.  ReflowInFragmentainer handles the case when we're
 | |
|    * fragmenting and our row axis is a grid axis and it handles masonry layout
 | |
|    * in the column axis in that case.
 | |
|    * @return the intrinsic size in the masonry axis
 | |
|    */
 | |
|   nscoord MasonryLayout(GridReflowInput& aState,
 | |
|                         const LogicalRect& aContentArea,
 | |
|                         SizingConstraint aConstraint,
 | |
|                         ReflowOutput& aDesiredSize, nsReflowStatus& aStatus,
 | |
|                         Fragmentainer* aFragmentainer,
 | |
|                         const nsSize& aContainerSize);
 | |
| 
 | |
|   // Return the stored UsedTrackSizes, if any.
 | |
|   UsedTrackSizes* GetUsedTrackSizes() const;
 | |
| 
 | |
|   // Store the given TrackSizes in aAxis on a UsedTrackSizes frame property.
 | |
|   void StoreUsedTrackSizes(LogicalAxis aAxis,
 | |
|                            const nsTArray<TrackSize>& aSizes);
 | |
| 
 | |
|   /**
 | |
|    * Cached values to optimize GetMinISize/GetPrefISize.
 | |
|    */
 | |
|   nscoord mCachedMinISize;
 | |
|   nscoord mCachedPrefISize;
 | |
| 
 | |
|   // Our baselines, one per BaselineSharingGroup per axis.
 | |
|   PerLogicalAxis<PerBaseline<nscoord>> mBaseline;
 | |
| 
 | |
|  public:
 | |
|   // A cached result for a grid item's block-axis measuring reflow. This
 | |
|   // cache prevents us from doing exponential reflows in cases of deeply
 | |
|   // nested grid frames.
 | |
|   //
 | |
|   // We store the cached value in the grid item's frame property table.
 | |
|   //
 | |
|   // We cache the following as a "key"
 | |
|   //   - The size of the grid area in the item's inline axis
 | |
|   //   - The item's block axis baseline padding
 | |
|   // ...and we cache the following as the "value",
 | |
|   //   - The item's border-box BSize
 | |
|   class CachedBAxisMeasurement {
 | |
|    public:
 | |
|     NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(Prop, CachedBAxisMeasurement)
 | |
|     CachedBAxisMeasurement(const nsIFrame* aFrame, const LogicalSize& aCBSize,
 | |
|                            const nscoord aBSize)
 | |
|         : mKey(aFrame, aCBSize), mBSize(aBSize) {}
 | |
| 
 | |
|     CachedBAxisMeasurement() = default;
 | |
| 
 | |
|     bool IsValidFor(const nsIFrame* aFrame, const LogicalSize& aCBSize) const {
 | |
|       if (aFrame->IsSubtreeDirty()) {
 | |
|         return false;
 | |
|       }
 | |
| 
 | |
|       if (!CanCacheMeasurement(aFrame, aCBSize)) {
 | |
|         return false;
 | |
|       }
 | |
| 
 | |
|       return mKey == Key(aFrame, aCBSize);
 | |
|     }
 | |
| 
 | |
|     static bool CanCacheMeasurement(const nsIFrame* aFrame,
 | |
|                                     const LogicalSize& aCBSize) {
 | |
|       return Key::CanHash(aFrame, aCBSize);
 | |
|     }
 | |
| 
 | |
|     nscoord BSize() const { return mBSize; }
 | |
| 
 | |
|     void Update(const nsIFrame* aFrame, const LogicalSize& aCBSize,
 | |
|                 const nscoord aBSize) {
 | |
|       MOZ_ASSERT(CanCacheMeasurement(aFrame, aCBSize));
 | |
|       mKey.mHashKey = Key::GenerateHash(aFrame, aCBSize);
 | |
|       mBSize = aBSize;
 | |
|     }
 | |
| 
 | |
|    private:
 | |
|     struct Key {
 | |
|       // mHashKey is generated by combining these 2 variables together
 | |
|       //   1. The containing block size in the item's inline axis used
 | |
|       //   for measuring reflow
 | |
|       //   2. The item's baseline padding property
 | |
|       uint32_t mHashKey;
 | |
| 
 | |
|       Key() = default;
 | |
| 
 | |
|       Key(const nsIFrame* aFrame, const LogicalSize& aCBSize) {
 | |
|         MOZ_ASSERT(CanHash(aFrame, aCBSize));
 | |
|         mHashKey = GenerateHash(aFrame, aCBSize);
 | |
|       }
 | |
| 
 | |
|       void UpdateHash(const nsIFrame* aFrame, const LogicalSize& aCBSize) {
 | |
|         MOZ_ASSERT(CanHash(aFrame, aCBSize));
 | |
|         mHashKey = GenerateHash(aFrame, aCBSize);
 | |
|       }
 | |
| 
 | |
|       static uint32_t GenerateHash(const nsIFrame* aFrame,
 | |
|                                    const LogicalSize& aCBSize) {
 | |
|         MOZ_ASSERT(CanHash(aFrame, aCBSize));
 | |
| 
 | |
|         nscoord gridAreaISize = aCBSize.ISize(aFrame->GetWritingMode());
 | |
|         nscoord bBaselinePaddingProperty =
 | |
|             abs(aFrame->GetProperty(nsIFrame::BBaselinePadProperty()));
 | |
| 
 | |
|         uint_fast8_t bitsNeededForISize = mozilla::FloorLog2(gridAreaISize) + 1;
 | |
| 
 | |
|         return (gridAreaISize << (32 - bitsNeededForISize)) |
 | |
|                bBaselinePaddingProperty;
 | |
|       }
 | |
| 
 | |
|       static bool CanHash(const nsIFrame* aFrame, const LogicalSize& aCBSize) {
 | |
|         uint_fast8_t bitsNeededForISize =
 | |
|             mozilla::FloorLog2(aCBSize.ISize(aFrame->GetWritingMode())) + 1;
 | |
| 
 | |
|         uint_fast8_t bitsNeededForBBaselinePadding =
 | |
|             mozilla::FloorLog2(
 | |
|                 abs(aFrame->GetProperty(nsIFrame::BBaselinePadProperty()))) +
 | |
|             1;
 | |
| 
 | |
|         return bitsNeededForISize + bitsNeededForBBaselinePadding <= 32;
 | |
|       }
 | |
| 
 | |
|       bool operator==(const Key& aOther) const {
 | |
|         return mHashKey == aOther.mHashKey;
 | |
|       }
 | |
|     };
 | |
| 
 | |
|     Key mKey;
 | |
|     nscoord mBSize;
 | |
|   };
 | |
| 
 | |
|   bool CanProvideLineIterator() const final { return true; }
 | |
|   nsILineIterator* GetLineIterator() final { return this; }
 | |
|   int32_t GetNumLines() const final;
 | |
|   bool IsLineIteratorFlowRTL() final;
 | |
|   mozilla::Result<LineInfo, nsresult> GetLine(int32_t aLineNumber) final;
 | |
|   int32_t FindLineContaining(nsIFrame* aFrame, int32_t aStartLine = 0) final;
 | |
|   NS_IMETHOD FindFrameAt(int32_t aLineNumber, nsPoint aPos,
 | |
|                          nsIFrame** aFrameFound, bool* aPosIsBeforeFirstFrame,
 | |
|                          bool* aPosIsAfterLastFrame) final;
 | |
|   NS_IMETHOD CheckLineOrder(int32_t aLine, bool* aIsReordered,
 | |
|                             nsIFrame** aFirstVisual,
 | |
|                             nsIFrame** aLastVisual) final;
 | |
| };
 | |
| 
 | |
| #endif /* nsGridContainerFrame_h___ */
 |