Backed out changeset 496886cb30a5 (bug 1867152) for bc failures on browser_user_input...
[gecko.git] / layout / generic / nsGridContainerFrame.h
blobd4760a0e7ab95d1509c6a7bcb62f6d9f14e4f526
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"
20 namespace mozilla {
21 class PresShell;
22 namespace dom {
23 class Grid;
25 } // namespace mozilla
27 /**
28 * Factory function.
29 * @return a newly allocated nsGridContainerFrame (infallible)
31 nsContainerFrame* NS_NewGridContainerFrame(mozilla::PresShell* aPresShell,
32 mozilla::ComputedStyle* aStyle);
34 namespace mozilla {
36 /**
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
69 // collapsed tracks.
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;
76 bool mIsSubgrid;
77 bool mIsMasonry;
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 {
99 public:
100 NS_DECL_FRAMEARENA_HELPERS(nsGridContainerFrame)
101 NS_DECL_QUERYFRAME
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)) {
135 return Nothing{};
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;
143 #endif
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;
155 #ifdef DEBUG
156 void SetInitialChildList(ChildListID aListID,
157 nsFrameList&& aChildList) override;
158 #endif
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.");
177 return info;
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.");
184 return info;
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.");
191 return info;
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.");
198 return info;
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,
216 ImplicitNamedAreas)
217 ImplicitNamedAreas* GetImplicitNamedAreas() const {
218 return GetProperty(ImplicitNamedAreasProperty());
221 using ExplicitNamedAreas = mozilla::StyleOwnedSlice<NamedArea>;
222 NS_DECLARE_FRAME_PROPERTY_DELETABLE(ExplicitNamedAreasProperty,
223 ExplicitNamedAreas)
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);
276 struct Subgrid;
277 struct UsedTrackSizes;
278 struct TrackSize;
279 struct GridItemInfo;
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?
285 bool mIsInEdgeTrack;
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
298 protected:
299 typedef mozilla::LogicalPoint LogicalPoint;
300 typedef mozilla::LogicalRect LogicalRect;
301 typedef mozilla::LogicalSize LogicalSize;
302 typedef mozilla::WritingMode WritingMode;
303 struct Grid;
304 struct GridArea;
305 class LineNameMap;
306 struct LineRange;
307 struct SharedGridData;
308 struct SubgridFallbackTrackSizingFunctions;
309 struct TrackSizingFunctions;
310 struct Tracks;
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);
334 using LineNameList =
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 {
375 eNone = 0x0,
376 eFirst = 0x1,
377 eLast = 0x2,
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,
395 WritingMode aCBWM);
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;
437 private:
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.
448 bool mIsTopOfPage;
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?
456 bool mCanBreakAtEnd;
458 * Is the grid container's block-size unconstrained?
460 bool mIsAutoBSize;
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;
527 public:
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 {
540 public:
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()) {
550 return false;
553 if (!CanCacheMeasurement(aFrame, aCBSize)) {
554 return false;
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);
571 mBSize = aBSize;
574 private:
575 struct Key {
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
580 uint32_t mHashKey;
582 Key() = default;
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 =
613 mozilla::FloorLog2(
614 abs(aFrame->GetProperty(nsIFrame::BBaselinePadProperty()))) +
617 return bitsNeededForISize + bitsNeededForBBaselinePadding <= 32;
620 bool operator==(const Key& aOther) const {
621 return mHashKey == aOther.mHashKey;
625 Key mKey;
626 nscoord mBSize;
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___ */