author | Daniel Holbert <dholbert@cs.stanford.edu> |
Fri, 27 Mar 2015 12:06:03 -0700 | |
changeset 236184 | 52c1155d7bff4dba1b5e53bdb07f62767ad1daef |
parent 236183 | e0e18a7b4e5d50faa5a2187d814012e943f71b1e |
child 236185 | 7c6354ab3e22d21460681b92b0fcb3bc78f7c8f5 |
push id | 57612 |
push user | dholbert@mozilla.com |
push date | Fri, 27 Mar 2015 19:08:20 +0000 |
treeherder | mozilla-inbound@2e874a1e7a7a [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mats |
bugs | 1148294 |
milestone | 39.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/layout/generic/nsFlexContainerFrame.cpp +++ b/layout/generic/nsFlexContainerFrame.cpp @@ -16,16 +16,17 @@ #include "nsPlaceholderFrame.h" #include "nsPresContext.h" #include "nsRenderingContext.h" #include "nsStyleContext.h" #include "prlog.h" #include <algorithm> #include "mozilla/LinkedList.h" #include "mozilla/FloatingPoint.h" +#include "WritingModes.h" using namespace mozilla; using namespace mozilla::layout; // Convenience typedefs for helper classes that we forward-declare in .h file // (so that nsFlexContainerFrame methods can use them as parameters): typedef nsFlexContainerFrame::FlexItem FlexItem; typedef nsFlexContainerFrame::FlexLine FlexLine; @@ -150,17 +151,18 @@ PhysicalCoordFromFlexRelativeCoord(nscoo (axisTracker_).IsMainAxisHorizontal() ? (width_) : (height_) #define GET_CROSS_COMPONENT(axisTracker_, width_, height_) \ (axisTracker_).IsCrossAxisHorizontal() ? (width_) : (height_) // Encapsulates our flex container's main & cross axes. class MOZ_STACK_CLASS nsFlexContainerFrame::FlexboxAxisTracker { public: - explicit FlexboxAxisTracker(nsFlexContainerFrame* aFlexContainerFrame); + FlexboxAxisTracker(const nsStylePosition* aStylePosition, + const WritingMode& aWM); // Accessors: AxisOrientationType GetMainAxis() const { return mMainAxis; } AxisOrientationType GetCrossAxis() const { return mCrossAxis; } bool IsMainAxisHorizontal() const { return IsAxisHorizontal(mMainAxis); } bool IsCrossAxisHorizontal() const { return IsAxisHorizontal(mCrossAxis); } @@ -978,17 +980,17 @@ IsOrderLEQ(nsIFrame* aFrame1, int32_t order2 = aRealFrame2->StylePosition()->mOrder; return order1 <= order2; } bool nsFlexContainerFrame::IsHorizontal() { - const FlexboxAxisTracker axisTracker(this); + const FlexboxAxisTracker axisTracker(StylePosition(), GetWritingMode()); return axisTracker.IsMainAxisHorizontal(); } FlexItem* nsFlexContainerFrame::GenerateFlexItemForChild( nsPresContext* aPresContext, nsIFrame* aChildFrame, const nsHTMLReflowState& aParentReflowState, @@ -2881,46 +2883,67 @@ SingleLineCrossAxisPositionTracker:: break; } default: NS_NOTREACHED("Unexpected align-self value"); break; } } -FlexboxAxisTracker::FlexboxAxisTracker( - nsFlexContainerFrame* aFlexContainerFrame) +// Utility function to convert an InlineDir to an AxisOrientationType +static inline AxisOrientationType +InlineDirToAxisOrientation(WritingMode::InlineDir aInlineDir) +{ + switch (aInlineDir) { + case WritingMode::eInlineLTR: + return eAxis_LR; + case WritingMode::eInlineRTL: + return eAxis_RL; + case WritingMode::eInlineTTB: + return eAxis_TB; + case WritingMode::eInlineBTT: + return eAxis_BT; + } + + MOZ_ASSERT_UNREACHABLE("Unhandled InlineDir"); + return eAxis_LR; // in case of unforseen error, assume English LTR text flow. +} + +// Utility function to convert a BlockDir to an AxisOrientationType +static inline AxisOrientationType +BlockDirToAxisOrientation(WritingMode::BlockDir aBlockDir) +{ + switch (aBlockDir) { + case WritingMode::eBlockLR: + return eAxis_LR; + case WritingMode::eBlockRL: + return eAxis_RL; + case WritingMode::eBlockTB: + return eAxis_TB; + // NOTE: WritingMode::eBlockBT (bottom-to-top) does not exist. + } + + MOZ_ASSERT_UNREACHABLE("Unhandled BlockDir"); + return eAxis_TB; // in case of unforseen error, assume English TTB block-flow +} + +FlexboxAxisTracker::FlexboxAxisTracker(const nsStylePosition* aStylePosition, + const WritingMode& aWM) : mAreAxesInternallyReversed(false) { - const nsStylePosition* pos = aFlexContainerFrame->StylePosition(); - uint32_t flexDirection = pos->mFlexDirection; - uint32_t cssDirection = - aFlexContainerFrame->StyleVisibility()->mDirection; - - MOZ_ASSERT(cssDirection == NS_STYLE_DIRECTION_LTR || - cssDirection == NS_STYLE_DIRECTION_RTL, - "Unexpected computed value for 'direction' property"); - // (Not asserting for flexDirection here; it's checked by the switch below.) - - // These are defined according to writing-modes' definitions of - // start/end (for the inline dimension) and before/after (for the block - // dimension), here: - // http://www.w3.org/TR/css3-writing-modes/#logical-directions - // (NOTE: I'm intentionally not calling this "inlineAxis"/"blockAxis", since + uint32_t flexDirection = aStylePosition->mFlexDirection; + + // Inline dimension ("start-to-end"): + // (NOTE: I'm intentionally not calling these "inlineAxis"/"blockAxis", since // those terms have explicit definition in the writing-modes spec, which are // the opposite of how I'd be using them here.) - // XXXdholbert Once we support the 'writing-mode' property, use its value - // here to further customize inlineDimension & blockDimension. - - // Inline dimension ("start-to-end"): AxisOrientationType inlineDimension = - cssDirection == NS_STYLE_DIRECTION_RTL ? eAxis_RL : eAxis_LR; - - // Block dimension ("before-to-after"): - AxisOrientationType blockDimension = eAxis_TB; + InlineDirToAxisOrientation(aWM.GetInlineDir()); + AxisOrientationType blockDimension = + BlockDirToAxisOrientation(aWM.GetBlockDir()); // Determine main axis: switch (flexDirection) { case NS_STYLE_FLEX_DIRECTION_ROW: mMainAxis = inlineDimension; break; case NS_STYLE_FLEX_DIRECTION_ROW_REVERSE: mMainAxis = GetReverseAxis(inlineDimension); @@ -2941,17 +2964,17 @@ FlexboxAxisTracker::FlexboxAxisTracker( if (flexDirection == NS_STYLE_FLEX_DIRECTION_COLUMN || flexDirection == NS_STYLE_FLEX_DIRECTION_COLUMN_REVERSE) { mCrossAxis = inlineDimension; } else { mCrossAxis = blockDimension; } // "flex-wrap: wrap-reverse" reverses our cross axis. - if (pos->mFlexWrap == NS_STYLE_FLEX_WRAP_WRAP_REVERSE) { + if (aStylePosition->mFlexWrap == NS_STYLE_FLEX_WRAP_WRAP_REVERSE) { mCrossAxis = GetReverseAxis(mCrossAxis); } // Master switch to enable/disable bug 983427's code for reversing our axes // and reversing some logic, to avoid reflowing children in bottom-to-top // order. (This switch can be removed eventually, but for now, it allows // this special-case code path to be compared against the normal code path.) static bool sPreventBottomToTopChildOrdering = true; @@ -3446,17 +3469,18 @@ nsFlexContainerFrame::Reflow(nsPresConte if (!HasAnyStateBits(NS_STATE_FLEX_CHILDREN_REORDERED)) { if (SortChildrenIfNeeded<IsOrderLEQ>()) { AddStateBits(NS_STATE_FLEX_CHILDREN_REORDERED); } } else { SortChildrenIfNeeded<IsOrderLEQWithDOMFallback>(); } - const FlexboxAxisTracker axisTracker(this); + const FlexboxAxisTracker axisTracker(aReflowState.mStylePosition, + aReflowState.GetWritingMode()); // If we're being fragmented into a constrained height, subtract off // borderpadding-top from it, to get the available height for our // content box. (Don't subtract if we're skipping top border/padding, // though.) nscoord availableHeightForContent = aReflowState.AvailableHeight(); if (availableHeightForContent != NS_UNCONSTRAINEDSIZE && !GetSkipSides().Top()) { @@ -3929,28 +3953,29 @@ nsFlexContainerFrame::ReflowFlexItem(nsP } /* virtual */ nscoord nsFlexContainerFrame::GetMinISize(nsRenderingContext* aRenderingContext) { nscoord minWidth = 0; DISPLAY_MIN_WIDTH(this, minWidth); - FlexboxAxisTracker axisTracker(this); + const nsStylePosition* stylePos = StylePosition(); + const FlexboxAxisTracker axisTracker(stylePos, GetWritingMode()); for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) { nscoord childMinWidth = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, e.get(), nsLayoutUtils::MIN_ISIZE); // For a horizontal single-line flex container, the intrinsic min width is // the sum of its items' min widths. // For a vertical flex container, or for a multi-line horizontal flex // container, the intrinsic min width is the max of its items' min widths. if (axisTracker.IsMainAxisHorizontal() && - NS_STYLE_FLEX_WRAP_NOWRAP == StylePosition()->mFlexWrap) { + NS_STYLE_FLEX_WRAP_NOWRAP == stylePos->mFlexWrap) { minWidth += childMinWidth; } else { minWidth = std::max(minWidth, childMinWidth); } } return minWidth; } @@ -3960,17 +3985,17 @@ nsFlexContainerFrame::GetPrefISize(nsRen nscoord prefWidth = 0; DISPLAY_PREF_WIDTH(this, prefWidth); // XXXdholbert Optimization: We could cache our intrinsic widths like // nsBlockFrame does (and return it early from this function if it's set). // Whenever anything happens that might change it, set it to // NS_INTRINSIC_WIDTH_UNKNOWN (like nsBlockFrame::MarkIntrinsicISizesDirty // does) - FlexboxAxisTracker axisTracker(this); + const FlexboxAxisTracker axisTracker(StylePosition(), GetWritingMode()); for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) { nscoord childPrefWidth = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, e.get(), nsLayoutUtils::PREF_ISIZE); if (axisTracker.IsMainAxisHorizontal()) { prefWidth += childPrefWidth; } else {