From 1ceb807b656a5a54ebd61870b8817d8086ce128e Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 27 Oct 2016 18:58:26 -0700 Subject: [PATCH] Bug 1269045 part 2: Separate out abspos placeholders when creating FlexItems, and give them a trivial reflow at container's content-box origin. r=mats MozReview-Commit-ID: 5lXUsusLryC --- layout/generic/nsFlexContainerFrame.cpp | 51 ++++++++++++++++++++++++- layout/generic/nsFlexContainerFrame.h | 45 ++++++++++++++++++++-- 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp index 03f0d9cea7e8..347258e93747 100644 --- a/layout/generic/nsFlexContainerFrame.cpp +++ b/layout/generic/nsFlexContainerFrame.cpp @@ -3403,7 +3403,8 @@ nsFlexContainerFrame::GenerateFlexLines( nscoord aAvailableBSizeForContent, const nsTArray& aStruts, const FlexboxAxisTracker& aAxisTracker, - LinkedList& aLines) + nsTArray& aPlaceholders, /* out */ + LinkedList& aLines /* out */) { MOZ_ASSERT(aLines.isEmpty(), "Expecting outparam to start out empty"); @@ -3460,6 +3461,12 @@ nsFlexContainerFrame::GenerateFlexLines( uint32_t itemIdxInContainer = 0; for (nsIFrame* childFrame : mFrames) { + // Don't create flex items / lines for placeholder frames: + if (childFrame->GetType() == nsGkAtoms::placeholderFrame) { + aPlaceholders.AppendElement(childFrame); + continue; + } + // Honor "page-break-before", if we're multi-line and this line isn't empty: if (!isSingleLine && !curLine->IsEmpty() && childFrame->StyleDisplay()->mBreakBefore) { @@ -4035,12 +4042,14 @@ nsFlexContainerFrame::DoFlexLayout(nsPresContext* aPresContext, aStatus = NS_FRAME_COMPLETE; LinkedList lines; + nsTArray placeholderKids; AutoFlexLineListClearer cleanupLines(lines); GenerateFlexLines(aPresContext, aReflowInput, aContentBoxMainSize, aAvailableBSizeForContent, - aStruts, aAxisTracker, lines); + aStruts, aAxisTracker, + placeholderKids, lines); aContentBoxMainSize = ResolveFlexContainerMainSize(aReflowInput, aAxisTracker, @@ -4269,6 +4278,12 @@ nsFlexContainerFrame::DoFlexLayout(nsPresContext* aPresContext, } } + if (!placeholderKids.IsEmpty()) { + ReflowPlaceholders(aPresContext, aReflowInput, + placeholderKids, containerContentBoxOrigin, + containerSize); + } + // Compute flex container's desired size (in its own writing-mode), // starting w/ content-box size & growing from there: LogicalSize desiredSizeInFlexWM = @@ -4470,6 +4485,38 @@ nsFlexContainerFrame::ReflowFlexItem(nsPresContext* aPresContext, aItem.SetAscent(childDesiredSize.BlockStartAscent()); } +void +nsFlexContainerFrame::ReflowPlaceholders(nsPresContext* aPresContext, + const ReflowInput& aReflowInput, + nsTArray& aPlaceholders, + const LogicalPoint& aContentBoxOrigin, + const nsSize& aContainerSize) +{ + WritingMode outerWM = aReflowInput.GetWritingMode(); + + // As noted in this method's documentation, we'll reflow every entry in + // |aPlaceholders| at the container's content-box origin. + for (nsIFrame* placeholder : aPlaceholders) { + MOZ_ASSERT(placeholder->GetType() == nsGkAtoms::placeholderFrame, + "placeholders array should only contain placeholder frames"); + WritingMode wm = placeholder->GetWritingMode(); + LogicalSize availSize = aReflowInput.ComputedSize(wm); + ReflowInput childReflowInput(aPresContext, aReflowInput, + placeholder, availSize); + ReflowOutput childDesiredSize(childReflowInput); + nsReflowStatus childReflowStatus; + ReflowChild(placeholder, aPresContext, + childDesiredSize, childReflowInput, + outerWM, aContentBoxOrigin, aContainerSize, 0, + childReflowStatus); + + FinishReflowChild(placeholder, aPresContext, + childDesiredSize, &childReflowInput, + outerWM, aContentBoxOrigin, aContainerSize, 0); + + } +} + /* virtual */ nscoord nsFlexContainerFrame::GetMinISize(nsRenderingContext* aRenderingContext) { diff --git a/layout/generic/nsFlexContainerFrame.h b/layout/generic/nsFlexContainerFrame.h index 734936edd09a..52b180f4c954 100644 --- a/layout/generic/nsFlexContainerFrame.h +++ b/layout/generic/nsFlexContainerFrame.h @@ -193,16 +193,23 @@ protected: const ReflowInput& aItemReflowInput, const FlexboxAxisTracker& aAxisTracker); - // Creates FlexItems for all of our child frames, arranged in a list of - // FlexLines. These are returned by reference in |aLines|. Our actual - // return value has to be |nsresult|, in case we have to reflow a child - // to establish its flex base size and that reflow fails. + /** + * This method: + * - Creates FlexItems for all of our child frames (except placeholders). + * - Groups those FlexItems into FlexLines. + * - Returns those FlexLines in the outparam |aLines|. + * + * 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(nsPresContext* aPresContext, const ReflowInput& aReflowInput, nscoord aContentBoxMainSize, nscoord aAvailableBSizeForContent, const nsTArray& aStruts, const FlexboxAxisTracker& aAxisTracker, + nsTArray& aPlaceholders, mozilla::LinkedList& aLines); nscoord GetMainSizeFromReflowInput(const ReflowInput& aReflowInput, @@ -259,6 +266,36 @@ protected: mozilla::LogicalPoint& aFramePos, const nsSize& aContainerSize); + /** + * 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). + * + * XXXdholbert The nsAbsoluteContainingBlock stuff is coming in bug 1269046. + * + * @param aPresContext The presentation context being used in reflow. + * @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(nsPresContext* aPresContext, + const ReflowInput& aReflowInput, + nsTArray& aPlaceholders, + const mozilla::LogicalPoint& aContentBoxOrigin, + const nsSize& aContainerSize); + bool mChildrenHaveBeenReordered; // Have we ever had to reorder our kids // to satisfy their 'order' values?