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/. */
6 
7 /* rendering object for CSS "display: flex" and "display: -webkit-box" */
8 
9 #ifndef nsFlexContainerFrame_h___
10 #define nsFlexContainerFrame_h___
11 
12 #include <tuple>
13 
14 #include "mozilla/dom/FlexBinding.h"
15 #include "mozilla/UniquePtr.h"
16 #include "nsContainerFrame.h"
17 
18 namespace mozilla {
19 class LogicalPoint;
20 class PresShell;
21 }  // namespace mozilla
22 
23 nsContainerFrame* NS_NewFlexContainerFrame(mozilla::PresShell* aPresShell,
24                                            mozilla::ComputedStyle* aStyle);
25 
26 /**
27  * These structures are used to capture data during reflow to be
28  * extracted by devtools via Chrome APIs. The structures are only
29  * created when requested in GetFlexFrameWithComputedInfo(), and
30  * the structures are attached to the nsFlexContainerFrame via the
31  * FlexContainerInfo property.
32  */
33 struct ComputedFlexItemInfo {
34   nsCOMPtr<nsINode> mNode;
35   nsRect mFrameRect;
36   /**
37    * mMainBaseSize is a measure of the size of the item in the main
38    * axis before the flex sizing algorithm is applied. In the spec,
39    * this is called "flex base size", but we use this name to connect
40    * the value to the other main axis sizes.
41    */
42   nscoord mMainBaseSize;
43   /**
44    * mMainDeltaSize is the amount that the flex sizing algorithm
45    * adds to the mMainBaseSize, before clamping to mMainMinSize and
46    * mMainMaxSize. This can be thought of as the amount by which the
47    * flex layout algorithm "wants" to shrink or grow the item, and
48    * would do, if it was unconstrained. Since the flex sizing
49    * algorithm proceeds linearly, the mMainDeltaSize for an item only
50    * respects the resolved size of items already frozen.
51    */
52   nscoord mMainDeltaSize;
53   nscoord mMainMinSize;
54   nscoord mMainMaxSize;
55   nscoord mCrossMinSize;
56   nscoord mCrossMaxSize;
57   mozilla::dom::FlexItemClampState mClampState;
58 };
59 
60 struct ComputedFlexLineInfo {
61   nsTArray<ComputedFlexItemInfo> mItems;
62   nscoord mCrossStart;
63   nscoord mCrossSize;
64   nscoord mFirstBaselineOffset;
65   nscoord mLastBaselineOffset;
66   mozilla::dom::FlexLineGrowthState mGrowthState;
67 };
68 
69 struct ComputedFlexContainerInfo {
70   nsTArray<ComputedFlexLineInfo> mLines;
71   mozilla::dom::FlexPhysicalDirection mMainAxisDirection;
72   mozilla::dom::FlexPhysicalDirection mCrossAxisDirection;
73 };
74 
75 /**
76  * This is the rendering object used for laying out elements with
77  * "display: flex" or "display: inline-flex".
78  *
79  * We also use this class for elements with "display: -webkit-box" or
80  * "display: -webkit-inline-box" (but not "-moz-box" / "-moz-inline-box" --
81  * those are rendered with old-school XUL frame classes).
82  *
83  * Note: we represent the -webkit-box family of properties (-webkit-box-orient,
84  * -webkit-box-flex, etc.) as aliases for their -moz equivalents.  And for
85  * -webkit-{inline-}box containers, nsFlexContainerFrame will honor those
86  * "legacy" properties for alignment/flexibility/etc. *instead of* honoring the
87  * modern flexbox & alignment properties.  For brevity, many comments in
88  * nsFlexContainerFrame.cpp simply refer to these properties using their
89  * "-webkit" versions, since we're mostly expecting to encounter them in that
90  * form. (Technically, the "-moz" versions of these properties *can* influence
91  * layout here as well (since that's what the -webkit versions are aliased to)
92  * -- but only inside of a "display:-webkit-{inline-}box" container.)
93  */
94 class nsFlexContainerFrame final : public nsContainerFrame {
95  public:
96   NS_DECL_FRAMEARENA_HELPERS(nsFlexContainerFrame)
97   NS_DECL_QUERYFRAME
98 
99   // Factory method:
100   friend nsContainerFrame* NS_NewFlexContainerFrame(
101       mozilla::PresShell* aPresShell, ComputedStyle* aStyle);
102 
103   // Forward-decls of helper classes
104   class FlexItem;
105   class FlexLine;
106   class FlexboxAxisTracker;
107   struct StrutInfo;
108   class CachedBAxisMeasurement;
109   class CachedFlexItemData;
110   struct SharedFlexData;
111   class FlexItemIterator;
112 
113   // nsIFrame overrides
114   void Init(nsIContent* aContent, nsContainerFrame* aParent,
115             nsIFrame* aPrevInFlow) override;
116 
IsFrameOfType(uint32_t aFlags)117   bool IsFrameOfType(uint32_t aFlags) const override {
118     return nsContainerFrame::IsFrameOfType(
119         aFlags & ~(nsIFrame::eCanContainOverflowContainers));
120   }
121 
122   void BuildDisplayList(nsDisplayListBuilder* aBuilder,
123                         const nsDisplayListSet& aLists) override;
124 
125   void MarkIntrinsicISizesDirty() override;
126 
127   void Reflow(nsPresContext* aPresContext, ReflowOutput& aReflowOutput,
128               const ReflowInput& aReflowInput,
129               nsReflowStatus& aStatus) override;
130 
131   nscoord GetMinISize(gfxContext* aRenderingContext) override;
132   nscoord GetPrefISize(gfxContext* aRenderingContext) override;
133 
134 #ifdef DEBUG_FRAME_DUMP
135   nsresult GetFrameName(nsAString& aResult) const override;
136 #endif
137 
138   nscoord GetLogicalBaseline(mozilla::WritingMode aWM) const override;
139 
GetVerticalAlignBaseline(mozilla::WritingMode aWM,nscoord * aBaseline)140   bool GetVerticalAlignBaseline(mozilla::WritingMode aWM,
141                                 nscoord* aBaseline) const override {
142     return GetNaturalBaselineBOffset(aWM, BaselineSharingGroup::First,
143                                      aBaseline);
144   }
145 
GetNaturalBaselineBOffset(mozilla::WritingMode aWM,BaselineSharingGroup aBaselineGroup,nscoord * aBaseline)146   bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM,
147                                  BaselineSharingGroup aBaselineGroup,
148                                  nscoord* aBaseline) const override {
149     if (HasAnyStateBits(NS_STATE_FLEX_SYNTHESIZE_BASELINE)) {
150       return false;
151     }
152     *aBaseline = aBaselineGroup == BaselineSharingGroup::First
153                      ? mBaselineFromLastReflow
154                      : mLastBaselineFromLastReflow;
155     return true;
156   }
157 
158   /**
159    * Returns the effective value of -webkit-line-clamp for this flex container.
160    *
161    * This will be 0 if the property is 'none', or if the element is not
162    * display:-webkit-(inline-)box and -webkit-box-orient:vertical.
163    */
164   uint32_t GetLineClampValue() const;
165 
166   // nsContainerFrame overrides
167   bool DrainSelfOverflowList() override;
168   void AppendFrames(ChildListID aListID, nsFrameList& aFrameList) override;
169   void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
170                     const nsLineList::iterator* aPrevFrameLine,
171                     nsFrameList& aFrameList) override;
172   void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override;
173   mozilla::StyleAlignFlags CSSAlignmentForAbsPosChild(
174       const ReflowInput& aChildRI,
175       mozilla::LogicalAxis aLogicalAxis) const override;
176 
177   /**
178    * Helper function to calculate packing space and initial offset of alignment
179    * subjects in MainAxisPositionTracker() and CrossAxisPositionTracker() for
180    * space-between, space-around, and space-evenly.
181    *    * @param aNumThingsToPack             Number of alignment subjects.
182    * @param aAlignVal                    Value for align-content or
183    *                                     justify-content.
184    * @param aFirstSubjectOffset          Outparam for first subject offset.
185    * @param aNumPackingSpacesRemaining   Outparam for number of equal-sized
186    *                                     packing spaces to apply between each
187    *                                     alignment subject.
188    * @param aPackingSpaceRemaining       Outparam for total amount of packing
189    *                                     space to be divided up.
190    */
191   static void CalculatePackingSpace(
192       uint32_t aNumThingsToPack,
193       const mozilla::StyleContentDistribution& aAlignVal,
194       nscoord* aFirstSubjectOffset, uint32_t* aNumPackingSpacesRemaining,
195       nscoord* aPackingSpaceRemaining);
196 
197   /**
198    * This property is created by a call to
199    * nsFlexContainerFrame::GetFlexFrameWithComputedInfo.
200    */
NS_DECLARE_FRAME_PROPERTY_DELETABLE(FlexContainerInfo,ComputedFlexContainerInfo)201   NS_DECLARE_FRAME_PROPERTY_DELETABLE(FlexContainerInfo,
202                                       ComputedFlexContainerInfo)
203   /**
204    * This function should only be called on a nsFlexContainerFrame
205    * that has just been returned by a call to
206    * GetFlexFrameWithComputedInfo.
207    */
208   const ComputedFlexContainerInfo* GetFlexContainerInfo() {
209     const ComputedFlexContainerInfo* info = GetProperty(FlexContainerInfo());
210     NS_WARNING_ASSERTION(info,
211                          "Property generation wasn't requested. "
212                          "This is a known issue in Print Preview. "
213                          "See Bug 1157012.");
214     return info;
215   }
216 
217   /**
218    * Return aFrame as a flex frame after ensuring it has computed flex info.
219    * @return nullptr if aFrame is null or doesn't have a flex frame
220    *         as its content insertion frame.
221    * @note this might destroy layout/style data since it may flush layout.
222    */
223   MOZ_CAN_RUN_SCRIPT_BOUNDARY
224   static nsFlexContainerFrame* GetFlexFrameWithComputedInfo(nsIFrame* aFrame);
225 
226   /**
227    * Given a frame for a flex item, this method returns true IFF that flex
228    * item's inline axis is the same as (i.e. not orthogonal to) its flex
229    * container's main axis.
230    *
231    * (This method is only intended to be used from external
232    * callers. Inside of flex reflow code, FlexItem::IsInlineAxisMainAxis() is
233    * equivalent & more optimal.)
234    *
235    * @param aFrame a flex item (must return true from IsFlexItem)
236    * @return true iff aFrame's inline axis is the same as (i.e. not orthogonal
237    *              to) its flex container's main axis. Otherwise, false.
238    */
239   static bool IsItemInlineAxisMainAxis(nsIFrame* aFrame);
240 
241   /**
242    * Returns true iff the given computed 'flex-basis' & main-size property
243    * values collectively represent a used flex-basis of 'content'.
244    * See https://drafts.csswg.org/css-flexbox-1/#valdef-flex-basis-auto
245    *
246    * @param aFlexBasis the computed 'flex-basis' for a flex item.
247    * @param aMainSize the computed main-size property for a flex item.
248    */
249   static bool IsUsedFlexBasisContent(const StyleFlexBasis& aFlexBasis,
250                                      const StyleSize& aMainSize);
251 
252   /**
253    * Callback for nsFrame::MarkIntrinsicISizesDirty() on a flex item.
254    */
255   static void MarkCachedFlexMeasurementsDirty(nsIFrame* aItemFrame);
256 
257  protected:
258   // Protected constructor & destructor
nsFlexContainerFrame(ComputedStyle * aStyle,nsPresContext * aPresContext)259   explicit nsFlexContainerFrame(ComputedStyle* aStyle,
260                                 nsPresContext* aPresContext)
261       : nsContainerFrame(aStyle, aPresContext, kClassID) {}
262 
263   virtual ~nsFlexContainerFrame();
264 
265   // Protected flex-container-specific methods / member-vars
266 
267   /*
268    * This method does the bulk of the flex layout, implementing the algorithm
269    * described at:
270    *   http://dev.w3.org/csswg/css-flexbox/#layout-algorithm
271    * (with a few initialization pieces happening in the caller, Reflow().
272    *
273    * (The logic behind the division of work between Reflow and DoFlexLayout is
274    * as follows: DoFlexLayout() begins at the step that we have to jump back
275    * to, if we find any visibility:collapse children, and Reflow() does
276    * everything before that point.)
277    *
278    * @param aContentBoxMainSize [in/out] initially, the "tentative" content-box
279    *                            main-size of the flex container; "tentative"
280    *                            because it may be unconstrained or may run off
281    *                            the page. In those cases, this method will
282    *                            resolve it to a final value before returning.
283    * @param aContentBoxCrossSize [out] the final content-box cross-size of the
284    *                             flex container.
285    * @param aFlexContainerAscent [out] the flex container's ascent, derived from
286    *                             any baseline-aligned flex items in the first
287    *                             flex line, if any such items exist. Otherwise,
288    *                             nscoord_MIN.
289    * @param aAvailableBSizeForContent the fragmentainer's available block-size
290    *                                  for our content, when we run the flex
291    *                                  layout algorithm. This may be
292    *                                  unconstrained, even in a context where the
293    *                                  flex container is ultimately being
294    *                                  fragmented, because flex container
295    *                                  fragmentation usually starts out by
296    *                                  performing flex layout without regard to
297    *                                  pagination.
298    * @param aColumnWrapThreshold the block-size threshold to wrap to a new line.
299    *                             Used only by multi-line column-oriented flex
300    *                             container if the available block-size is
301    *                             constrained.
302    */
303   void DoFlexLayout(const ReflowInput& aReflowInput, nsReflowStatus& aStatus,
304                     nscoord& aContentBoxMainSize, nscoord& aContentBoxCrossSize,
305                     nscoord& aFlexContainerAscent,
306                     nscoord aAvailableBSizeForContent,
307                     nscoord aColumnWrapThreshold, nsTArray<FlexLine>& aLines,
308                     nsTArray<StrutInfo>& aStruts,
309                     nsTArray<nsIFrame*>& aPlaceholders,
310                     const FlexboxAxisTracker& aAxisTracker,
311                     nscoord aMainGapSize, nscoord aCrossGapSize,
312                     bool aHasLineClampEllipsis,
313                     ComputedFlexContainerInfo* const aContainerInfo);
314 
315   /**
316    * If our devtools have requested a ComputedFlexContainerInfo for this flex
317    * container, this method ensures that we have one (and if one already exists,
318    * this method reinitializes it to look like a freshly-created one).
319    *
320    * @return the pointer to a freshly created or reinitialized
321    *         ComputedFlexContainerInfo if our devtools have requested it;
322    *         otherwise nullptr.
323    */
324   ComputedFlexContainerInfo* CreateOrClearFlexContainerInfo();
325 
326   /**
327    * Helpers for DoFlexLayout to computed fields in ComputedFlexContainerInfo.
328    */
329   static void CreateFlexLineAndFlexItemInfo(
330       ComputedFlexContainerInfo& aContainerInfo,
331       const nsTArray<FlexLine>& aLines);
332 
333   static void ComputeFlexDirections(ComputedFlexContainerInfo& aContainerInfo,
334                                     const FlexboxAxisTracker& aAxisTracker);
335 
336   static void UpdateFlexLineAndItemInfo(
337       ComputedFlexContainerInfo& aContainerInfo,
338       const nsTArray<FlexLine>& aLines);
339 
340 #ifdef DEBUG
341   void SanityCheckAnonymousFlexItems() const;
342 #endif  // DEBUG
343 
344   /**
345    * Returns a new FlexItem for the given child frame, directly constructed at
346    * the end of aLine. Guaranteed to return non-null.
347    *
348    * Before returning, this method also processes the FlexItem to resolve its
349    * flex basis (including e.g. auto-height) as well as to resolve
350    * "min-height:auto", via ResolveAutoFlexBasisAndMinSize(). (Basically, the
351    * returned FlexItem will be ready to participate in the "Resolve the
352    * Flexible Lengths" step of the Flex Layout Algorithm.)
353    * https://drafts.csswg.org/css-flexbox-1/#algo-flex
354    *
355    * Note that this method **does not** update aLine's main-size bookkeeping to
356    * account for the newly-constructed flex item. The caller is responsible for
357    * determining whether this line is a good fit for the new item. If so,
358    * updating aLine's bookkeeping (via FlexLine::AddLastItemToMainSizeTotals),
359    * or moving the new item to a new line otherwise.
360    */
361   FlexItem* GenerateFlexItemForChild(FlexLine& aLine, nsIFrame* aChildFrame,
362                                      const ReflowInput& aParentReflowInput,
363                                      const FlexboxAxisTracker& aAxisTracker,
364                                      bool aHasLineClampEllipsis);
365 
366   /**
367    * This method looks up cached block-axis measurements for a flex item, or
368    * does a measuring reflow and caches those measurements.
369    *
370    * This avoids exponential reflows - see the comment above the
371    * CachedBAxisMeasurement struct.
372    */
373   const CachedBAxisMeasurement& MeasureAscentAndBSizeForFlexItem(
374       FlexItem& aItem, ReflowInput& aChildReflowInput);
375 
376   /**
377    * This method performs a "measuring" reflow to get the content BSize of
378    * aFlexItem.Frame() (treating it as if it had a computed BSize of "auto"),
379    * and returns the resulting BSize measurement.
380    * (Helper for ResolveAutoFlexBasisAndMinSize().)
381    */
382   nscoord MeasureFlexItemContentBSize(FlexItem& aFlexItem,
383                                       bool aForceBResizeForMeasuringReflow,
384                                       bool aHasLineClampEllipsis,
385                                       const ReflowInput& aParentReflowInput);
386 
387   /**
388    * This method resolves an "auto" flex-basis and/or min-main-size value
389    * on aFlexItem, if needed.
390    * (Helper for GenerateFlexItemForChild().)
391    */
392   void ResolveAutoFlexBasisAndMinSize(FlexItem& aFlexItem,
393                                       const ReflowInput& aItemReflowInput,
394                                       const FlexboxAxisTracker& aAxisTracker,
395                                       bool aHasLineClampEllipsis);
396 
397   /**
398    * Returns true if "this" is the nsFlexContainerFrame for a -moz-box or
399    * a -moz-inline-box -- these boxes have special behavior for flex items with
400    * "visibility:collapse".
401    *
402    * @param aFlexStyleDisp This frame's StyleDisplay(). (Just an optimization to
403    *                       avoid repeated lookup; some callers already have it.)
404    * @return true if "this" is the nsFlexContainerFrame for a -moz-{inline}box.
405    */
406   bool ShouldUseMozBoxCollapseBehavior(const nsStyleDisplay* aFlexStyleDisp);
407 
408   /**
409    * This method:
410    *  - Creates FlexItems for all of our child frames (except placeholders).
411    *  - Groups those FlexItems into FlexLines.
412    *  - Returns those FlexLines in the outparam |aLines|.
413    *
414    * This corresponds to "Collect flex items into flex lines" step in the spec.
415    * https://drafts.csswg.org/css-flexbox-1/#algo-line-break
416    *
417    * For any child frames which are placeholders, this method will instead just
418    * append that child to the outparam |aPlaceholders| for separate handling.
419    * (Absolutely positioned children of a flex container are *not* flex items.)
420    */
421   void GenerateFlexLines(const ReflowInput& aReflowInput,
422                          nscoord aContentBoxMainSize,
423                          nscoord aColumnWrapThreshold,
424                          const nsTArray<StrutInfo>& aStruts,
425                          const FlexboxAxisTracker& aAxisTracker,
426                          nscoord aMainGapSize, bool aHasLineClampEllipsis,
427                          nsTArray<nsIFrame*>& aPlaceholders,
428                          nsTArray<FlexLine>& aLines);
429 
430   /**
431    * This method creates FlexLines and FlexItems for children in flex
432    * container's next-in-flows by using the SharedFlexData stored in flex
433    * container's first-in-flow. Returns FlexLines in the outparam |aLines|.
434    */
435   void GenerateFlexLines(const SharedFlexData& aData,
436                          nsTArray<FlexLine>& aLines);
437 
438   nscoord GetMainSizeFromReflowInput(const ReflowInput& aReflowInput,
439                                      const FlexboxAxisTracker& aAxisTracker);
440 
441   /**
442    * Resolves the content-box main-size of a flex container frame,
443    * primarily based on:
444    * - the "tentative" main size, taken from the reflow input ("tentative"
445    *    because it may be unconstrained or may run off the page).
446    * - the available BSize (needed if the main axis is the block axis).
447    * - the sizes of our lines of flex items.
448    *
449    * Guaranteed to return a definite length, i.e. not NS_UNCONSTRAINEDSIZE,
450    * aside from cases with huge lengths which happen to compute to that value.
451    *
452    * This corresponds to "Determine the main size of the flex container" step in
453    * the spec. https://drafts.csswg.org/css-flexbox-1/#algo-main-container
454    *
455    * (Note: This function should be structurally similar to
456    * 'ComputeCrossSize()', except that here, the caller has already grabbed the
457    * tentative size from the reflow input.)
458    */
459   nscoord ComputeMainSize(const ReflowInput& aReflowInput,
460                           const FlexboxAxisTracker& aAxisTracker,
461                           nscoord aTentativeMainSize,
462                           nscoord aAvailableBSizeForContent,
463                           nsTArray<FlexLine>& aLines,
464                           nsReflowStatus& aStatus) const;
465 
466   nscoord ComputeCrossSize(const ReflowInput& aReflowInput,
467                            const FlexboxAxisTracker& aAxisTracker,
468                            nscoord aSumLineCrossSizes,
469                            nscoord aAvailableBSizeForContent, bool* aIsDefinite,
470                            nsReflowStatus& aStatus) const;
471 
472   /**
473    * Compute the size of the available space that we'll give to our children to
474    * reflow into. In particular, compute the available size that we would give
475    * to a hypothetical child placed at the IStart/BStart corner of this flex
476    * container's content-box.
477    *
478    * @param aReflowInput the flex container's reflow input.
479    * @param aBorderPadding the border and padding of this frame with the
480    *                       assumption that this is the last fragment.
481    *
482    * @return the size of the available space for our children to reflow into.
483    */
484   mozilla::LogicalSize ComputeAvailableSizeForItems(
485       const ReflowInput& aReflowInput,
486       const mozilla::LogicalMargin& aBorderPadding) const;
487 
488   void SizeItemInCrossAxis(ReflowInput& aChildReflowInput, FlexItem& aItem);
489 
490   /**
491    * This method computes the metrics to be reported via the flex container's
492    * ReflowOutput & nsReflowStatus output parameters in Reflow().
493    *
494    * @param aContentBoxSize the final content-box size for the flex container as
495    *                        a whole, converted from the flex container's
496    *                        main/cross sizes. The main/cross sizes are computed
497    *                        by DoFlexLayout() if this frame is the
498    *                        first-in-flow, or are the stored ones in
499    *                        SharedFlexData if this frame is a not the
500    *                        first-in-flow.
501    * @param aBorderPadding the border and padding for this frame (possibly with
502    *                       some sides skipped as-appropriate, if we're in a
503    *                       continuation chain).
504    * @param aConsumedBSize the sum of our content-box block-size consumed by our
505    *                       prev-in-flows.
506    * @param aMayNeedNextInFlow true if we may need a next-in-flow because our
507    *                           effective content-box block-size exceeds the
508    *                           available block-size.
509    * @param aMaxBlockEndEdgeOfChildren the maximum block-end edge of the
510    *                                   children of this fragment in this frame's
511    *                                   coordinate space (as returned by
512    *                                   ReflowChildren()).
513    * @param aAnyChildIncomplete true if any child being reflowed is incomplete;
514    *                            false otherwise (as returned by
515    *                            ReflowChildren()).
516    * @param aFlexContainerAscent the flex container's ascent, if one has been
517    *                             determined from its children. (If there are no
518    *                             children, pass nscoord_MIN to synthesize a
519    *                             value from the flex container itself).
520    */
521   void PopulateReflowOutput(
522       ReflowOutput& aReflowOutput, const ReflowInput& aReflowInput,
523       nsReflowStatus& aStatus, const mozilla::LogicalSize& aContentBoxSize,
524       const mozilla::LogicalMargin& aBorderPadding,
525       const nscoord aConsumedBSize, const bool aMayNeedNextInFlow,
526       const nscoord aMaxBlockEndEdgeOfChildren, const bool aAnyChildIncomplete,
527       nscoord aFlexContainerAscent, nsTArray<FlexLine>& aLines,
528       const FlexboxAxisTracker& aAxisTracker);
529 
530   /**
531    * Perform a final Reflow for our child frames.
532    *
533    * @param aContentBoxMainSize the final content-box main-size of the flex
534    *                            container.
535    * @param aContentBoxCrossSize the final content-box cross-size of the flex
536    *                             container.
537    * @param aAvailableSizeForItems the size of the available space for our
538    *                               children to reflow into.
539    * @param aBorderPadding the border and padding for this frame (possibly with
540    *                       some sides skipped as-appropriate, if we're in a
541    *                       continuation chain).
542    * @param aSumOfPrevInFlowsChildrenBlockSize See the comment for
543    *                                           SumOfChildrenBlockSizeProperty.
544    * @param aFlexContainerAscent [in/out] initially, the "tentative" flex
545    *                             container ascent computed in DoFlexLayout; or,
546    *                             nscoord_MIN if the ascent hasn't been
547    *                             established yet. If the latter, this will be
548    *                             updated with an ascent derived from the first
549    *                             flex item (if there are any flex items).
550    * @return nscoord the maximum block-end edge of children of this fragment in
551    *                 flex container's coordinate space.
552    * @return bool true if any child being reflowed is incomplete; false
553    *              otherwise.
554    */
555   std::tuple<nscoord, bool> ReflowChildren(
556       const ReflowInput& aReflowInput, const nscoord aContentBoxMainSize,
557       const nscoord aContentBoxCrossSize,
558       const mozilla::LogicalSize& aAvailableSizeForItems,
559       const mozilla::LogicalMargin& aBorderPadding,
560       const nscoord aSumOfPrevInFlowsChildrenBlockSize,
561       nscoord& aFlexContainerAscent, nsTArray<FlexLine>& aLines,
562       nsTArray<nsIFrame*>& aPlaceholders,
563       const FlexboxAxisTracker& aAxisTracker, bool aHasLineClampEllipsis);
564 
565   /**
566    * Moves the given flex item's frame to the given LogicalPosition (modulo any
567    * relative positioning).
568    *
569    * This can be used in cases where we've already done a "measuring reflow"
570    * for the flex item at the correct size, and hence can skip its final reflow
571    * (but still need to move it to the right final position).
572    *
573    * @param aReflowInput    The flex container's reflow input.
574    * @param aItem           The flex item whose frame should be moved.
575    * @param aFramePos       The position where the flex item's frame should
576    *                        be placed. (pre-relative positioning)
577    * @param aContainerSize  The flex container's size (required by some methods
578    *                        that we call, to interpret aFramePos correctly).
579    */
580   void MoveFlexItemToFinalPosition(const ReflowInput& aReflowInput,
581                                    const FlexItem& aItem,
582                                    mozilla::LogicalPoint& aFramePos,
583                                    const nsSize& aContainerSize);
584   /**
585    * Helper-function to reflow a child frame, at its final position determined
586    * by flex layout.
587    *
588    * @param aAxisTracker    A FlexboxAxisTracker with the flex container's axes.
589    * @param aReflowInput    The flex container's reflow input.
590    * @param aItem           The flex item to be reflowed.
591    * @param aFramePos       The position where the flex item's frame should
592    *                        be placed. (pre-relative positioning)
593    * @param aAvailableSize  The available size to reflow the child frame (in the
594    *                        child frame's writing-mode).
595    * @param aContainerSize  The flex container's size (required by some methods
596    *                        that we call, to interpret aFramePos correctly).
597    * @return the child frame's reflow status.
598    */
599   nsReflowStatus ReflowFlexItem(const FlexboxAxisTracker& aAxisTracker,
600                                 const ReflowInput& aReflowInput,
601                                 const FlexItem& aItem,
602                                 mozilla::LogicalPoint& aFramePos,
603                                 const mozilla::LogicalSize& aAvailableSize,
604                                 const nsSize& aContainerSize,
605                                 bool aHasLineClampEllipsis);
606 
607   /**
608    * Helper-function to perform a "dummy reflow" on all our nsPlaceholderFrame
609    * children, at the container's content-box origin.
610    *
611    * This doesn't actually represent the static position of the placeholders'
612    * out-of-flow (OOF) frames -- we can't compute that until we've reflowed the
613    * OOF, because (depending on the CSS Align properties) the static position
614    * may be influenced by the OOF's size.  So for now, we just co-opt the
615    * placeholder to store the flex container's logical content-box origin, and
616    * we defer to nsAbsoluteContainingBlock to determine the OOF's actual static
617    * position (using this origin, the OOF's size, and the CSS Align
618    * properties).
619    *
620    * @param aReflowInput       The flex container's reflow input.
621    * @param aPlaceholders      An array of all the flex container's
622    *                           nsPlaceholderFrame children.
623    * @param aContentBoxOrigin  The flex container's logical content-box
624    *                           origin (in its own coordinate space).
625    * @param aContainerSize     The flex container's size (required by some
626    *                           reflow methods to interpret positions correctly).
627    */
628   void ReflowPlaceholders(const ReflowInput& aReflowInput,
629                           nsTArray<nsIFrame*>& aPlaceholders,
630                           const mozilla::LogicalPoint& aContentBoxOrigin,
631                           const nsSize& aContainerSize);
632 
633   /**
634    * Helper for GetMinISize / GetPrefISize.
635    */
636   nscoord IntrinsicISize(gfxContext* aRenderingContext,
637                          nsLayoutUtils::IntrinsicISizeType aType);
638 
639   /**
640    * Cached values to optimize GetMinISize/GetPrefISize.
641    */
642   nscoord mCachedMinISize = NS_INTRINSIC_ISIZE_UNKNOWN;
643   nscoord mCachedPrefISize = NS_INTRINSIC_ISIZE_UNKNOWN;
644 
645   nscoord mBaselineFromLastReflow = NS_INTRINSIC_ISIZE_UNKNOWN;
646   // Note: the last baseline is a distance from our border-box end edge.
647   nscoord mLastBaselineFromLastReflow = NS_INTRINSIC_ISIZE_UNKNOWN;
648 };
649 
650 #endif /* nsFlexContainerFrame_h___ */
651