summaryrefslogtreecommitdiffstats
path: root/layout/generic/nsGridContainerFrame.h
diff options
context:
space:
mode:
Diffstat (limited to 'layout/generic/nsGridContainerFrame.h')
-rw-r--r--layout/generic/nsGridContainerFrame.h458
1 files changed, 458 insertions, 0 deletions
diff --git a/layout/generic/nsGridContainerFrame.h b/layout/generic/nsGridContainerFrame.h
new file mode 100644
index 000000000..e610dfa0b
--- /dev/null
+++ b/layout/generic/nsGridContainerFrame.h
@@ -0,0 +1,458 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code is subject to the terms of the Mozilla Public License
+ * version 2.0 (the "License"). You can obtain a copy of the License at
+ * http://mozilla.org/MPL/2.0/. */
+
+/* rendering object for CSS "display: grid | inline-grid" */
+
+#ifndef nsGridContainerFrame_h___
+#define nsGridContainerFrame_h___
+
+#include "mozilla/Maybe.h"
+#include "mozilla/TypeTraits.h"
+#include "nsContainerFrame.h"
+#include "nsHashKeys.h"
+#include "nsTHashtable.h"
+
+/**
+ * Factory function.
+ * @return a newly allocated nsGridContainerFrame (infallible)
+ */
+nsContainerFrame* NS_NewGridContainerFrame(nsIPresShell* aPresShell,
+ nsStyleContext* aContext);
+
+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)
+ : mNumLeadingImplicitTracks(aNumLeadingImplicitTracks)
+ , mNumExplicitTracks(aNumExplicitTracks)
+ , mStartFragmentTrack(aStartFragmentTrack)
+ , mEndFragmentTrack(aEndFragmentTrack)
+ , mPositions(aPositions)
+ , mSizes(aSizes)
+ , mStates(aStates)
+ , mRemovedRepeatTracks(aRemovedRepeatTracks)
+ , mRepeatFirstTrack(aRepeatFirstTrack)
+ {}
+ uint32_t mNumLeadingImplicitTracks;
+ uint32_t mNumExplicitTracks;
+ uint32_t mStartFragmentTrack;
+ uint32_t mEndFragmentTrack;
+ nsTArray<nscoord> mPositions;
+ nsTArray<nscoord> mSizes;
+ nsTArray<uint32_t> mStates;
+ nsTArray<bool> mRemovedRepeatTracks;
+ uint32_t mRepeatFirstTrack;
+};
+
+struct ComputedGridLineInfo
+{
+ explicit ComputedGridLineInfo(nsTArray<nsTArray<nsString>>&& aNames,
+ const nsTArray<nsString>& aNamesBefore,
+ const nsTArray<nsString>& aNamesAfter)
+ : mNames(aNames)
+ , mNamesBefore(aNamesBefore)
+ , mNamesAfter(aNamesAfter)
+ {}
+ nsTArray<nsTArray<nsString>> mNames;
+ nsTArray<nsString> mNamesBefore;
+ nsTArray<nsString> mNamesAfter;
+};
+} // namespace mozilla
+
+class nsGridContainerFrame final : public nsContainerFrame
+{
+public:
+ NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_QUERYFRAME_TARGET(nsGridContainerFrame)
+ NS_DECL_QUERYFRAME
+ typedef mozilla::ComputedGridTrackInfo ComputedGridTrackInfo;
+ typedef mozilla::ComputedGridLineInfo ComputedGridLineInfo;
+
+ // nsIFrame overrides
+ void Reflow(nsPresContext* aPresContext,
+ ReflowOutput& aDesiredSize,
+ const ReflowInput& aReflowInput,
+ nsReflowStatus& aStatus) override;
+ nscoord GetMinISize(nsRenderingContext* aRenderingContext) override;
+ nscoord GetPrefISize(nsRenderingContext* aRenderingContext) override;
+ void MarkIntrinsicISizesDirty() override;
+ nsIAtom* GetType() const override;
+ bool IsFrameOfType(uint32_t aFlags) const override
+ {
+ return nsContainerFrame::IsFrameOfType(aFlags &
+ ~nsIFrame::eCanContainOverflowContainers);
+ }
+
+ void BuildDisplayList(nsDisplayListBuilder* aBuilder,
+ const nsRect& aDirtyRect,
+ const nsDisplayListSet& aLists) override;
+
+ nscoord GetLogicalBaseline(mozilla::WritingMode aWM) const override
+ {
+ if (HasAnyStateBits(NS_STATE_GRID_SYNTHESIZE_BASELINE)) {
+ // Return a baseline synthesized from our margin-box.
+ return nsContainerFrame::GetLogicalBaseline(aWM);
+ }
+ nscoord b;
+ GetBBaseline(BaselineSharingGroup::eFirst, &b);
+ return b;
+ }
+
+ bool GetVerticalAlignBaseline(mozilla::WritingMode aWM,
+ nscoord* aBaseline) const override
+ {
+ return GetNaturalBaselineBOffset(aWM, BaselineSharingGroup::eFirst, aBaseline);
+ }
+
+ bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM,
+ BaselineSharingGroup aBaselineGroup,
+ nscoord* aBaseline) const override
+ {
+ if (HasAnyStateBits(NS_STATE_GRID_SYNTHESIZE_BASELINE)) {
+ return false;
+ }
+ return GetBBaseline(aBaselineGroup, aBaseline);
+ }
+
+#ifdef DEBUG_FRAME_DUMP
+ nsresult GetFrameName(nsAString& aResult) const override;
+#endif
+
+ // nsContainerFrame overrides
+ bool DrainSelfOverflowList() override;
+ void AppendFrames(ChildListID aListID, nsFrameList& aFrameList) override;
+ void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
+ nsFrameList& aFrameList) override;
+ void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override;
+ uint16_t CSSAlignmentForAbsPosChild(
+ const ReflowInput& aChildRI,
+ mozilla::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. This is just a helper method for
+ * nsAbsoluteContainingBlock::Reflow - it's not meant to be used elsewhere.
+ */
+ 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 = Properties().Get(GridColTrackInfo());
+ MOZ_ASSERT(info, "Property generation wasn't requested.");
+ return info;
+ }
+
+ NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridRowTrackInfo, ComputedGridTrackInfo)
+ const ComputedGridTrackInfo* GetComputedTemplateRows()
+ {
+ const ComputedGridTrackInfo* info = Properties().Get(GridRowTrackInfo());
+ MOZ_ASSERT(info, "Property generation wasn't requested.");
+ return info;
+ }
+
+ NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridColumnLineInfo, ComputedGridLineInfo)
+ const ComputedGridLineInfo* GetComputedTemplateColumnLines()
+ {
+ const ComputedGridLineInfo* info = Properties().Get(GridColumnLineInfo());
+ MOZ_ASSERT(info, "Property generation wasn't requested.");
+ return info;
+ }
+
+ NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridRowLineInfo, ComputedGridLineInfo)
+ const ComputedGridLineInfo* GetComputedTemplateRowLines()
+ {
+ const ComputedGridLineInfo* info = Properties().Get(GridRowLineInfo());
+ MOZ_ASSERT(info, "Property generation wasn't requested.");
+ return info;
+ }
+
+ typedef nsBaseHashtable<nsStringHashKey,
+ mozilla::css::GridNamedArea,
+ mozilla::css::GridNamedArea> ImplicitNamedAreas;
+ NS_DECLARE_FRAME_PROPERTY_DELETABLE(ImplicitNamedAreasProperty,
+ ImplicitNamedAreas)
+ ImplicitNamedAreas* GetImplicitNamedAreas() const {
+ return Properties().Get(ImplicitNamedAreasProperty());
+ }
+
+ typedef nsTArray<mozilla::css::GridNamedArea> ExplicitNamedAreas;
+ NS_DECLARE_FRAME_PROPERTY_DELETABLE(ExplicitNamedAreasProperty,
+ ExplicitNamedAreas)
+ ExplicitNamedAreas* GetExplicitNamedAreas() const {
+ return Properties().Get(ExplicitNamedAreasProperty());
+ }
+
+ /**
+ * Return a containing 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
+ */
+ static nsGridContainerFrame* GetGridFrameWithComputedInfo(nsIFrame* aFrame);
+
+ struct TrackSize;
+ struct GridItemInfo;
+ struct GridReflowInput;
+ template<typename Iterator> class GridItemCSSOrderIteratorT;
+ typedef GridItemCSSOrderIteratorT<nsFrameList::iterator>
+ GridItemCSSOrderIterator;
+ typedef GridItemCSSOrderIteratorT<nsFrameList::reverse_iterator>
+ ReverseGridItemCSSOrderIterator;
+ struct FindItemInGridOrderResult
+ {
+ // The first(last) item in (reverse) grid order.
+ const GridItemInfo* mItem;
+ // Does the above item span the first(last) track?
+ bool mIsInEdgeTrack;
+ };
+protected:
+ static const uint32_t kAutoLine;
+ // The maximum line number, in the zero-based translated grid.
+ static const uint32_t kTranslatedMaxLine;
+ typedef mozilla::LogicalPoint LogicalPoint;
+ typedef mozilla::LogicalRect LogicalRect;
+ typedef mozilla::LogicalSize LogicalSize;
+ typedef mozilla::WritingMode WritingMode;
+ typedef mozilla::css::GridNamedArea GridNamedArea;
+ typedef mozilla::layout::AutoFrameListPtr AutoFrameListPtr;
+ typedef nsLayoutUtils::IntrinsicISizeType IntrinsicISizeType;
+ struct Grid;
+ struct GridArea;
+ class LineNameMap;
+ struct LineRange;
+ struct SharedGridData;
+ struct TrackSizingFunctions;
+ struct Tracks;
+ struct TranslatedLineRange;
+ friend nsContainerFrame* NS_NewGridContainerFrame(nsIPresShell* aPresShell,
+ nsStyleContext* aContext);
+ explicit nsGridContainerFrame(nsStyleContext* aContext)
+ : nsContainerFrame(aContext)
+ , mCachedMinISize(NS_INTRINSIC_WIDTH_UNKNOWN)
+ , mCachedPrefISize(NS_INTRINSIC_WIDTH_UNKNOWN)
+ {
+ mBaseline[0][0] = NS_INTRINSIC_WIDTH_UNKNOWN;
+ mBaseline[0][1] = NS_INTRINSIC_WIDTH_UNKNOWN;
+ mBaseline[1][0] = NS_INTRINSIC_WIDTH_UNKNOWN;
+ mBaseline[1][1] = NS_INTRINSIC_WIDTH_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);
+ void AddImplicitNamedAreas(const nsTArray<nsTArray<nsString>>& aLineNameLists);
+
+ /**
+ * 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,
+ ReflowOutput& aDesiredSize,
+ nsReflowStatus& aStatus);
+
+ /**
+ * Helper for GetMinISize / GetPrefISize.
+ */
+ nscoord IntrinsicISize(nsRenderingContext* aRenderingContext,
+ IntrinsicISizeType aConstraint);
+
+ // Helper for AppendFrames / InsertFrames.
+ void NoteNewChildren(ChildListID aListID, const nsFrameList& aFrameList);
+
+ // Helper to move child frames into the kOverflowList.
+ void MergeSortedOverflow(nsFrameList& aList);
+ // Helper to move child frames into the kExcessOverflowContainersList:.
+ void MergeSortedExcessOverflowContainers(nsFrameList& aList);
+
+ bool GetBBaseline(BaselineSharingGroup aBaselineGroup, nscoord* aResult) const
+ {
+ *aResult = mBaseline[mozilla::eLogicalAxisBlock][aBaselineGroup];
+ return true;
+ }
+ bool GetIBaseline(BaselineSharingGroup aBaselineGroup, nscoord* aResult) const
+ {
+ *aResult = mBaseline[mozilla::eLogicalAxisInline][aBaselineGroup];
+ return true;
+ }
+
+ /**
+ * 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,
+ GridItemCSSOrderIterator* 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,
+ mozilla::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(GridItemCSSOrderIterator& 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(ReverseGridItemCSSOrderIterator& aIter,
+ const nsTArray<GridItemInfo>& aGridItems,
+ LineRange GridArea::* aMajor,
+ LineRange GridArea::* aMinor,
+ uint32_t aFragmentStartTrack,
+ uint32_t aFirstExcludedTrack);
+
+#ifdef DEBUG
+ void SanityCheckGridItemsBeforeReflow() const;
+#endif // DEBUG
+
+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,
+ mozilla::Maybe<nscoord> aStretchBSize,
+ const Fragmentainer* aFragmentainer,
+ const GridReflowInput& aState,
+ const LogicalRect& aContentArea,
+ ReflowOutput& aDesiredSize,
+ nsReflowStatus& aStatus);
+
+ /**
+ * Cached values to optimize GetMinISize/GetPrefISize.
+ */
+ nscoord mCachedMinISize;
+ nscoord mCachedPrefISize;
+
+ // Our baselines, one per BaselineSharingGroup per axis.
+ nscoord mBaseline[2/*LogicalAxis*/][2/*BaselineSharingGroup*/];
+
+#ifdef DEBUG
+ // If true, NS_STATE_GRID_DID_PUSH_ITEMS may be set even though all pushed
+ // frames may have been removed. This is used to suppress an assertion
+ // in case RemoveFrame removed all associated child frames.
+ bool mDidPushItemsBitMayLie;
+#endif
+};
+
+#endif /* nsGridContainerFrame_h___ */