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 "nsAtomHashKeys.h"
17 #include "nsContainerFrame.h"
18 #include "nsILineIterator.h"
25 } // namespace mozilla
29 * @return a newly allocated nsGridContainerFrame (infallible)
31 nsContainerFrame
* NS_NewGridContainerFrame(mozilla::PresShell
* aPresShell
,
32 mozilla::ComputedStyle
* aStyle
);
37 * The number of implicit / explicit tracks and their sizes.
39 struct ComputedGridTrackInfo
{
40 ComputedGridTrackInfo(
41 uint32_t aNumLeadingImplicitTracks
, uint32_t aNumExplicitTracks
,
42 uint32_t aStartFragmentTrack
, uint32_t aEndFragmentTrack
,
43 nsTArray
<nscoord
>&& aPositions
, nsTArray
<nscoord
>&& aSizes
,
44 nsTArray
<uint32_t>&& aStates
, nsTArray
<bool>&& aRemovedRepeatTracks
,
45 uint32_t aRepeatFirstTrack
,
46 nsTArray
<nsTArray
<StyleCustomIdent
>>&& aResolvedLineNames
,
47 bool aIsSubgrid
, bool aIsMasonry
)
48 : mNumLeadingImplicitTracks(aNumLeadingImplicitTracks
),
49 mNumExplicitTracks(aNumExplicitTracks
),
50 mStartFragmentTrack(aStartFragmentTrack
),
51 mEndFragmentTrack(aEndFragmentTrack
),
52 mPositions(std::move(aPositions
)),
53 mSizes(std::move(aSizes
)),
54 mStates(std::move(aStates
)),
55 mRemovedRepeatTracks(std::move(aRemovedRepeatTracks
)),
56 mResolvedLineNames(std::move(aResolvedLineNames
)),
57 mRepeatFirstTrack(aRepeatFirstTrack
),
58 mIsSubgrid(aIsSubgrid
),
59 mIsMasonry(aIsMasonry
) {}
60 uint32_t mNumLeadingImplicitTracks
;
61 uint32_t mNumExplicitTracks
;
62 uint32_t mStartFragmentTrack
;
63 uint32_t mEndFragmentTrack
;
64 nsTArray
<nscoord
> mPositions
;
65 nsTArray
<nscoord
> mSizes
;
66 nsTArray
<uint32_t> mStates
;
67 // Indicates if a track has been collapsed. This will be populated for each
68 // track in the repeat(auto-fit) and repeat(auto-fill), even if there are no
70 nsTArray
<bool> mRemovedRepeatTracks
;
71 // Contains lists of all line name lists, including the name lists inside
72 // repeats. When a repeat(auto) track exists, the internal track names will
73 // appear once each in this array.
74 nsTArray
<nsTArray
<StyleCustomIdent
>> mResolvedLineNames
;
75 uint32_t mRepeatFirstTrack
;
80 struct ComputedGridLineInfo
{
81 explicit ComputedGridLineInfo(
82 nsTArray
<nsTArray
<RefPtr
<nsAtom
>>>&& aNames
,
83 const nsTArray
<RefPtr
<nsAtom
>>& aNamesBefore
,
84 const nsTArray
<RefPtr
<nsAtom
>>& aNamesAfter
,
85 nsTArray
<RefPtr
<nsAtom
>>&& aNamesFollowingRepeat
)
86 : mNames(std::move(aNames
)),
87 mNamesBefore(aNamesBefore
.Clone()),
88 mNamesAfter(aNamesAfter
.Clone()),
89 mNamesFollowingRepeat(std::move(aNamesFollowingRepeat
)) {}
90 nsTArray
<nsTArray
<RefPtr
<nsAtom
>>> mNames
;
91 nsTArray
<RefPtr
<nsAtom
>> mNamesBefore
;
92 nsTArray
<RefPtr
<nsAtom
>> mNamesAfter
;
93 nsTArray
<RefPtr
<nsAtom
>> mNamesFollowingRepeat
;
95 } // namespace mozilla
97 class nsGridContainerFrame final
: public nsContainerFrame
,
98 public nsILineIterator
{
100 NS_DECL_FRAMEARENA_HELPERS(nsGridContainerFrame
)
102 using ComputedGridTrackInfo
= mozilla::ComputedGridTrackInfo
;
103 using ComputedGridLineInfo
= mozilla::ComputedGridLineInfo
;
104 using LogicalAxis
= mozilla::LogicalAxis
;
105 using BaselineSharingGroup
= mozilla::BaselineSharingGroup
;
106 using NamedArea
= mozilla::StyleNamedArea
;
108 template <typename T
>
109 using PerBaseline
= mozilla::EnumeratedArray
<BaselineSharingGroup
,
110 BaselineSharingGroup(2), T
>;
112 template <typename T
>
113 using PerLogicalAxis
=
114 mozilla::EnumeratedArray
<LogicalAxis
, LogicalAxis(2), T
>;
116 // nsIFrame overrides
117 void Reflow(nsPresContext
* aPresContext
, ReflowOutput
& aDesiredSize
,
118 const ReflowInput
& aReflowInput
,
119 nsReflowStatus
& aStatus
) override
;
120 void Init(nsIContent
* aContent
, nsContainerFrame
* aParent
,
121 nsIFrame
* aPrevInFlow
) override
;
122 void DidSetComputedStyle(ComputedStyle
* aOldStyle
) override
;
123 nscoord
GetMinISize(gfxContext
* aRenderingContext
) override
;
124 nscoord
GetPrefISize(gfxContext
* aRenderingContext
) override
;
125 void MarkIntrinsicISizesDirty() override
;
127 void BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
128 const nsDisplayListSet
& aLists
) override
;
130 Maybe
<nscoord
> GetNaturalBaselineBOffset(
131 mozilla::WritingMode aWM
, BaselineSharingGroup aBaselineGroup
,
132 BaselineExportContext
) const override
{
133 if (StyleDisplay()->IsContainLayout() ||
134 HasAnyStateBits(NS_STATE_GRID_SYNTHESIZE_BASELINE
)) {
137 return mozilla::Some(GetBBaseline(aBaselineGroup
));
140 #ifdef DEBUG_FRAME_DUMP
141 nsresult
GetFrameName(nsAString
& aResult
) const override
;
142 void ExtraContainerFrameInfo(nsACString
& aTo
) const override
;
145 // nsContainerFrame overrides
146 bool DrainSelfOverflowList() override
;
147 void AppendFrames(ChildListID aListID
, nsFrameList
&& aFrameList
) override
;
148 void InsertFrames(ChildListID aListID
, nsIFrame
* aPrevFrame
,
149 const nsLineList::iterator
* aPrevFrameLine
,
150 nsFrameList
&& aFrameList
) override
;
151 void RemoveFrame(DestroyContext
&, ChildListID
, nsIFrame
*) override
;
152 mozilla::StyleAlignFlags
CSSAlignmentForAbsPosChild(
153 const ReflowInput
& aChildRI
, LogicalAxis aLogicalAxis
) const override
;
156 void SetInitialChildList(ChildListID aListID
,
157 nsFrameList
&& aChildList
) override
;
161 * Return the containing block for aChild which MUST be an abs.pos. child
162 * of a grid container and that container must have been reflowed.
164 static const nsRect
& GridItemCB(nsIFrame
* aChild
);
166 NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridItemContainingBlockRect
, nsRect
)
169 * These properties are created by a call to
170 * nsGridContainerFrame::GetGridFrameWithComputedInfo, typically from
171 * Element::GetGridFragments.
173 NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridColTrackInfo
, ComputedGridTrackInfo
)
174 const ComputedGridTrackInfo
* GetComputedTemplateColumns() {
175 const ComputedGridTrackInfo
* info
= GetProperty(GridColTrackInfo());
176 MOZ_ASSERT(info
, "Property generation wasn't requested.");
180 NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridRowTrackInfo
, ComputedGridTrackInfo
)
181 const ComputedGridTrackInfo
* GetComputedTemplateRows() {
182 const ComputedGridTrackInfo
* info
= GetProperty(GridRowTrackInfo());
183 MOZ_ASSERT(info
, "Property generation wasn't requested.");
187 NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridColumnLineInfo
, ComputedGridLineInfo
)
188 const ComputedGridLineInfo
* GetComputedTemplateColumnLines() {
189 const ComputedGridLineInfo
* info
= GetProperty(GridColumnLineInfo());
190 MOZ_ASSERT(info
, "Property generation wasn't requested.");
194 NS_DECLARE_FRAME_PROPERTY_DELETABLE(GridRowLineInfo
, ComputedGridLineInfo
)
195 const ComputedGridLineInfo
* GetComputedTemplateRowLines() {
196 const ComputedGridLineInfo
* info
= GetProperty(GridRowLineInfo());
197 MOZ_ASSERT(info
, "Property generation wasn't requested.");
202 * This property is set by the creation of a dom::Grid object, and cleared
203 * during GC unlink. Since the Grid object manages the lifecycle, the property
204 * itself is set without a destructor. The property is also cleared whenever
205 * new grid computed info is generated during reflow, ensuring that we aren't
206 * holding a stale dom::Grid object.
208 NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(GridFragmentInfo
, mozilla::dom::Grid
)
209 mozilla::dom::Grid
* GetGridFragmentInfo() {
210 return GetProperty(GridFragmentInfo());
213 using ImplicitNamedAreas
=
214 mozilla::HashMap
<mozilla::AtomHashKey
, NamedArea
, mozilla::AtomHashKey
>;
215 NS_DECLARE_FRAME_PROPERTY_DELETABLE(ImplicitNamedAreasProperty
,
217 ImplicitNamedAreas
* GetImplicitNamedAreas() const {
218 return GetProperty(ImplicitNamedAreasProperty());
221 using ExplicitNamedAreas
= mozilla::StyleOwnedSlice
<NamedArea
>;
222 NS_DECLARE_FRAME_PROPERTY_DELETABLE(ExplicitNamedAreasProperty
,
224 ExplicitNamedAreas
* GetExplicitNamedAreas() const {
225 return GetProperty(ExplicitNamedAreasProperty());
228 using nsContainerFrame::IsMasonry
;
230 /** Return true if this frame has masonry layout in any axis. */
231 bool IsMasonry() const {
232 return HasAnyStateBits(NS_STATE_GRID_IS_ROW_MASONRY
|
233 NS_STATE_GRID_IS_COL_MASONRY
);
236 /** Return true if this frame is subgridded in its aAxis. */
237 bool IsSubgrid(LogicalAxis aAxis
) const {
238 return HasAnyStateBits(aAxis
== mozilla::eLogicalAxisBlock
239 ? NS_STATE_GRID_IS_ROW_SUBGRID
240 : NS_STATE_GRID_IS_COL_SUBGRID
);
242 bool IsColSubgrid() const { return IsSubgrid(mozilla::eLogicalAxisInline
); }
243 bool IsRowSubgrid() const { return IsSubgrid(mozilla::eLogicalAxisBlock
); }
244 /** Return true if this frame is subgridded in any axis. */
245 bool IsSubgrid() const {
246 return HasAnyStateBits(NS_STATE_GRID_IS_ROW_SUBGRID
|
247 NS_STATE_GRID_IS_COL_SUBGRID
);
250 /** Return true if this frame has an item that is subgridded in our aAxis. */
251 bool HasSubgridItems(LogicalAxis aAxis
) const {
252 return HasAnyStateBits(aAxis
== mozilla::eLogicalAxisBlock
253 ? NS_STATE_GRID_HAS_ROW_SUBGRID_ITEM
254 : NS_STATE_GRID_HAS_COL_SUBGRID_ITEM
);
256 /** Return true if this frame has any subgrid items. */
257 bool HasSubgridItems() const {
258 return HasAnyStateBits(NS_STATE_GRID_HAS_ROW_SUBGRID_ITEM
|
259 NS_STATE_GRID_HAS_COL_SUBGRID_ITEM
);
263 * Return a container grid frame for the supplied frame, if available.
264 * @return nullptr if aFrame has no grid container.
266 static nsGridContainerFrame
* GetGridContainerFrame(nsIFrame
* aFrame
);
269 * Return a container grid frame, and ensure it has computed grid info
270 * @return nullptr if aFrame has no grid container, or frame was destroyed
271 * @note this might destroy layout/style data since it may flush layout
273 MOZ_CAN_RUN_SCRIPT_BOUNDARY
274 static nsGridContainerFrame
* GetGridFrameWithComputedInfo(nsIFrame
* aFrame
);
277 struct UsedTrackSizes
;
280 struct GridReflowInput
;
281 struct FindItemInGridOrderResult
{
282 // The first(last) item in (reverse) grid order.
283 const GridItemInfo
* mItem
;
284 // Does the above item span the first(last) track?
288 /** Return our parent grid container; |this| MUST be a subgrid. */
289 nsGridContainerFrame
* ParentGridContainerForSubgrid() const;
291 // https://drafts.csswg.org/css-sizing/#constraints
292 enum class SizingConstraint
{
293 MinContent
, // sizing under min-content constraint
294 MaxContent
, // sizing under max-content constraint
295 NoConstraint
// no constraint, used during Reflow
299 typedef mozilla::LogicalPoint LogicalPoint
;
300 typedef mozilla::LogicalRect LogicalRect
;
301 typedef mozilla::LogicalSize LogicalSize
;
302 typedef mozilla::WritingMode WritingMode
;
307 struct SharedGridData
;
308 struct SubgridFallbackTrackSizingFunctions
;
309 struct TrackSizingFunctions
;
311 struct TranslatedLineRange
;
312 friend nsContainerFrame
* NS_NewGridContainerFrame(
313 mozilla::PresShell
* aPresShell
, ComputedStyle
* aStyle
);
314 explicit nsGridContainerFrame(ComputedStyle
* aStyle
,
315 nsPresContext
* aPresContext
)
316 : nsContainerFrame(aStyle
, aPresContext
, kClassID
),
317 mCachedMinISize(NS_INTRINSIC_ISIZE_UNKNOWN
),
318 mCachedPrefISize(NS_INTRINSIC_ISIZE_UNKNOWN
) {
319 for (auto& perAxisBaseline
: mBaseline
) {
320 for (auto& baseline
: perAxisBaseline
) {
321 baseline
= NS_INTRINSIC_ISIZE_UNKNOWN
;
327 * XXX temporary - move the ImplicitNamedAreas stuff to the style system.
328 * The implicit area names that come from x-start .. x-end lines in
329 * grid-template-columns / grid-template-rows are stored in this frame
330 * property when needed, as a ImplicitNamedAreas* value.
332 void InitImplicitNamedAreas(const nsStylePosition
* aStyle
);
335 const mozilla::StyleOwnedSlice
<mozilla::StyleCustomIdent
>;
336 void AddImplicitNamedAreas(mozilla::Span
<LineNameList
>);
337 using StyleLineNameListValue
=
338 const mozilla::StyleGenericLineNameListValue
<mozilla::StyleInteger
>;
339 void AddImplicitNamedAreas(mozilla::Span
<StyleLineNameListValue
>);
342 * Reflow and place our children.
343 * @return the consumed size of all of this grid container's continuations
344 * so far including this frame
346 nscoord
ReflowChildren(GridReflowInput
& aState
,
347 const LogicalRect
& aContentArea
,
348 const nsSize
& aContainerSize
,
349 ReflowOutput
& aDesiredSize
, nsReflowStatus
& aStatus
);
352 * Helper for GetMinISize / GetPrefISize.
354 nscoord
IntrinsicISize(gfxContext
* aRenderingContext
,
355 mozilla::IntrinsicISizeType aConstraint
);
357 nscoord
GetBBaseline(BaselineSharingGroup aBaselineGroup
) const {
358 return mBaseline
[mozilla::eLogicalAxisBlock
][aBaselineGroup
];
360 nscoord
GetIBaseline(BaselineSharingGroup aBaselineGroup
) const {
361 return mBaseline
[mozilla::eLogicalAxisInline
][aBaselineGroup
];
365 * Calculate this grid container's baselines.
366 * @param aBaselineSet which baseline(s) to derive from a baseline-group or
367 * items; a baseline not included is synthesized from the border-box instead.
368 * @param aFragmentStartTrack is the first track in this fragment in the same
369 * axis as aMajor. Pass zero if that's not the axis we're fragmenting in.
370 * @param aFirstExcludedTrack should be the first track in the next fragment
371 * or one beyond the final track in the last fragment, in aMajor's axis.
372 * Pass the number of tracks if that's not the axis we're fragmenting in.
374 enum BaselineSet
: uint32_t {
378 eBoth
= eFirst
| eLast
,
380 void CalculateBaselines(BaselineSet aBaselineSet
,
381 mozilla::CSSOrderAwareFrameIterator
* aIter
,
382 const nsTArray
<GridItemInfo
>* aGridItems
,
383 const Tracks
& aTracks
, uint32_t aFragmentStartTrack
,
384 uint32_t aFirstExcludedTrack
, WritingMode aWM
,
385 const nsSize
& aCBPhysicalSize
,
386 nscoord aCBBorderPaddingStart
,
387 nscoord aCBBorderPaddingStartEnd
, nscoord aCBSize
);
390 * Synthesize a Grid container baseline for aGroup.
392 nscoord
SynthesizeBaseline(const FindItemInGridOrderResult
& aItem
,
393 LogicalAxis aAxis
, BaselineSharingGroup aGroup
,
394 const nsSize
& aCBPhysicalSize
, nscoord aCBSize
,
397 * Find the first item in Grid Order in this fragment.
398 * https://drafts.csswg.org/css-grid/#grid-order
399 * @param aFragmentStartTrack is the first track in this fragment in the same
400 * axis as aMajor. Pass zero if that's not the axis we're fragmenting in.
402 static FindItemInGridOrderResult
FindFirstItemInGridOrder(
403 mozilla::CSSOrderAwareFrameIterator
& aIter
,
404 const nsTArray
<GridItemInfo
>& aGridItems
, LineRange
GridArea::*aMajor
,
405 LineRange
GridArea::*aMinor
, uint32_t aFragmentStartTrack
);
407 * Find the last item in Grid Order in this fragment.
408 * @param aFragmentStartTrack is the first track in this fragment in the same
409 * axis as aMajor. Pass zero if that's not the axis we're fragmenting in.
410 * @param aFirstExcludedTrack should be the first track in the next fragment
411 * or one beyond the final track in the last fragment, in aMajor's axis.
412 * Pass the number of tracks if that's not the axis we're fragmenting in.
414 static FindItemInGridOrderResult
FindLastItemInGridOrder(
415 mozilla::ReverseCSSOrderAwareFrameIterator
& aIter
,
416 const nsTArray
<GridItemInfo
>& aGridItems
, LineRange
GridArea::*aMajor
,
417 LineRange
GridArea::*aMinor
, uint32_t aFragmentStartTrack
,
418 uint32_t aFirstExcludedTrack
);
421 * Update our NS_STATE_GRID_IS_COL/ROW_SUBGRID bits and related subgrid state
422 * on our entire continuation chain based on the current style.
423 * This is needed because grid-template-columns/rows style changes only
424 * trigger a reflow so we need to update this dynamically.
426 void UpdateSubgridFrameState();
429 * Return the NS_STATE_GRID_IS_COL/ROW_SUBGRID and
430 * NS_STATE_GRID_IS_ROW/COL_MASONRY bits we ought to have.
432 nsFrameState
ComputeSelfSubgridMasonryBits() const;
434 /** Helper for ComputeSelfSubgridMasonryBits(). */
435 bool WillHaveAtLeastOneTrackInAxis(LogicalAxis aAxis
) const;
438 // Helpers for ReflowChildren
439 struct Fragmentainer
{
441 * The distance from the first grid container fragment's block-axis content
442 * edge to the fragmentainer end.
444 nscoord mToFragmentainerEnd
;
446 * True if the current fragment is at the start of the fragmentainer.
450 * Is there a Class C break opportunity at the start content edge?
452 bool mCanBreakAtStart
;
454 * Is there a Class C break opportunity at the end content edge?
458 * Is the grid container's block-size unconstrained?
463 mozilla::Maybe
<nsGridContainerFrame::Fragmentainer
> GetNearestFragmentainer(
464 const GridReflowInput
& aState
) const;
466 // @return the consumed size of all continuations so far including this frame
467 nscoord
ReflowInFragmentainer(GridReflowInput
& aState
,
468 const LogicalRect
& aContentArea
,
469 ReflowOutput
& aDesiredSize
,
470 nsReflowStatus
& aStatus
,
471 Fragmentainer
& aFragmentainer
,
472 const nsSize
& aContainerSize
);
474 // Helper for ReflowInFragmentainer
475 // @return the consumed size of all continuations so far including this frame
476 nscoord
ReflowRowsInFragmentainer(
477 GridReflowInput
& aState
, const LogicalRect
& aContentArea
,
478 ReflowOutput
& aDesiredSize
, nsReflowStatus
& aStatus
,
479 Fragmentainer
& aFragmentainer
, const nsSize
& aContainerSize
,
480 const nsTArray
<const GridItemInfo
*>& aItems
, uint32_t aStartRow
,
481 uint32_t aEndRow
, nscoord aBSize
, nscoord aAvailableSize
);
483 // Helper for ReflowChildren / ReflowInFragmentainer
484 void ReflowInFlowChild(nsIFrame
* aChild
, const GridItemInfo
* aGridItemInfo
,
485 nsSize aContainerSize
,
486 const mozilla::Maybe
<nscoord
>& aStretchBSize
,
487 const Fragmentainer
* aFragmentainer
,
488 const GridReflowInput
& aState
,
489 const LogicalRect
& aContentArea
,
490 ReflowOutput
& aDesiredSize
, nsReflowStatus
& aStatus
);
493 * Places and reflows items when we have masonry layout.
494 * It handles unconstrained reflow and also fragmentation when the row axis
495 * is the masonry axis. ReflowInFragmentainer handles the case when we're
496 * fragmenting and our row axis is a grid axis and it handles masonry layout
497 * in the column axis in that case.
498 * @return the intrinsic size in the masonry axis
500 nscoord
MasonryLayout(GridReflowInput
& aState
,
501 const LogicalRect
& aContentArea
,
502 SizingConstraint aConstraint
,
503 ReflowOutput
& aDesiredSize
, nsReflowStatus
& aStatus
,
504 Fragmentainer
* aFragmentainer
,
505 const nsSize
& aContainerSize
);
507 // Return the stored UsedTrackSizes, if any.
508 UsedTrackSizes
* GetUsedTrackSizes() const;
510 // Store the given TrackSizes in aAxis on a UsedTrackSizes frame property.
511 void StoreUsedTrackSizes(LogicalAxis aAxis
,
512 const nsTArray
<TrackSize
>& aSizes
);
514 // The internal implementation for AddImplicitNamedAreas().
515 void AddImplicitNamedAreasInternal(LineNameList
& aNameList
,
516 ImplicitNamedAreas
*& aAreas
);
519 * Cached values to optimize GetMinISize/GetPrefISize.
521 nscoord mCachedMinISize
;
522 nscoord mCachedPrefISize
;
524 // Our baselines, one per BaselineSharingGroup per axis.
525 PerLogicalAxis
<PerBaseline
<nscoord
>> mBaseline
;
528 // A cached result for a grid item's block-axis measuring reflow. This
529 // cache prevents us from doing exponential reflows in cases of deeply
530 // nested grid frames.
532 // We store the cached value in the grid item's frame property table.
534 // We cache the following as a "key"
535 // - The size of the grid area in the item's inline axis
536 // - The item's block axis baseline padding
537 // ...and we cache the following as the "value",
538 // - The item's border-box BSize
539 class CachedBAxisMeasurement
{
541 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(Prop
, CachedBAxisMeasurement
)
542 CachedBAxisMeasurement(const nsIFrame
* aFrame
, const LogicalSize
& aCBSize
,
543 const nscoord aBSize
)
544 : mKey(aFrame
, aCBSize
), mBSize(aBSize
) {}
546 CachedBAxisMeasurement() = default;
548 bool IsValidFor(const nsIFrame
* aFrame
, const LogicalSize
& aCBSize
) const {
549 if (aFrame
->IsSubtreeDirty()) {
553 if (!CanCacheMeasurement(aFrame
, aCBSize
)) {
557 return mKey
== Key(aFrame
, aCBSize
);
560 static bool CanCacheMeasurement(const nsIFrame
* aFrame
,
561 const LogicalSize
& aCBSize
) {
562 return Key::CanHash(aFrame
, aCBSize
);
565 nscoord
BSize() const { return mBSize
; }
567 void Update(const nsIFrame
* aFrame
, const LogicalSize
& aCBSize
,
568 const nscoord aBSize
) {
569 MOZ_ASSERT(CanCacheMeasurement(aFrame
, aCBSize
));
570 mKey
.mHashKey
= Key::GenerateHash(aFrame
, aCBSize
);
576 // mHashKey is generated by combining these 2 variables together
577 // 1. The containing block size in the item's inline axis used
578 // for measuring reflow
579 // 2. The item's baseline padding property
584 Key(const nsIFrame
* aFrame
, const LogicalSize
& aCBSize
) {
585 MOZ_ASSERT(CanHash(aFrame
, aCBSize
));
586 mHashKey
= GenerateHash(aFrame
, aCBSize
);
589 void UpdateHash(const nsIFrame
* aFrame
, const LogicalSize
& aCBSize
) {
590 MOZ_ASSERT(CanHash(aFrame
, aCBSize
));
591 mHashKey
= GenerateHash(aFrame
, aCBSize
);
594 static uint32_t GenerateHash(const nsIFrame
* aFrame
,
595 const LogicalSize
& aCBSize
) {
596 MOZ_ASSERT(CanHash(aFrame
, aCBSize
));
598 nscoord gridAreaISize
= aCBSize
.ISize(aFrame
->GetWritingMode());
599 nscoord bBaselinePaddingProperty
=
600 abs(aFrame
->GetProperty(nsIFrame::BBaselinePadProperty()));
602 uint_fast8_t bitsNeededForISize
= mozilla::FloorLog2(gridAreaISize
) + 1;
604 return (gridAreaISize
<< (32 - bitsNeededForISize
)) |
605 bBaselinePaddingProperty
;
608 static bool CanHash(const nsIFrame
* aFrame
, const LogicalSize
& aCBSize
) {
609 uint_fast8_t bitsNeededForISize
=
610 mozilla::FloorLog2(aCBSize
.ISize(aFrame
->GetWritingMode())) + 1;
612 uint_fast8_t bitsNeededForBBaselinePadding
=
614 abs(aFrame
->GetProperty(nsIFrame::BBaselinePadProperty()))) +
617 return bitsNeededForISize
+ bitsNeededForBBaselinePadding
<= 32;
620 bool operator==(const Key
& aOther
) const {
621 return mHashKey
== aOther
.mHashKey
;
629 bool CanProvideLineIterator() const final
{ return true; }
630 nsILineIterator
* GetLineIterator() final
{ return this; }
631 int32_t GetNumLines() const final
;
632 bool IsLineIteratorFlowRTL() final
;
633 mozilla::Result
<LineInfo
, nsresult
> GetLine(int32_t aLineNumber
) final
;
634 int32_t FindLineContaining(nsIFrame
* aFrame
, int32_t aStartLine
= 0) final
;
635 NS_IMETHOD
FindFrameAt(int32_t aLineNumber
, nsPoint aPos
,
636 nsIFrame
** aFrameFound
, bool* aPosIsBeforeFirstFrame
,
637 bool* aPosIsAfterLastFrame
) final
;
638 NS_IMETHOD
CheckLineOrder(int32_t aLine
, bool* aIsReordered
,
639 nsIFrame
** aFirstVisual
,
640 nsIFrame
** aLastVisual
) final
;
643 #endif /* nsGridContainerFrame_h___ */