Bug 1269046 part 7: Give nsFlexContainerFrame a CSSAlignmentForAbsPosChild() implementation (to determine appropriate align enum for abspos children). r=mats
MozReview-Commit-ID: LFQfKPlR9Gv
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -1190,16 +1190,143 @@ IsOrderLEQ(nsIFrame* aFrame1,
bool isInLegacyBox = nsFlexContainerFrame::IsLegacyBox(aFrame1->GetParent());
int32_t order1 = GetOrderOrBoxOrdinalGroup(aFrame1, isInLegacyBox);
int32_t order2 = GetOrderOrBoxOrdinalGroup(aFrame2, isInLegacyBox);
return order1 <= order2;
}
+uint8_t
+SimplifyAlignOrJustifyContentForOneItem(uint16_t aAlignmentVal,
+ bool aIsAlign)
+{
+ // Mask away any explicit fallback, to get the main (non-fallback) part of
+ // the specified value:
+ uint16_t specified = aAlignmentVal & NS_STYLE_ALIGN_ALL_BITS;
+
+ // XXX strip off <overflow-position> bits until we implement it (bug 1311892)
+ specified &= ~NS_STYLE_ALIGN_FLAG_BITS;
+
+ // FIRST: handle a special-case for "justify-content:stretch" (or equivalent),
+ // which requires that we ignore any author-provided explicit fallback value.
+ if (specified == NS_STYLE_ALIGN_NORMAL) {
+ // In a flex container, *-content: "'normal' behaves as 'stretch'".
+ // Do that conversion early, so it benefits from our 'stretch' special-case.
+ // https://drafts.csswg.org/css-align-3/#distribution-flex
+ specified = NS_STYLE_ALIGN_STRETCH;
+ }
+ if (!aIsAlign && specified == NS_STYLE_ALIGN_STRETCH) {
+ // In a flex container, in "justify-content Axis: [...] 'stretch' behaves
+ // as 'flex-start' (ignoring the specified fallback alignment, if any)."
+ // https://drafts.csswg.org/css-align-3/#distribution-flex
+ // So, we just directly return 'flex-start', & ignore explicit fallback..
+ return NS_STYLE_ALIGN_FLEX_START;
+ }
+
+ // Now check for an explicit fallback value (and if it's present, use it).
+ uint16_t explicitFallback = aAlignmentVal >> NS_STYLE_ALIGN_ALL_SHIFT;
+ if (explicitFallback) {
+ // XXX strip off <overflow-position> bits until we implement it
+ // (bug 1311892)
+ explicitFallback &= ~NS_STYLE_ALIGN_FLAG_BITS;
+ return explicitFallback;
+ }
+
+ // There's no explicit fallback. Use the implied fallback values for
+ // space-{between,around,evenly} (since those values only make sense with
+ // multiple alignment subjects), and otherwise just use the specified value:
+ switch (specified) {
+ case NS_STYLE_ALIGN_SPACE_BETWEEN:
+ return NS_STYLE_ALIGN_START;
+ case NS_STYLE_ALIGN_SPACE_AROUND:
+ case NS_STYLE_ALIGN_SPACE_EVENLY:
+ return NS_STYLE_ALIGN_CENTER;
+ default:
+ return specified;
+ }
+}
+
+uint16_t
+nsFlexContainerFrame::CSSAlignmentForAbsPosChild(
+ const ReflowInput& aChildRI,
+ LogicalAxis aLogicalAxis) const
+{
+ WritingMode wm = GetWritingMode();
+ const FlexboxAxisTracker
+ axisTracker(this, wm, AxisTrackerFlags::eAllowBottomToTopChildOrdering);
+
+ // If we're row-oriented and the caller is asking about our inline axis (or
+ // alternately, if we're column-oriented and the caller is asking about our
+ // block axis), then the caller is really asking about our *main* axis.
+ // Otherwise, the caller is asking about our cross axis.
+ const bool isMainAxis = (axisTracker.IsRowOriented() ==
+ (aLogicalAxis == eLogicalAxisInline));
+ const nsStylePosition* containerStylePos = StylePosition();
+ const bool isAxisReversed = isMainAxis ? axisTracker.IsMainAxisReversed()
+ : axisTracker.IsCrossAxisReversed();
+
+ uint8_t alignment;
+ if (isMainAxis) {
+ alignment = SimplifyAlignOrJustifyContentForOneItem(
+ containerStylePos->mJustifyContent,
+ /*aIsAlign = */false);
+ } else {
+ const uint8_t alignContent = SimplifyAlignOrJustifyContentForOneItem(
+ containerStylePos->mAlignContent,
+ /*aIsAlign = */true);
+ if (NS_STYLE_FLEX_WRAP_NOWRAP != containerStylePos->mFlexWrap &&
+ alignContent != NS_STYLE_ALIGN_STRETCH) {
+ // Multi-line, align-content isn't stretch --> align-content determines
+ // this child's alignment in the cross axis.
+ alignment = alignContent;
+ } else {
+ // Single-line, or multi-line but the (one) line stretches to fill
+ // container. Respect align-self.
+ alignment = aChildRI.mStylePosition->UsedAlignSelf(nullptr);
+ // XXX strip off <overflow-position> bits until we implement it
+ // (bug 1311892)
+ alignment &= ~NS_STYLE_ALIGN_FLAG_BITS;
+
+ if (alignment == NS_STYLE_ALIGN_NORMAL) {
+ // "the 'normal' keyword behaves as 'start' on replaced
+ // absolutely-positioned boxes, and behaves as 'stretch' on all other
+ // absolutely-positioned boxes."
+ // https://drafts.csswg.org/css-align/#align-abspos
+ alignment = aChildRI.mFrame->IsFrameOfType(nsIFrame::eReplaced) ?
+ NS_STYLE_ALIGN_START : NS_STYLE_ALIGN_STRETCH;
+ }
+ }
+ }
+
+ // Resolve flex-start, flex-end, auto, left, right, baseline, last-baseline;
+ if (alignment == NS_STYLE_ALIGN_FLEX_START) {
+ alignment = isAxisReversed ? NS_STYLE_ALIGN_END : NS_STYLE_ALIGN_START;
+ } else if (alignment == NS_STYLE_ALIGN_FLEX_END) {
+ alignment = isAxisReversed ? NS_STYLE_ALIGN_START : NS_STYLE_ALIGN_END;
+ } else if (alignment == NS_STYLE_ALIGN_AUTO) {
+ alignment = NS_STYLE_ALIGN_START;
+ } else if (alignment == NS_STYLE_ALIGN_LEFT ||
+ alignment == NS_STYLE_ALIGN_RIGHT) {
+ if (aLogicalAxis == eLogicalAxisInline) {
+ const bool isLeft = (alignment == NS_STYLE_ALIGN_LEFT);
+ alignment = (isLeft == wm.IsBidiLTR()) ? NS_STYLE_ALIGN_START
+ : NS_STYLE_ALIGN_END;
+ } else {
+ alignment = NS_STYLE_ALIGN_START;
+ }
+ } else if (alignment == NS_STYLE_ALIGN_BASELINE) {
+ alignment = NS_STYLE_ALIGN_START;
+ } else if (alignment == NS_STYLE_ALIGN_LAST_BASELINE) {
+ alignment = NS_STYLE_ALIGN_END;
+ }
+
+ return alignment;
+}
+
bool
nsFlexContainerFrame::IsHorizontal()
{
const FlexboxAxisTracker axisTracker(this, GetWritingMode());
return axisTracker.IsMainAxisHorizontal();
}
UniquePtr<FlexItem>
--- a/layout/generic/nsFlexContainerFrame.h
+++ b/layout/generic/nsFlexContainerFrame.h
@@ -74,16 +74,21 @@ public:
virtual nsIAtom* GetType() const override;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
nscoord GetLogicalBaseline(mozilla::WritingMode aWM) const override;
+ // nsContainerFrame overrides
+ uint16_t CSSAlignmentForAbsPosChild(
+ const ReflowInput& aChildRI,
+ mozilla::LogicalAxis aLogicalAxis) const override;
+
// Flexbox-specific public methods
bool IsHorizontal();
/**
* Helper function to calculate packing space and initial offset of alignment
* subjects in MainAxisPositionTracker() and CrossAxisPositionTracker() for
* space-between, space-around, and space-evenly.
*
@@ -274,18 +279,16 @@ protected:
* 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).
--- a/layout/reftests/flexbox/reftest.list
+++ b/layout/reftests/flexbox/reftest.list
@@ -68,22 +68,22 @@ fuzzy-if(skiaContent,3,10) == flexbox-dy
== flexbox-float-2a.xhtml flexbox-float-2-ref.xhtml
== flexbox-float-2b.xhtml flexbox-float-2-ref.xhtml
# Tests for the order in which we paint flex items
fails == flexbox-paint-ordering-3.html flexbox-paint-ordering-3-ref.html # bug 874718
# Tests for handling of absolutely/fixed/relatively-positioned flex items.
== flexbox-position-absolute-1.xhtml flexbox-position-absolute-1-ref.xhtml
-fails == flexbox-position-absolute-2.xhtml flexbox-position-absolute-2-ref.xhtml # bug 1269046
+== flexbox-position-absolute-2.xhtml flexbox-position-absolute-2-ref.xhtml
== flexbox-position-absolute-3.xhtml flexbox-position-absolute-3-ref.xhtml
== flexbox-position-absolute-4.xhtml flexbox-position-absolute-4-ref.xhtml
== flexbox-position-fixed-3.xhtml flexbox-position-fixed-3-ref.xhtml
fuzzy-if(Android,16,400) == flexbox-position-fixed-1.xhtml flexbox-position-fixed-1-ref.xhtml
-fuzzy-if(Android,16,400) fails == flexbox-position-fixed-2.xhtml flexbox-position-fixed-2-ref.xhtml # bug 1269046
+fuzzy-if(Android,16,400) == flexbox-position-fixed-2.xhtml flexbox-position-fixed-2-ref.xhtml
== flexbox-position-fixed-3.xhtml flexbox-position-fixed-3-ref.xhtml
== flexbox-position-fixed-4.xhtml flexbox-position-fixed-4-ref.xhtml
# Tests for inline content in a flexbox that gets wrapped in an anonymous block
fails == flexbox-inlinecontent-horiz-1a.xhtml flexbox-inlinecontent-horiz-1-ref.xhtml # reference case rendering is incorrect; bug 858333
fails == flexbox-inlinecontent-horiz-1b.xhtml flexbox-inlinecontent-horiz-1-ref.xhtml # reference case rendering is incorrect; bug 858333
== flexbox-inlinecontent-horiz-2.xhtml flexbox-inlinecontent-horiz-2-ref.xhtml
== flexbox-inlinecontent-horiz-3a.xhtml flexbox-inlinecontent-horiz-3-ref.xhtml