diff options
Diffstat (limited to '')
-rw-r--r-- | layout/generic/nsFlexContainerFrame.h | 664 |
1 files changed, 664 insertions, 0 deletions
diff --git a/layout/generic/nsFlexContainerFrame.h b/layout/generic/nsFlexContainerFrame.h new file mode 100644 index 0000000000..3349c698b3 --- /dev/null +++ b/layout/generic/nsFlexContainerFrame.h @@ -0,0 +1,664 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* rendering object for CSS "display: flex" and "display: -webkit-box" */ + +#ifndef nsFlexContainerFrame_h___ +#define nsFlexContainerFrame_h___ + +#include <tuple> + +#include "mozilla/dom/FlexBinding.h" +#include "mozilla/UniquePtr.h" +#include "nsContainerFrame.h" + +namespace mozilla { +class LogicalPoint; +class PresShell; +} // namespace mozilla + +nsContainerFrame* NS_NewFlexContainerFrame(mozilla::PresShell* aPresShell, + mozilla::ComputedStyle* aStyle); + +/** + * These structures are used to capture data during reflow to be + * extracted by devtools via Chrome APIs. The structures are only + * created when requested in GetFlexFrameWithComputedInfo(), and + * the structures are attached to the nsFlexContainerFrame via the + * FlexContainerInfo property. + */ +struct ComputedFlexItemInfo { + nsCOMPtr<nsINode> mNode; + nsRect mFrameRect; + /** + * mMainBaseSize is a measure of the size of the item in the main + * axis before the flex sizing algorithm is applied. In the spec, + * this is called "flex base size", but we use this name to connect + * the value to the other main axis sizes. + */ + nscoord mMainBaseSize; + /** + * mMainDeltaSize is the amount that the flex sizing algorithm + * adds to the mMainBaseSize, before clamping to mMainMinSize and + * mMainMaxSize. This can be thought of as the amount by which the + * flex layout algorithm "wants" to shrink or grow the item, and + * would do, if it was unconstrained. Since the flex sizing + * algorithm proceeds linearly, the mMainDeltaSize for an item only + * respects the resolved size of items already frozen. + */ + nscoord mMainDeltaSize; + nscoord mMainMinSize; + nscoord mMainMaxSize; + nscoord mCrossMinSize; + nscoord mCrossMaxSize; + mozilla::dom::FlexItemClampState mClampState; +}; + +struct ComputedFlexLineInfo { + nsTArray<ComputedFlexItemInfo> mItems; + nscoord mCrossStart; + nscoord mCrossSize; + nscoord mFirstBaselineOffset; + nscoord mLastBaselineOffset; + mozilla::dom::FlexLineGrowthState mGrowthState; +}; + +struct ComputedFlexContainerInfo { + nsTArray<ComputedFlexLineInfo> mLines; + mozilla::dom::FlexPhysicalDirection mMainAxisDirection; + mozilla::dom::FlexPhysicalDirection mCrossAxisDirection; +}; + +/** + * Helper class to get the orientation of a flex container's axes. + */ +class MOZ_STACK_CLASS FlexboxAxisInfo final { + public: + explicit FlexboxAxisInfo(const nsIFrame* aFlexContainer); + + // Is our main axis the inline axis? (Are we 'flex-direction:row[-reverse]'?) + bool mIsRowOriented = true; + + // Is our main axis in the opposite direction as mWM's corresponding axis? + // (e.g. RTL vs LTR) + bool mIsMainAxisReversed = false; + + // Is our cross axis in the opposite direction as mWM's corresponding axis? + // (e.g. BTT vs TTB) + bool mIsCrossAxisReversed = false; + + private: + // Helpers for constructor which determine the orientation of our axes, based + // on legacy box properties (-webkit-box-orient, -webkit-box-direction) or + // modern flexbox properties (flex-direction, flex-wrap) depending on whether + // the flex container is a "legacy box" (as determined by IsLegacyBox). + void InitAxesFromLegacyProps(const nsIFrame* aFlexContainer); + void InitAxesFromModernProps(const nsIFrame* aFlexContainer); +}; + +/** + * This is the rendering object used for laying out elements with + * "display: flex" or "display: inline-flex". + * + * We also use this class for elements with "display: -webkit-box" or + * "display: -webkit-inline-box" (but not "-moz-box" / "-moz-inline-box" -- + * those are rendered with old-school XUL frame classes). + * + * Note: we represent the -webkit-box family of properties (-webkit-box-orient, + * -webkit-box-flex, etc.) as aliases for their -moz equivalents. And for + * -webkit-{inline-}box containers, nsFlexContainerFrame will honor those + * "legacy" properties for alignment/flexibility/etc. *instead of* honoring the + * modern flexbox & alignment properties. For brevity, many comments in + * nsFlexContainerFrame.cpp simply refer to these properties using their + * "-webkit" versions, since we're mostly expecting to encounter them in that + * form. (Technically, the "-moz" versions of these properties *can* influence + * layout here as well (since that's what the -webkit versions are aliased to) + * -- but only inside of a "display:-webkit-{inline-}box" container.) + */ +class nsFlexContainerFrame final : public nsContainerFrame { + public: + NS_DECL_FRAMEARENA_HELPERS(nsFlexContainerFrame) + NS_DECL_QUERYFRAME + + // Factory method: + friend nsContainerFrame* NS_NewFlexContainerFrame( + mozilla::PresShell* aPresShell, ComputedStyle* aStyle); + + // Forward-decls of helper classes + class FlexItem; + class FlexLine; + class FlexboxAxisTracker; + struct StrutInfo; + class CachedBAxisMeasurement; + class CachedFlexItemData; + struct SharedFlexData; + class FlexItemIterator; + + // nsIFrame overrides + void Init(nsIContent* aContent, nsContainerFrame* aParent, + nsIFrame* aPrevInFlow) override; + + bool IsFrameOfType(uint32_t aFlags) const override { + return nsContainerFrame::IsFrameOfType( + aFlags & ~(nsIFrame::eCanContainOverflowContainers)); + } + + void BuildDisplayList(nsDisplayListBuilder* aBuilder, + const nsDisplayListSet& aLists) override; + + void MarkIntrinsicISizesDirty() override; + + void Reflow(nsPresContext* aPresContext, ReflowOutput& aReflowOutput, + const ReflowInput& aReflowInput, + nsReflowStatus& aStatus) override; + + nscoord GetMinISize(gfxContext* aRenderingContext) override; + nscoord GetPrefISize(gfxContext* aRenderingContext) override; + +#ifdef DEBUG_FRAME_DUMP + nsresult GetFrameName(nsAString& aResult) const override; +#endif + + nscoord GetLogicalBaseline(mozilla::WritingMode aWM) const override; + + bool GetVerticalAlignBaseline(mozilla::WritingMode aWM, + nscoord* aBaseline) const override { + return GetNaturalBaselineBOffset(aWM, BaselineSharingGroup::First, + aBaseline); + } + + bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM, + BaselineSharingGroup aBaselineGroup, + nscoord* aBaseline) const override { + if (HasAnyStateBits(NS_STATE_FLEX_SYNTHESIZE_BASELINE)) { + return false; + } + *aBaseline = aBaselineGroup == BaselineSharingGroup::First + ? mBaselineFromLastReflow + : mLastBaselineFromLastReflow; + return true; + } + + /** + * Returns the effective value of -webkit-line-clamp for this flex container. + * + * This will be 0 if the property is 'none', or if the element is not + * display:-webkit-(inline-)box and -webkit-box-orient:vertical. + */ + uint32_t GetLineClampValue() const; + + // nsContainerFrame overrides + bool DrainSelfOverflowList() override; + void AppendFrames(ChildListID aListID, nsFrameList& aFrameList) override; + void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame, + const nsLineList::iterator* aPrevFrameLine, + nsFrameList& aFrameList) override; + void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override; + mozilla::StyleAlignFlags CSSAlignmentForAbsPosChild( + const ReflowInput& aChildRI, + mozilla::LogicalAxis aLogicalAxis) const override; + + /** + * Helper function to calculate packing space and initial offset of alignment + * subjects in MainAxisPositionTracker() and CrossAxisPositionTracker() for + * space-between, space-around, and space-evenly. + * * @param aNumThingsToPack Number of alignment subjects. + * @param aAlignVal Value for align-content or + * justify-content. + * @param aFirstSubjectOffset Outparam for first subject offset. + * @param aNumPackingSpacesRemaining Outparam for number of equal-sized + * packing spaces to apply between each + * alignment subject. + * @param aPackingSpaceRemaining Outparam for total amount of packing + * space to be divided up. + */ + static void CalculatePackingSpace( + uint32_t aNumThingsToPack, + const mozilla::StyleContentDistribution& aAlignVal, + nscoord* aFirstSubjectOffset, uint32_t* aNumPackingSpacesRemaining, + nscoord* aPackingSpaceRemaining); + + /** + * This property is created by a call to + * nsFlexContainerFrame::GetFlexFrameWithComputedInfo. + */ + NS_DECLARE_FRAME_PROPERTY_DELETABLE(FlexContainerInfo, + ComputedFlexContainerInfo) + /** + * This function should only be called on a nsFlexContainerFrame + * that has just been returned by a call to + * GetFlexFrameWithComputedInfo. + */ + const ComputedFlexContainerInfo* GetFlexContainerInfo() { + const ComputedFlexContainerInfo* info = GetProperty(FlexContainerInfo()); + NS_WARNING_ASSERTION(info, + "Property generation wasn't requested. " + "This is a known issue in Print Preview. " + "See Bug 1157012."); + return info; + } + + /** + * Return aFrame as a flex frame after ensuring it has computed flex info. + * @return nullptr if aFrame is null or doesn't have a flex frame + * as its content insertion frame. + * @note this might destroy layout/style data since it may flush layout. + */ + MOZ_CAN_RUN_SCRIPT_BOUNDARY + static nsFlexContainerFrame* GetFlexFrameWithComputedInfo(nsIFrame* aFrame); + + /** + * Given a frame for a flex item, this method returns true IFF that flex + * item's inline axis is the same as (i.e. not orthogonal to) its flex + * container's main axis. + * + * (This method is only intended to be used from external + * callers. Inside of flex reflow code, FlexItem::IsInlineAxisMainAxis() is + * equivalent & more optimal.) + * + * @param aFrame a flex item (must return true from IsFlexItem) + * @return true iff aFrame's inline axis is the same as (i.e. not orthogonal + * to) its flex container's main axis. Otherwise, false. + */ + static bool IsItemInlineAxisMainAxis(nsIFrame* aFrame); + + /** + * Returns true iff the given computed 'flex-basis' & main-size property + * values collectively represent a used flex-basis of 'content'. + * See https://drafts.csswg.org/css-flexbox-1/#valdef-flex-basis-auto + * + * @param aFlexBasis the computed 'flex-basis' for a flex item. + * @param aMainSize the computed main-size property for a flex item. + */ + static bool IsUsedFlexBasisContent(const mozilla::StyleFlexBasis& aFlexBasis, + const mozilla::StyleSize& aMainSize); + + /** + * Callback for nsIFrame::MarkIntrinsicISizesDirty() on a flex item. + */ + static void MarkCachedFlexMeasurementsDirty(nsIFrame* aItemFrame); + + protected: + // Protected constructor & destructor + explicit nsFlexContainerFrame(ComputedStyle* aStyle, + nsPresContext* aPresContext) + : nsContainerFrame(aStyle, aPresContext, kClassID) {} + + virtual ~nsFlexContainerFrame(); + + // Protected flex-container-specific methods / member-vars + + /* + * This method does the bulk of the flex layout, implementing the algorithm + * described at: + * http://dev.w3.org/csswg/css-flexbox/#layout-algorithm + * (with a few initialization pieces happening in the caller, Reflow(). + * + * (The logic behind the division of work between Reflow and DoFlexLayout is + * as follows: DoFlexLayout() begins at the step that we have to jump back + * to, if we find any visibility:collapse children, and Reflow() does + * everything before that point.) + * + * @param aContentBoxMainSize [in/out] initially, the "tentative" content-box + * main-size of the flex container; "tentative" + * because it may be unconstrained or may run off + * the page. In those cases, this method will + * resolve it to a final value before returning. + * @param aContentBoxCrossSize [out] the final content-box cross-size of the + * flex container. + * @param aFlexContainerAscent [out] the flex container's ascent, derived from + * any baseline-aligned flex items in the first + * flex line, if any such items exist. Otherwise, + * nscoord_MIN. + */ + void DoFlexLayout(const ReflowInput& aReflowInput, + nscoord& aContentBoxMainSize, nscoord& aContentBoxCrossSize, + nscoord& aFlexContainerAscent, nsTArray<FlexLine>& aLines, + nsTArray<StrutInfo>& aStruts, + nsTArray<nsIFrame*>& aPlaceholders, + const FlexboxAxisTracker& aAxisTracker, + nscoord aMainGapSize, nscoord aCrossGapSize, + nscoord aConsumedBSize, bool aHasLineClampEllipsis, + ComputedFlexContainerInfo* const aContainerInfo); + + /** + * If our devtools have requested a ComputedFlexContainerInfo for this flex + * container, this method ensures that we have one (and if one already exists, + * this method reinitializes it to look like a freshly-created one). + * + * @return the pointer to a freshly created or reinitialized + * ComputedFlexContainerInfo if our devtools have requested it; + * otherwise nullptr. + */ + ComputedFlexContainerInfo* CreateOrClearFlexContainerInfo(); + + /** + * Helpers for DoFlexLayout to computed fields in ComputedFlexContainerInfo. + */ + static void CreateFlexLineAndFlexItemInfo( + ComputedFlexContainerInfo& aContainerInfo, + const nsTArray<FlexLine>& aLines); + + static void ComputeFlexDirections(ComputedFlexContainerInfo& aContainerInfo, + const FlexboxAxisTracker& aAxisTracker); + + static void UpdateFlexLineAndItemInfo( + ComputedFlexContainerInfo& aContainerInfo, + const nsTArray<FlexLine>& aLines); + +#ifdef DEBUG + void SanityCheckAnonymousFlexItems() const; +#endif // DEBUG + + /** + * Returns a new FlexItem for the given child frame, directly constructed at + * the end of aLine. Guaranteed to return non-null. + * + * Before returning, this method also processes the FlexItem to resolve its + * flex basis (including e.g. auto-height) as well as to resolve + * "min-height:auto", via ResolveAutoFlexBasisAndMinSize(). (Basically, the + * returned FlexItem will be ready to participate in the "Resolve the + * Flexible Lengths" step of the Flex Layout Algorithm.) + * https://drafts.csswg.org/css-flexbox-1/#algo-flex + * + * Note that this method **does not** update aLine's main-size bookkeeping to + * account for the newly-constructed flex item. The caller is responsible for + * determining whether this line is a good fit for the new item. If so, + * updating aLine's bookkeeping (via FlexLine::AddLastItemToMainSizeTotals), + * or moving the new item to a new line otherwise. + */ + FlexItem* GenerateFlexItemForChild(FlexLine& aLine, nsIFrame* aChildFrame, + const ReflowInput& aParentReflowInput, + const FlexboxAxisTracker& aAxisTracker, + bool aHasLineClampEllipsis); + + /** + * This method looks up cached block-axis measurements for a flex item, or + * does a measuring reflow and caches those measurements. + * + * This avoids exponential reflows - see the comment above the + * CachedBAxisMeasurement struct. + */ + const CachedBAxisMeasurement& MeasureAscentAndBSizeForFlexItem( + FlexItem& aItem, ReflowInput& aChildReflowInput); + + /** + * This method performs a "measuring" reflow to get the content BSize of + * aFlexItem.Frame() (treating it as if it had a computed BSize of "auto"), + * and returns the resulting BSize measurement. + * (Helper for ResolveAutoFlexBasisAndMinSize().) + */ + nscoord MeasureFlexItemContentBSize(FlexItem& aFlexItem, + bool aForceBResizeForMeasuringReflow, + bool aHasLineClampEllipsis, + const ReflowInput& aParentReflowInput); + + /** + * This method resolves an "auto" flex-basis and/or min-main-size value + * on aFlexItem, if needed. + * (Helper for GenerateFlexItemForChild().) + */ + void ResolveAutoFlexBasisAndMinSize(FlexItem& aFlexItem, + const ReflowInput& aItemReflowInput, + const FlexboxAxisTracker& aAxisTracker, + bool aHasLineClampEllipsis); + + /** + * Returns true if "this" is the nsFlexContainerFrame for a -moz-box or + * a -moz-inline-box -- these boxes have special behavior for flex items with + * "visibility:collapse". + * + * @param aFlexStyleDisp This frame's StyleDisplay(). (Just an optimization to + * avoid repeated lookup; some callers already have it.) + * @return true if "this" is the nsFlexContainerFrame for a -moz-{inline}box. + */ + bool ShouldUseMozBoxCollapseBehavior(const nsStyleDisplay* aFlexStyleDisp); + + /** + * This method: + * - Creates FlexItems for all of our child frames (except placeholders). + * - Groups those FlexItems into FlexLines. + * - Returns those FlexLines in the outparam |aLines|. + * + * This corresponds to "Collect flex items into flex lines" step in the spec. + * https://drafts.csswg.org/css-flexbox-1/#algo-line-break + * + * For any child frames which are placeholders, this method will instead just + * append that child to the outparam |aPlaceholders| for separate handling. + * (Absolutely positioned children of a flex container are *not* flex items.) + */ + void GenerateFlexLines(const ReflowInput& aReflowInput, + nscoord aContentBoxMainSize, + const nsTArray<StrutInfo>& aStruts, + const FlexboxAxisTracker& aAxisTracker, + nscoord aMainGapSize, bool aHasLineClampEllipsis, + nsTArray<nsIFrame*>& aPlaceholders, + nsTArray<FlexLine>& aLines); + + /** + * This method creates FlexLines and FlexItems for children in flex + * container's next-in-flows by using the SharedFlexData stored in flex + * container's first-in-flow. Returns FlexLines in the outparam |aLines|. + */ + void GenerateFlexLines(const SharedFlexData& aData, + nsTArray<FlexLine>& aLines); + + nscoord GetMainSizeFromReflowInput(const ReflowInput& aReflowInput, + const FlexboxAxisTracker& aAxisTracker, + nscoord aConsumedBSize); + + /** + * Resolves the content-box main-size of a flex container frame, + * primarily based on: + * - the "tentative" main size, taken from the reflow input ("tentative" + * because it may be unconstrained or may run off the page). + * - the sizes of our lines of flex items. + * + * We assume the available block-size is always *unconstrained* because this + * is called only in flex algorithm to measure the flex container's size + * without regards to pagination. + * + * Guaranteed to return a definite length, i.e. not NS_UNCONSTRAINEDSIZE, + * aside from cases with huge lengths which happen to compute to that value. + * + * This corresponds to "Determine the main size of the flex container" step in + * the spec. https://drafts.csswg.org/css-flexbox-1/#algo-main-container + * + * (Note: This function should be structurally similar to + * 'ComputeCrossSize()', except that here, the caller has already grabbed the + * tentative size from the reflow input.) + */ + nscoord ComputeMainSize(const ReflowInput& aReflowInput, + const FlexboxAxisTracker& aAxisTracker, + nscoord aTentativeMainSize, + nsTArray<FlexLine>& aLines) const; + + nscoord ComputeCrossSize(const ReflowInput& aReflowInput, + const FlexboxAxisTracker& aAxisTracker, + nscoord aSumLineCrossSizes, nscoord aConsumedBSize, + bool* aIsDefinite) const; + + /** + * Compute the size of the available space that we'll give to our children to + * reflow into. In particular, compute the available size that we would give + * to a hypothetical child placed at the IStart/BStart corner of this flex + * container's content-box. + * + * @param aReflowInput the flex container's reflow input. + * @param aBorderPadding the border and padding of this frame with the + * assumption that this is the last fragment. + * + * @return the size of the available space for our children to reflow into. + */ + mozilla::LogicalSize ComputeAvailableSizeForItems( + const ReflowInput& aReflowInput, + const mozilla::LogicalMargin& aBorderPadding) const; + + void SizeItemInCrossAxis(ReflowInput& aChildReflowInput, FlexItem& aItem); + + /** + * This method computes the metrics to be reported via the flex container's + * ReflowOutput & nsReflowStatus output parameters in Reflow(). + * + * @param aContentBoxSize the final content-box size for the flex container as + * a whole, converted from the flex container's + * main/cross sizes. The main/cross sizes are computed + * by DoFlexLayout() if this frame is the + * first-in-flow, or are the stored ones in + * SharedFlexData if this frame is a not the + * first-in-flow. + * @param aBorderPadding the border and padding for this frame (possibly with + * some sides skipped as-appropriate, if we're in a + * continuation chain). + * @param aConsumedBSize the sum of our content-box block-size consumed by our + * prev-in-flows. + * @param aMayNeedNextInFlow true if we may need a next-in-flow because our + * effective content-box block-size exceeds the + * available block-size. + * @param aMaxBlockEndEdgeOfChildren the maximum block-end edge of the + * children of this fragment in this frame's + * coordinate space (as returned by + * ReflowChildren()). + * @param aAnyChildIncomplete true if any child being reflowed is incomplete; + * false otherwise (as returned by + * ReflowChildren()). + * @param aFlexContainerAscent the flex container's ascent, if one has been + * determined from its children. (If there are no + * children, pass nscoord_MIN to synthesize a + * value from the flex container itself). + */ + void PopulateReflowOutput( + ReflowOutput& aReflowOutput, const ReflowInput& aReflowInput, + nsReflowStatus& aStatus, const mozilla::LogicalSize& aContentBoxSize, + const mozilla::LogicalMargin& aBorderPadding, + const nscoord aConsumedBSize, const bool aMayNeedNextInFlow, + const nscoord aMaxBlockEndEdgeOfChildren, const bool aAnyChildIncomplete, + nscoord aFlexContainerAscent, nsTArray<FlexLine>& aLines, + const FlexboxAxisTracker& aAxisTracker); + + /** + * Perform a final Reflow for our child frames. + * + * @param aContentBoxMainSize the final content-box main-size of the flex + * container. + * @param aContentBoxCrossSize the final content-box cross-size of the flex + * container. + * @param aContainerSize this frame's tentative physical border-box size, used + * only for logical to physical coordinate conversion. + * @param aAvailableSizeForItems the size of the available space for our + * children to reflow into. + * @param aBorderPadding the border and padding for this frame (possibly with + * some sides skipped as-appropriate, if we're in a + * continuation chain). + * @param aSumOfPrevInFlowsChildrenBlockSize See the comment for + * SumOfChildrenBlockSizeProperty. + * @param aFlexContainerAscent [in/out] initially, the "tentative" flex + * container ascent computed in DoFlexLayout; or, + * nscoord_MIN if the ascent hasn't been + * established yet. If the latter, this will be + * updated with an ascent derived from the first + * flex item (if there are any flex items). + * @return nscoord the maximum block-end edge of children of this fragment in + * flex container's coordinate space. + * @return bool true if any child being reflowed is incomplete; false + * otherwise. + */ + std::tuple<nscoord, bool> ReflowChildren( + const ReflowInput& aReflowInput, const nscoord aContentBoxMainSize, + const nscoord aContentBoxCrossSize, const nsSize& aContainerSize, + const mozilla::LogicalSize& aAvailableSizeForItems, + const mozilla::LogicalMargin& aBorderPadding, + const nscoord aSumOfPrevInFlowsChildrenBlockSize, + nscoord& aFlexContainerAscent, nsTArray<FlexLine>& aLines, + nsTArray<nsIFrame*>& aPlaceholders, + const FlexboxAxisTracker& aAxisTracker, bool aHasLineClampEllipsis); + + /** + * Moves the given flex item's frame to the given LogicalPosition (modulo any + * relative positioning). + * + * This can be used in cases where we've already done a "measuring reflow" + * for the flex item at the correct size, and hence can skip its final reflow + * (but still need to move it to the right final position). + * + * @param aReflowInput The flex container's reflow input. + * @param aItem The flex item whose frame should be moved. + * @param aFramePos The position where the flex item's frame should + * be placed. (pre-relative positioning) + * @param aContainerSize The flex container's size (required by some methods + * that we call, to interpret aFramePos correctly). + */ + void MoveFlexItemToFinalPosition(const ReflowInput& aReflowInput, + const FlexItem& aItem, + mozilla::LogicalPoint& aFramePos, + const nsSize& aContainerSize); + /** + * Helper-function to reflow a child frame, at its final position determined + * by flex layout. + * + * @param aAxisTracker A FlexboxAxisTracker with the flex container's axes. + * @param aReflowInput The flex container's reflow input. + * @param aItem The flex item to be reflowed. + * @param aFramePos The position where the flex item's frame should + * be placed. (pre-relative positioning) + * @param aAvailableSize The available size to reflow the child frame (in the + * child frame's writing-mode). + * @param aContainerSize The flex container's size (required by some methods + * that we call, to interpret aFramePos correctly). + * @return the child frame's reflow status. + */ + nsReflowStatus ReflowFlexItem(const FlexboxAxisTracker& aAxisTracker, + const ReflowInput& aReflowInput, + const FlexItem& aItem, + mozilla::LogicalPoint& aFramePos, + const mozilla::LogicalSize& aAvailableSize, + const nsSize& aContainerSize, + bool aHasLineClampEllipsis); + + /** + * Helper-function to perform a "dummy reflow" on all our nsPlaceholderFrame + * children, at the container's content-box origin. + * + * This doesn't actually represent the static position of the placeholders' + * out-of-flow (OOF) frames -- we can't compute that until we've reflowed the + * OOF, because (depending on the CSS Align properties) the static position + * may be influenced by the OOF's size. So for now, we just co-opt the + * placeholder to store the flex container's logical content-box origin, and + * we defer to nsAbsoluteContainingBlock to determine the OOF's actual static + * position (using this origin, the OOF's size, and the CSS Align + * properties). + * + * @param aReflowInput The flex container's reflow input. + * @param aPlaceholders An array of all the flex container's + * nsPlaceholderFrame children. + * @param aContentBoxOrigin The flex container's logical content-box + * origin (in its own coordinate space). + * @param aContainerSize The flex container's size (required by some + * reflow methods to interpret positions correctly). + */ + void ReflowPlaceholders(const ReflowInput& aReflowInput, + nsTArray<nsIFrame*>& aPlaceholders, + const mozilla::LogicalPoint& aContentBoxOrigin, + const nsSize& aContainerSize); + + /** + * Helper for GetMinISize / GetPrefISize. + */ + nscoord IntrinsicISize(gfxContext* aRenderingContext, + mozilla::IntrinsicISizeType aType); + + /** + * Cached values to optimize GetMinISize/GetPrefISize. + */ + nscoord mCachedMinISize = NS_INTRINSIC_ISIZE_UNKNOWN; + nscoord mCachedPrefISize = NS_INTRINSIC_ISIZE_UNKNOWN; + + nscoord mBaselineFromLastReflow = NS_INTRINSIC_ISIZE_UNKNOWN; + // Note: the last baseline is a distance from our border-box end edge. + nscoord mLastBaselineFromLastReflow = NS_INTRINSIC_ISIZE_UNKNOWN; +}; + +#endif /* nsFlexContainerFrame_h___ */ |