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
This commit is contained in:
Daniel Holbert 2016-10-27 18:58:26 -07:00
Родитель 0237208c0b
Коммит 1ceb807b65
2 изменённых файлов: 90 добавлений и 6 удалений

Просмотреть файл

@ -3403,7 +3403,8 @@ nsFlexContainerFrame::GenerateFlexLines(
nscoord aAvailableBSizeForContent, nscoord aAvailableBSizeForContent,
const nsTArray<StrutInfo>& aStruts, const nsTArray<StrutInfo>& aStruts,
const FlexboxAxisTracker& aAxisTracker, const FlexboxAxisTracker& aAxisTracker,
LinkedList<FlexLine>& aLines) nsTArray<nsIFrame*>& aPlaceholders, /* out */
LinkedList<FlexLine>& aLines /* out */)
{ {
MOZ_ASSERT(aLines.isEmpty(), "Expecting outparam to start out empty"); MOZ_ASSERT(aLines.isEmpty(), "Expecting outparam to start out empty");
@ -3460,6 +3461,12 @@ nsFlexContainerFrame::GenerateFlexLines(
uint32_t itemIdxInContainer = 0; uint32_t itemIdxInContainer = 0;
for (nsIFrame* childFrame : mFrames) { 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: // Honor "page-break-before", if we're multi-line and this line isn't empty:
if (!isSingleLine && !curLine->IsEmpty() && if (!isSingleLine && !curLine->IsEmpty() &&
childFrame->StyleDisplay()->mBreakBefore) { childFrame->StyleDisplay()->mBreakBefore) {
@ -4035,12 +4042,14 @@ nsFlexContainerFrame::DoFlexLayout(nsPresContext* aPresContext,
aStatus = NS_FRAME_COMPLETE; aStatus = NS_FRAME_COMPLETE;
LinkedList<FlexLine> lines; LinkedList<FlexLine> lines;
nsTArray<nsIFrame*> placeholderKids;
AutoFlexLineListClearer cleanupLines(lines); AutoFlexLineListClearer cleanupLines(lines);
GenerateFlexLines(aPresContext, aReflowInput, GenerateFlexLines(aPresContext, aReflowInput,
aContentBoxMainSize, aContentBoxMainSize,
aAvailableBSizeForContent, aAvailableBSizeForContent,
aStruts, aAxisTracker, lines); aStruts, aAxisTracker,
placeholderKids, lines);
aContentBoxMainSize = aContentBoxMainSize =
ResolveFlexContainerMainSize(aReflowInput, aAxisTracker, 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), // Compute flex container's desired size (in its own writing-mode),
// starting w/ content-box size & growing from there: // starting w/ content-box size & growing from there:
LogicalSize desiredSizeInFlexWM = LogicalSize desiredSizeInFlexWM =
@ -4470,6 +4485,38 @@ nsFlexContainerFrame::ReflowFlexItem(nsPresContext* aPresContext,
aItem.SetAscent(childDesiredSize.BlockStartAscent()); aItem.SetAscent(childDesiredSize.BlockStartAscent());
} }
void
nsFlexContainerFrame::ReflowPlaceholders(nsPresContext* aPresContext,
const ReflowInput& aReflowInput,
nsTArray<nsIFrame*>& 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 /* virtual */ nscoord
nsFlexContainerFrame::GetMinISize(nsRenderingContext* aRenderingContext) nsFlexContainerFrame::GetMinISize(nsRenderingContext* aRenderingContext)
{ {

Просмотреть файл

@ -193,16 +193,23 @@ protected:
const ReflowInput& aItemReflowInput, const ReflowInput& aItemReflowInput,
const FlexboxAxisTracker& aAxisTracker); 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 * This method:
// return value has to be |nsresult|, in case we have to reflow a child * - Creates FlexItems for all of our child frames (except placeholders).
// to establish its flex base size and that reflow fails. * - 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, void GenerateFlexLines(nsPresContext* aPresContext,
const ReflowInput& aReflowInput, const ReflowInput& aReflowInput,
nscoord aContentBoxMainSize, nscoord aContentBoxMainSize,
nscoord aAvailableBSizeForContent, nscoord aAvailableBSizeForContent,
const nsTArray<StrutInfo>& aStruts, const nsTArray<StrutInfo>& aStruts,
const FlexboxAxisTracker& aAxisTracker, const FlexboxAxisTracker& aAxisTracker,
nsTArray<nsIFrame*>& aPlaceholders,
mozilla::LinkedList<FlexLine>& aLines); mozilla::LinkedList<FlexLine>& aLines);
nscoord GetMainSizeFromReflowInput(const ReflowInput& aReflowInput, nscoord GetMainSizeFromReflowInput(const ReflowInput& aReflowInput,
@ -259,6 +266,36 @@ protected:
mozilla::LogicalPoint& aFramePos, mozilla::LogicalPoint& aFramePos,
const nsSize& aContainerSize); 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<nsIFrame*>& aPlaceholders,
const mozilla::LogicalPoint& aContentBoxOrigin,
const nsSize& aContainerSize);
bool mChildrenHaveBeenReordered; // Have we ever had to reorder our kids bool mChildrenHaveBeenReordered; // Have we ever had to reorder our kids
// to satisfy their 'order' values? // to satisfy their 'order' values?