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