1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* rendering object for CSS "display: grid | inline-grid" */
9 #ifndef nsGridContainerFrame_h___
10 #define nsGridContainerFrame_h___
12 #include "mozilla/CSSOrderAwareFrameIterator.h"
13 #include "mozilla/MathAlgorithms.h"
14 #include "mozilla/Maybe.h"
15 #include "mozilla/HashTable.h"
16 #include "nsContainerFrame.h"
17 #include "nsILineIterator.h"
21 } // namespace mozilla
25 * @return a newly allocated nsGridContainerFrame (infallible)
27 nsContainerFrame
* NS_NewGridContainerFrame(mozilla::PresShell
* aPresShell
,
28 mozilla::ComputedStyle
* aStyle
);
33 * The number of implicit / explicit tracks and their sizes.
35 struct ComputedGridTrackInfo
{
36 ComputedGridTrackInfo(
37 uint32_t aNumLeadingImplicitTracks
, uint32_t aNumExplicitTracks
,
38 uint32_t aStartFragmentTrack
, uint32_t aEndFragmentTrack
,
39 nsTArray
<nscoord
>&& aPositions
, nsTArray
<nscoord
>&& aSizes
,
40 nsTArray
<uint32_t>&& aStates
, nsTArray
<bool>&& aRemovedRepeatTracks
,
41 uint32_t aRepeatFirstTrack
,
42 nsTArray
<nsTArray
<StyleCustomIdent
>>&& aResolvedLineNames
,
43 bool aIsSubgrid
, bool aIsMasonry
)
44 : mNumLeadingImplicitTracks(aNumLeadingImplicitTracks
),
45 mNumExplicitTracks(aNumExplicitTracks
),
46 mStartFragmentTrack(aStartFragmentTrack
),
47 mEndFragmentTrack(aEndFragmentTrack
),
48 mPositions(std::move(aPositions
)),
49 mSizes(std::move(aSizes
)),
50 mStates(std::move(aStates
)),
51 mRemovedRepeatTracks(std::move(aRemovedRepeatTracks
)),
52 mResolvedLineNames(std::move(aResolvedLineNames
)),
53 mRepeatFirstTrack(aRepeatFirstTrack
),
54 mIsSubgrid(aIsSubgrid
),
55 mIsMasonry(aIsMasonry
) {}
56 uint32_t mNumLeadingImplicitTracks
;
57 uint32_t mNumExplicitTracks
;
58 uint32_t mStartFragmentTrack
;
59 uint32_t mEndFragmentTrack
;
60 nsTArray
<nscoord
> mPositions
;
61 nsTArray
<nscoord
> mSizes
;
62 nsTArray
<uint32_t> mStates
;
63 // Indicates if a track has been collapsed. This will be populated for each
64 // track in the repeat(auto-fit) and repeat(auto-fill), even if there are no
66 nsTArray
<bool> mRemovedRepeatTracks
;
67 // Contains lists of all line name lists, including the name lists inside
68 // repeats. When a repeat(auto) track exists, the internal track names will
69 // appear once each in this array.
70 nsTArray
<nsTArray
<StyleCustomIdent
>> mResolvedLineNames
;
71 uint32_t mRepeatFirstTrack
;
76 struct ComputedGridLineInfo
{
77 explicit ComputedGridLineInfo(
78 nsTArray
<nsTArray
<RefPtr
<nsAtom
>>>&& aNames
,
79 const nsTArray
<RefPtr
<nsAtom
>>& aNamesBefore
,
80 const nsTArray
<RefPtr
<nsAtom
>>& aNamesAfter
,
81 nsTArray
<RefPtr
<nsAtom
>>&& aNamesFollowingRepeat
)
82 : mNames(std::move(aNames
)),
83 mNamesBefore(aNamesBefore
.Clone()),
84 mNamesAfter(aNamesAfter
.Clone()),
85 mNamesFollowingRepeat(std::move(aNamesFollowingRepeat
)) {}
86 nsTArray
<nsTArray
<RefPtr
<nsAtom
>>> mNames
;
87 nsTArray
<RefPtr
<nsAtom
>> mNamesBefore
;
88 nsTArray
<RefPtr
<nsAtom
>> mNamesAfter
;
89 nsTArray
<RefPtr
<nsAtom
>> mNamesFollowingRepeat
;
91 } // namespace mozilla
93 class nsGridContainerFrame final
: public nsContainerFrame
,
94 public nsILineIterator
{
96 NS_DECL_FRAMEARENA_HELPERS(nsGridContainerFrame
)
98 using ComputedGridTrackInfo
= mozilla::ComputedGridTrackInfo
;
99 using ComputedGridLineInfo
= mozilla::ComputedGridLineInfo
;
100 using LogicalAxis
= mozilla::LogicalAxis
;
101 using BaselineSharingGroup
= mozilla::BaselineSharingGroup
;
102 using NamedArea
= mozilla::StyleNamedArea
;
104 template <typename T
>
105 using PerBaseline
= mozilla::EnumeratedArray
<BaselineSharingGroup
,
106 BaselineSharingGroup(2), T
>;
108 template <typename T
>
109 using PerLogicalAxis
=
110 mozilla::EnumeratedArray
<LogicalAxis
, LogicalAxis(2), T
>;
112 // nsIFrame overrides
113 void Reflow(nsPresContext
* aPresContext
, ReflowOutput
& aDesiredSize
,
114 const ReflowInput
& aReflowInput
,
115 nsReflowStatus
& aStatus
) override
;
116 void Init(nsIContent
* aContent
, nsContainerFrame
* aParent
,
117 nsIFrame
* aPrevInFlow
) override
;
118 void DidSetComputedStyle(ComputedStyle
* aOldStyle
) override
;
119 nscoord
GetMinISize(gfxContext
* aRenderingContext
) override
;
120 nscoord
GetPrefISize(gfxContext
* aRenderingContext
) override
;
121 void MarkIntrinsicISizesDirty() override
;
122 bool IsFrameOfType(uint32_t aFlags
) const override
{
123 return nsContainerFrame::IsFrameOfType(
124 aFlags
& ~nsIFrame::eCanContainOverflowContainers
);
127 void BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
128 const nsDisplayListSet
& aLists
) override
;
130 nscoord
GetLogicalBaseline(mozilla::WritingMode aWM
) const override
{
131 if (HasAnyStateBits(NS_STATE_GRID_SYNTHESIZE_BASELINE
)) {
132 // Return a baseline synthesized from our margin-box.
133 return nsContainerFrame::GetLogicalBaseline(aWM
);
136 GetBBaseline(BaselineSharingGroup::First
, &b
);
140 bool GetVerticalAlignBaseline(mozilla::WritingMode aWM
,
141 nscoord
* aBaseline
) const override
{
142 return GetNaturalBaselineBOffset(aWM
, BaselineSharingGroup::First
,
146 bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM
,
147 BaselineSharingGroup aBaselineGroup
,
148 nscoord
* aBaseline
) const override
{
149 if (StyleDisplay()->IsContainLayout() ||
150 HasAnyStateBits(NS_STATE_GRID_SYNTHESIZE_BASELINE
)) {
153 return GetBBaseline(aBaselineGroup
, aBaseline
);
156 #ifdef DEBUG_FRAME_DUMP
157 nsresult
GetFrameName(nsAString
& aResult
) const override
;
158 void ExtraContainerFrameInfo(nsACString
& aTo
) const override
;
161 // nsContainerFrame overrides
162 bool DrainSelfOverflowList() override
;
163 void AppendFrames(ChildListID aListID
, nsFrameList
&& aFrameList
) override
;
164 void InsertFrames(ChildListID aListID
, nsIFrame
* aPrevFrame
,
165 const nsLineList::iterator
* aPrevFrameLine
,
166 nsFrameList
&& aFrameList
) override
;
167 void RemoveFrame(ChildListID aListID
, nsIFrame
* aOldFrame
) override
;
168 mozilla::StyleAlignFlags
CSSAlignmentForAbsPosChild(
169 const ReflowInput
& aChildRI
, LogicalAxis aLogicalAxis
) const override
;
172 void SetInitialChildList(ChildListID aListID
,
173 nsFrameList
&& aChildList
) override
;
177 * Return the containing block for aChild which MUST be an abs.pos. child
178 * of a grid container and that container must have been reflowed.
180 static const nsRect
& GridItemCB(nsIFrame
* aChild
);
182 NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridItemContainingBlockRect
, nsRect
)
185 * These properties are created by a call to
186 * nsGridContainerFrame::GetGridFrameWithComputedInfo, typically from
187 * Element::GetGridFragments.
189 NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridColTrackInfo
, ComputedGridTrackInfo
)
190 const ComputedGridTrackInfo
* GetComputedTemplateColumns() {
191 const ComputedGridTrackInfo
* info
= GetProperty(GridColTrackInfo());
192 MOZ_ASSERT(info
, "Property generation wasn't requested.");
196 NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridRowTrackInfo
, ComputedGridTrackInfo
)
197 const ComputedGridTrackInfo
* GetComputedTemplateRows() {
198 const ComputedGridTrackInfo
* info
= GetProperty(GridRowTrackInfo());
199 MOZ_ASSERT(info
, "Property generation wasn't requested.");
203 NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridColumnLineInfo
, ComputedGridLineInfo
)
204 const ComputedGridLineInfo
* GetComputedTemplateColumnLines() {
205 const ComputedGridLineInfo
* info
= GetProperty(GridColumnLineInfo());
206 MOZ_ASSERT(info
, "Property generation wasn't requested.");
210 NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridRowLineInfo
, ComputedGridLineInfo
)
211 const ComputedGridLineInfo
* GetComputedTemplateRowLines() {
212 const ComputedGridLineInfo
* info
= GetProperty(GridRowLineInfo());
213 MOZ_ASSERT(info
, "Property generation wasn't requested.");
220 explicit AtomKey(nsAtom
* aAtom
) : mKey(aAtom
) {}
222 using Lookup
= nsAtom
*;
224 static mozilla::HashNumber
hash(const Lookup
& aKey
) { return aKey
->hash(); }
226 static bool match(const AtomKey
& aFirst
, const Lookup
& aSecond
) {
227 return aFirst
.mKey
== aSecond
;
231 using ImplicitNamedAreas
= mozilla::HashMap
<AtomKey
, NamedArea
, AtomKey
>;
232 NS_DECLARE_FRAME_PROPERTY_DELETABLE(ImplicitNamedAreasProperty
,
234 ImplicitNamedAreas
* GetImplicitNamedAreas() const {
235 return GetProperty(ImplicitNamedAreasProperty());
238 using ExplicitNamedAreas
= mozilla::StyleOwnedSlice
<NamedArea
>;
239 NS_DECLARE_FRAME_PROPERTY_DELETABLE(ExplicitNamedAreasProperty
,
241 ExplicitNamedAreas
* GetExplicitNamedAreas() const {
242 return GetProperty(ExplicitNamedAreasProperty());
245 using nsContainerFrame::IsMasonry
;
247 /** Return true if this frame has masonry layout in any axis. */
248 bool IsMasonry() const {
249 return HasAnyStateBits(NS_STATE_GRID_IS_ROW_MASONRY
|
250 NS_STATE_GRID_IS_COL_MASONRY
);
253 /** Return true if this frame is subgridded in its aAxis. */
254 bool IsSubgrid(LogicalAxis aAxis
) const {
255 return HasAnyStateBits(aAxis
== mozilla::eLogicalAxisBlock
256 ? NS_STATE_GRID_IS_ROW_SUBGRID
257 : NS_STATE_GRID_IS_COL_SUBGRID
);
259 bool IsColSubgrid() const { return IsSubgrid(mozilla::eLogicalAxisInline
); }
260 bool IsRowSubgrid() const { return IsSubgrid(mozilla::eLogicalAxisBlock
); }
261 /** Return true if this frame is subgridded in any axis. */
262 bool IsSubgrid() const {
263 return HasAnyStateBits(NS_STATE_GRID_IS_ROW_SUBGRID
|
264 NS_STATE_GRID_IS_COL_SUBGRID
);
267 /** Return true if this frame has an item that is subgridded in our aAxis. */
268 bool HasSubgridItems(LogicalAxis aAxis
) const {
269 return HasAnyStateBits(aAxis
== mozilla::eLogicalAxisBlock
270 ? NS_STATE_GRID_HAS_ROW_SUBGRID_ITEM
271 : NS_STATE_GRID_HAS_COL_SUBGRID_ITEM
);
273 /** Return true if this frame has any subgrid items. */
274 bool HasSubgridItems() const {
275 return HasAnyStateBits(NS_STATE_GRID_HAS_ROW_SUBGRID_ITEM
|
276 NS_STATE_GRID_HAS_COL_SUBGRID_ITEM
);
280 * Return a container grid frame for the supplied frame, if available.
281 * @return nullptr if aFrame has no grid container.
283 static nsGridContainerFrame
* GetGridContainerFrame(nsIFrame
* aFrame
);
286 * Return a container grid frame, and ensure it has computed grid info
287 * @return nullptr if aFrame has no grid container, or frame was destroyed
288 * @note this might destroy layout/style data since it may flush layout
290 MOZ_CAN_RUN_SCRIPT_BOUNDARY
291 static nsGridContainerFrame
* GetGridFrameWithComputedInfo(nsIFrame
* aFrame
);
294 struct UsedTrackSizes
;
297 struct GridReflowInput
;
298 struct FindItemInGridOrderResult
{
299 // The first(last) item in (reverse) grid order.
300 const GridItemInfo
* mItem
;
301 // Does the above item span the first(last) track?
305 /** Return our parent grid container; |this| MUST be a subgrid. */
306 nsGridContainerFrame
* ParentGridContainerForSubgrid() const;
308 // https://drafts.csswg.org/css-sizing/#constraints
309 enum class SizingConstraint
{
310 MinContent
, // sizing under min-content constraint
311 MaxContent
, // sizing under max-content constraint
312 NoConstraint
// no constraint, used during Reflow
316 typedef mozilla::LogicalPoint LogicalPoint
;
317 typedef mozilla::LogicalRect LogicalRect
;
318 typedef mozilla::LogicalSize LogicalSize
;
319 typedef mozilla::WritingMode WritingMode
;
324 struct SharedGridData
;
325 struct SubgridFallbackTrackSizingFunctions
;
326 struct TrackSizingFunctions
;
328 struct TranslatedLineRange
;
329 friend nsContainerFrame
* NS_NewGridContainerFrame(
330 mozilla::PresShell
* aPresShell
, ComputedStyle
* aStyle
);
331 explicit nsGridContainerFrame(ComputedStyle
* aStyle
,
332 nsPresContext
* aPresContext
)
333 : nsContainerFrame(aStyle
, aPresContext
, kClassID
),
334 mCachedMinISize(NS_INTRINSIC_ISIZE_UNKNOWN
),
335 mCachedPrefISize(NS_INTRINSIC_ISIZE_UNKNOWN
) {
336 for (auto& perAxisBaseline
: mBaseline
) {
337 for (auto& baseline
: perAxisBaseline
) {
338 baseline
= NS_INTRINSIC_ISIZE_UNKNOWN
;
344 * XXX temporary - move the ImplicitNamedAreas stuff to the style system.
345 * The implicit area names that come from x-start .. x-end lines in
346 * grid-template-columns / grid-template-rows are stored in this frame
347 * property when needed, as a ImplicitNamedAreas* value.
349 void InitImplicitNamedAreas(const nsStylePosition
* aStyle
);
352 const mozilla::StyleOwnedSlice
<mozilla::StyleCustomIdent
>;
353 void AddImplicitNamedAreas(mozilla::Span
<LineNameList
>);
356 * Reflow and place our children.
357 * @return the consumed size of all of this grid container's continuations
358 * so far including this frame
360 nscoord
ReflowChildren(GridReflowInput
& aState
,
361 const LogicalRect
& aContentArea
,
362 const nsSize
& aContainerSize
,
363 ReflowOutput
& aDesiredSize
, nsReflowStatus
& aStatus
);
366 * Helper for GetMinISize / GetPrefISize.
368 nscoord
IntrinsicISize(gfxContext
* aRenderingContext
,
369 mozilla::IntrinsicISizeType aConstraint
);
371 bool GetBBaseline(BaselineSharingGroup aBaselineGroup
,
372 nscoord
* aResult
) const {
373 *aResult
= mBaseline
[mozilla::eLogicalAxisBlock
][aBaselineGroup
];
376 bool GetIBaseline(BaselineSharingGroup aBaselineGroup
,
377 nscoord
* aResult
) const {
378 *aResult
= mBaseline
[mozilla::eLogicalAxisInline
][aBaselineGroup
];
383 * Calculate this grid container's baselines.
384 * @param aBaselineSet which baseline(s) to derive from a baseline-group or
385 * items; a baseline not included is synthesized from the border-box instead.
386 * @param aFragmentStartTrack is the first track in this fragment in the same
387 * axis as aMajor. Pass zero if that's not the axis we're fragmenting in.
388 * @param aFirstExcludedTrack should be the first track in the next fragment
389 * or one beyond the final track in the last fragment, in aMajor's axis.
390 * Pass the number of tracks if that's not the axis we're fragmenting in.
392 enum BaselineSet
: uint32_t {
396 eBoth
= eFirst
| eLast
,
398 void CalculateBaselines(BaselineSet aBaselineSet
,
399 mozilla::CSSOrderAwareFrameIterator
* aIter
,
400 const nsTArray
<GridItemInfo
>* aGridItems
,
401 const Tracks
& aTracks
, uint32_t aFragmentStartTrack
,
402 uint32_t aFirstExcludedTrack
, WritingMode aWM
,
403 const nsSize
& aCBPhysicalSize
,
404 nscoord aCBBorderPaddingStart
,
405 nscoord aCBBorderPaddingStartEnd
, nscoord aCBSize
);
408 * Synthesize a Grid container baseline for aGroup.
410 nscoord
SynthesizeBaseline(const FindItemInGridOrderResult
& aItem
,
411 LogicalAxis aAxis
, BaselineSharingGroup aGroup
,
412 const nsSize
& aCBPhysicalSize
, nscoord aCBSize
,
415 * Find the first item in Grid Order in this fragment.
416 * https://drafts.csswg.org/css-grid/#grid-order
417 * @param aFragmentStartTrack is the first track in this fragment in the same
418 * axis as aMajor. Pass zero if that's not the axis we're fragmenting in.
420 static FindItemInGridOrderResult
FindFirstItemInGridOrder(
421 mozilla::CSSOrderAwareFrameIterator
& aIter
,
422 const nsTArray
<GridItemInfo
>& aGridItems
, LineRange
GridArea::*aMajor
,
423 LineRange
GridArea::*aMinor
, uint32_t aFragmentStartTrack
);
425 * Find the last item in Grid Order in this fragment.
426 * @param aFragmentStartTrack is the first track in this fragment in the same
427 * axis as aMajor. Pass zero if that's not the axis we're fragmenting in.
428 * @param aFirstExcludedTrack should be the first track in the next fragment
429 * or one beyond the final track in the last fragment, in aMajor's axis.
430 * Pass the number of tracks if that's not the axis we're fragmenting in.
432 static FindItemInGridOrderResult
FindLastItemInGridOrder(
433 mozilla::ReverseCSSOrderAwareFrameIterator
& aIter
,
434 const nsTArray
<GridItemInfo
>& aGridItems
, LineRange
GridArea::*aMajor
,
435 LineRange
GridArea::*aMinor
, uint32_t aFragmentStartTrack
,
436 uint32_t aFirstExcludedTrack
);
439 * Update our NS_STATE_GRID_IS_COL/ROW_SUBGRID bits and related subgrid state
440 * on our entire continuation chain based on the current style.
441 * This is needed because grid-template-columns/rows style changes only
442 * trigger a reflow so we need to update this dynamically.
444 void UpdateSubgridFrameState();
447 * Return the NS_STATE_GRID_IS_COL/ROW_SUBGRID and
448 * NS_STATE_GRID_IS_ROW/COL_MASONRY bits we ought to have.
450 nsFrameState
ComputeSelfSubgridMasonryBits() const;
452 /** Helper for ComputeSelfSubgridMasonryBits(). */
453 bool WillHaveAtLeastOneTrackInAxis(LogicalAxis aAxis
) const;
456 // Helpers for ReflowChildren
457 struct Fragmentainer
{
459 * The distance from the first grid container fragment's block-axis content
460 * edge to the fragmentainer end.
462 nscoord mToFragmentainerEnd
;
464 * True if the current fragment is at the start of the fragmentainer.
468 * Is there a Class C break opportunity at the start content edge?
470 bool mCanBreakAtStart
;
472 * Is there a Class C break opportunity at the end content edge?
476 * Is the grid container's block-size unconstrained?
481 mozilla::Maybe
<nsGridContainerFrame::Fragmentainer
> GetNearestFragmentainer(
482 const GridReflowInput
& aState
) const;
484 // @return the consumed size of all continuations so far including this frame
485 nscoord
ReflowInFragmentainer(GridReflowInput
& aState
,
486 const LogicalRect
& aContentArea
,
487 ReflowOutput
& aDesiredSize
,
488 nsReflowStatus
& aStatus
,
489 Fragmentainer
& aFragmentainer
,
490 const nsSize
& aContainerSize
);
492 // Helper for ReflowInFragmentainer
493 // @return the consumed size of all continuations so far including this frame
494 nscoord
ReflowRowsInFragmentainer(
495 GridReflowInput
& aState
, const LogicalRect
& aContentArea
,
496 ReflowOutput
& aDesiredSize
, nsReflowStatus
& aStatus
,
497 Fragmentainer
& aFragmentainer
, const nsSize
& aContainerSize
,
498 const nsTArray
<const GridItemInfo
*>& aItems
, uint32_t aStartRow
,
499 uint32_t aEndRow
, nscoord aBSize
, nscoord aAvailableSize
);
501 // Helper for ReflowChildren / ReflowInFragmentainer
502 void ReflowInFlowChild(nsIFrame
* aChild
, const GridItemInfo
* aGridItemInfo
,
503 nsSize aContainerSize
,
504 const mozilla::Maybe
<nscoord
>& aStretchBSize
,
505 const Fragmentainer
* aFragmentainer
,
506 const GridReflowInput
& aState
,
507 const LogicalRect
& aContentArea
,
508 ReflowOutput
& aDesiredSize
, nsReflowStatus
& aStatus
);
511 * Places and reflows items when we have masonry layout.
512 * It handles unconstrained reflow and also fragmentation when the row axis
513 * is the masonry axis. ReflowInFragmentainer handles the case when we're
514 * fragmenting and our row axis is a grid axis and it handles masonry layout
515 * in the column axis in that case.
516 * @return the intrinsic size in the masonry axis
518 nscoord
MasonryLayout(GridReflowInput
& aState
,
519 const LogicalRect
& aContentArea
,
520 SizingConstraint aConstraint
,
521 ReflowOutput
& aDesiredSize
, nsReflowStatus
& aStatus
,
522 Fragmentainer
* aFragmentainer
,
523 const nsSize
& aContainerSize
);
525 // Return the stored UsedTrackSizes, if any.
526 UsedTrackSizes
* GetUsedTrackSizes() const;
528 // Store the given TrackSizes in aAxis on a UsedTrackSizes frame property.
529 void StoreUsedTrackSizes(LogicalAxis aAxis
,
530 const nsTArray
<TrackSize
>& aSizes
);
533 * Cached values to optimize GetMinISize/GetPrefISize.
535 nscoord mCachedMinISize
;
536 nscoord mCachedPrefISize
;
538 // Our baselines, one per BaselineSharingGroup per axis.
539 PerLogicalAxis
<PerBaseline
<nscoord
>> mBaseline
;
542 // A cached result for a grid item's block-axis measuring reflow. This
543 // cache prevents us from doing exponential reflows in cases of deeply
544 // nested grid frames.
546 // We store the cached value in the grid item's frame property table.
548 // We cache the following as a "key"
549 // - The size of the grid area in the item's inline axis
550 // - The item's block axis baseline padding
551 // ...and we cache the following as the "value",
552 // - The item's border-box BSize
553 class CachedBAxisMeasurement
{
555 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(Prop
, CachedBAxisMeasurement
)
556 CachedBAxisMeasurement(const nsIFrame
* aFrame
, const LogicalSize
& aCBSize
,
557 const nscoord aBSize
)
558 : mKey(aFrame
, aCBSize
), mBSize(aBSize
) {}
560 CachedBAxisMeasurement() = default;
562 bool IsValidFor(const nsIFrame
* aFrame
, const LogicalSize
& aCBSize
) const {
563 if (aFrame
->IsSubtreeDirty()) {
567 if (!CanCacheMeasurement(aFrame
, aCBSize
)) {
571 return mKey
== Key(aFrame
, aCBSize
);
574 static bool CanCacheMeasurement(const nsIFrame
* aFrame
,
575 const LogicalSize
& aCBSize
) {
576 return Key::CanHash(aFrame
, aCBSize
);
579 nscoord
BSize() const { return mBSize
; }
581 void Update(const nsIFrame
* aFrame
, const LogicalSize
& aCBSize
,
582 const nscoord aBSize
) {
583 MOZ_ASSERT(CanCacheMeasurement(aFrame
, aCBSize
));
584 mKey
.mHashKey
= Key::GenerateHash(aFrame
, aCBSize
);
590 // mHashKey is generated by combining these 2 variables together
591 // 1. The containing block size in the item's inline axis used
592 // for measuring reflow
593 // 2. The item's baseline padding property
598 Key(const nsIFrame
* aFrame
, const LogicalSize
& aCBSize
) {
599 MOZ_ASSERT(CanHash(aFrame
, aCBSize
));
600 mHashKey
= GenerateHash(aFrame
, aCBSize
);
603 void UpdateHash(const nsIFrame
* aFrame
, const LogicalSize
& aCBSize
) {
604 MOZ_ASSERT(CanHash(aFrame
, aCBSize
));
605 mHashKey
= GenerateHash(aFrame
, aCBSize
);
608 static uint32_t GenerateHash(const nsIFrame
* aFrame
,
609 const LogicalSize
& aCBSize
) {
610 MOZ_ASSERT(CanHash(aFrame
, aCBSize
));
612 nscoord gridAreaISize
= aCBSize
.ISize(aFrame
->GetWritingMode());
613 nscoord bBaselinePaddingProperty
=
614 abs(aFrame
->GetProperty(nsIFrame::BBaselinePadProperty()));
616 uint_fast8_t bitsNeededForISize
= mozilla::FloorLog2(gridAreaISize
) + 1;
618 return (gridAreaISize
<< (32 - bitsNeededForISize
)) |
619 bBaselinePaddingProperty
;
622 static bool CanHash(const nsIFrame
* aFrame
, const LogicalSize
& aCBSize
) {
623 uint_fast8_t bitsNeededForISize
=
624 mozilla::FloorLog2(aCBSize
.ISize(aFrame
->GetWritingMode())) + 1;
626 uint_fast8_t bitsNeededForBBaselinePadding
=
628 abs(aFrame
->GetProperty(nsIFrame::BBaselinePadProperty()))) +
631 return bitsNeededForISize
+ bitsNeededForBBaselinePadding
<= 32;
634 bool operator==(const Key
& aOther
) const {
635 return mHashKey
== aOther
.mHashKey
;
643 bool CanProvideLineIterator() const final
{ return true; }
644 nsILineIterator
* GetLineIterator() final
{ return this; }
645 int32_t GetNumLines() const final
;
646 bool IsLineIteratorFlowRTL() final
;
647 mozilla::Result
<LineInfo
, nsresult
> GetLine(int32_t aLineNumber
) final
;
648 int32_t FindLineContaining(nsIFrame
* aFrame
, int32_t aStartLine
= 0) final
;
649 NS_IMETHOD
FindFrameAt(int32_t aLineNumber
, nsPoint aPos
,
650 nsIFrame
** aFrameFound
, bool* aPosIsBeforeFirstFrame
,
651 bool* aPosIsAfterLastFrame
) final
;
652 NS_IMETHOD
CheckLineOrder(int32_t aLine
, bool* aIsReordered
,
653 nsIFrame
** aFirstVisual
,
654 nsIFrame
** aLastVisual
) final
;
657 #endif /* nsGridContainerFrame_h___ */