Bug 1269046 part 8: Rewrite CSSAlignUtils::AlignJustifySelf to use a single "flags" arg instead of boolean args. r=mats
authorDaniel Holbert <dholbert@cs.stanford.edu>
Mon, 31 Oct 2016 08:59:40 -0700
changeset 320291 7085eed57189b0b50cc466683c153af6325ee4d4
parent 320290 b44098de249789c5aa196575d15e14c9b31457fb
child 320292 c8965356a17237420621f7089af5146275e5efff
push id83346
push userdholbert@mozilla.com
push dateMon, 31 Oct 2016 15:59:57 +0000
treeherdermozilla-inbound@995211b23a55 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats
bugs1269046
milestone52.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
Bug 1269046 part 8: Rewrite CSSAlignUtils::AlignJustifySelf to use a single "flags" arg instead of boolean args. r=mats MozReview-Commit-ID: 5loE21U7FF6
layout/generic/CSSAlignUtils.cpp
layout/generic/CSSAlignUtils.h
layout/generic/nsAbsoluteContainingBlock.cpp
layout/generic/nsGridContainerFrame.cpp
--- a/layout/generic/CSSAlignUtils.cpp
+++ b/layout/generic/CSSAlignUtils.cpp
@@ -14,37 +14,41 @@ SpaceToFill(WritingMode aWM, const Logic
             LogicalAxis aAxis, nscoord aCBSize)
 {
   nscoord size = aAxis == eLogicalAxisBlock ? aSize.BSize(aWM)
                                             : aSize.ISize(aWM);
   return aCBSize - (size + aMargin);
 }
 
 nscoord
-CSSAlignUtils::AlignJustifySelf(uint8_t aAlignment, bool aOverflowSafe,
-                                LogicalAxis aAxis, bool aSameSide,
+CSSAlignUtils::AlignJustifySelf(uint8_t aAlignment, LogicalAxis aAxis,
+                                AlignJustifyFlags aFlags,
                                 nscoord aBaselineAdjust, nscoord aCBSize,
                                 const ReflowInput& aRI,
                                 const LogicalSize& aChildSize)
 {
   MOZ_ASSERT(aAlignment != NS_STYLE_ALIGN_AUTO,
              "auto values should have resolved already");
   MOZ_ASSERT(aAlignment != NS_STYLE_ALIGN_LEFT &&
              aAlignment != NS_STYLE_ALIGN_RIGHT,
              "caller should map that to the corresponding START/END");
 
+  // Promote aFlags to convenience bools:
+  const bool isOverflowSafe = !!(aFlags & AlignJustifyFlags::eOverflowSafe);
+  const bool isSameSide = !!(aFlags & AlignJustifyFlags::eSameSide);
+
   // Map some alignment values to 'start' / 'end'.
   switch (aAlignment) {
     case NS_STYLE_ALIGN_SELF_START: // align/justify-self: self-start
-      aAlignment = MOZ_LIKELY(aSameSide) ? NS_STYLE_ALIGN_START
-                                         : NS_STYLE_ALIGN_END;
+      aAlignment = MOZ_LIKELY(isSameSide) ? NS_STYLE_ALIGN_START
+                                          : NS_STYLE_ALIGN_END;
       break;
     case NS_STYLE_ALIGN_SELF_END: // align/justify-self: self-end
-      aAlignment = MOZ_LIKELY(aSameSide) ? NS_STYLE_ALIGN_END
-                                         : NS_STYLE_ALIGN_START;
+      aAlignment = MOZ_LIKELY(isSameSide) ? NS_STYLE_ALIGN_END
+                                          : NS_STYLE_ALIGN_START;
       break;
     // flex-start/flex-end are the same as start/end, in most contexts.
     // (They have special behavior in flex containers, so flex containers
     // should map them to some other value before calling this method.)
     case NS_STYLE_ALIGN_FLEX_START:
       aAlignment = NS_STYLE_ALIGN_START;
       break;
     case NS_STYLE_ALIGN_FLEX_END:
@@ -55,25 +59,25 @@ CSSAlignUtils::AlignJustifySelf(uint8_t 
   // XXX try to condense this code a bit by adding the necessary convenience
   // methods? (bug 1209710)
 
   // Get the item's margin corresponding to the container's start/end side.
   const LogicalMargin margin = aRI.ComputedLogicalMargin();
   WritingMode wm = aRI.GetWritingMode();
   nscoord marginStart, marginEnd;
   if (aAxis == eLogicalAxisBlock) {
-    if (MOZ_LIKELY(aSameSide)) {
+    if (MOZ_LIKELY(isSameSide)) {
       marginStart = margin.BStart(wm);
       marginEnd = margin.BEnd(wm);
     } else {
       marginStart = margin.BEnd(wm);
       marginEnd = margin.BStart(wm);
     }
   } else {
-    if (MOZ_LIKELY(aSameSide)) {
+    if (MOZ_LIKELY(isSameSide)) {
       marginStart = margin.IStart(wm);
       marginEnd = margin.IEnd(wm);
     } else {
       marginStart = margin.IEnd(wm);
       marginEnd = margin.IStart(wm);
     }
   }
 
@@ -86,42 +90,42 @@ CSSAlignUtils::AlignJustifySelf(uint8_t 
   } else {
     hasAutoMarginStart = styleMargin.GetIStartUnit(wm) == eStyleUnit_Auto;
     hasAutoMarginEnd = styleMargin.GetIEndUnit(wm) == eStyleUnit_Auto;
   }
 
   // https://drafts.csswg.org/css-align-3/#overflow-values
   // This implements <overflow-position> = 'safe'.
   // And auto-margins: https://drafts.csswg.org/css-grid/#auto-margins
-  if ((MOZ_UNLIKELY(aOverflowSafe) && aAlignment != NS_STYLE_ALIGN_START) ||
+  if ((MOZ_UNLIKELY(isOverflowSafe) && aAlignment != NS_STYLE_ALIGN_START) ||
       hasAutoMarginStart || hasAutoMarginEnd) {
     nscoord space = SpaceToFill(wm, aChildSize, marginStart + marginEnd,
                                 aAxis, aCBSize);
     // XXX we might want to include == 0 here as an optimization -
     // I need to see what the baseline/last-baseline code looks like first.
     if (space < 0) {
       // "Overflowing elements ignore their auto margins and overflow
       // in the end directions"
       aAlignment = NS_STYLE_ALIGN_START;
     } else if (hasAutoMarginEnd) {
       aAlignment = hasAutoMarginStart ? NS_STYLE_ALIGN_CENTER
-                                      : (aSameSide ? NS_STYLE_ALIGN_START
-                                                   : NS_STYLE_ALIGN_END);
+                                      : (isSameSide ? NS_STYLE_ALIGN_START
+                                                    : NS_STYLE_ALIGN_END);
     } else if (hasAutoMarginStart) {
-      aAlignment = aSameSide ? NS_STYLE_ALIGN_END : NS_STYLE_ALIGN_START;
+      aAlignment = isSameSide ? NS_STYLE_ALIGN_END : NS_STYLE_ALIGN_START;
     }
   }
 
   // Determine the offset for the child frame (its border-box) which will
   // achieve the requested alignment.
   nscoord offset = 0;
   switch (aAlignment) {
     case NS_STYLE_ALIGN_BASELINE:
     case NS_STYLE_ALIGN_LAST_BASELINE:
-      if (MOZ_LIKELY(aSameSide == (aAlignment == NS_STYLE_ALIGN_BASELINE))) {
+      if (MOZ_LIKELY(isSameSide == (aAlignment == NS_STYLE_ALIGN_BASELINE))) {
         offset = marginStart + aBaselineAdjust;
       } else {
         nscoord size = aAxis == eLogicalAxisBlock ? aChildSize.BSize(wm)
                                                   : aChildSize.ISize(wm);
         offset = aCBSize - (size + marginEnd) - aBaselineAdjust;
       }
       break;
     case NS_STYLE_ALIGN_STRETCH:
--- a/layout/generic/CSSAlignUtils.h
+++ b/layout/generic/CSSAlignUtils.h
@@ -10,38 +10,48 @@
 
 #include "mozilla/WritingModes.h"
 
 namespace mozilla {
 
 class CSSAlignUtils {
 public:
   /**
+   * Flags to customize the behavior of AlignJustifySelf:
+   */
+  enum class AlignJustifyFlags {
+    eNoFlags           = 0,
+    // Indicates that we have <overflow-position> = safe.
+    eOverflowSafe      = 1 << 0,
+    // Indicates that the container's start side in aAxis is the same
+    // as the child's start side in the child's parallel axis.
+    eSameSide          = 1 << 1,
+  };
+
+  /**
    * This computes the aligned offset of a CSS-aligned child within its
    * alignment container. The returned offset is distance between the
    * logical "start" edge of the alignment container & the logical "start" edge
    * of the aligned child (in terms of the alignment container's writing mode).
    *
    * @param aAlignment An enumerated value representing a keyword for
    *                   "align-self" or "justify-self". The values
    *                   NS_STYLE_ALIGN_{AUTO,LEFT,RIGHT} must *not* be
    *                   passed here; this method expects the caller to have
    *                   already resolved those to 'start', 'end', or 'stretch'.
-   * @param aOverflowSafe Indicates whether we have <overflow-position> = safe.
    * @param aAxis The container's axis in which we're doing alignment.
-   * @param aSameSide Indicates whether the container's start side in aAxis is
-   *                  the same as the child's start side, in the child's
-   *                  parallel axis.
    * @param aBaselineAdjust The amount to offset baseline-aligned children.
    * @param aCBSize The size of the alignment container, in its aAxis.
    * @param aRI A ReflowInput for the child.
    * @param aChildSize The child's LogicalSize (in its own writing mode).
    */
-  static nscoord AlignJustifySelf(uint8_t aAlignment, bool aOverflowSafe,
-                                  LogicalAxis aAxis, bool aSameSide,
+  static nscoord AlignJustifySelf(uint8_t aAlignment, LogicalAxis aAxis,
+                                  AlignJustifyFlags aFlags,
                                   nscoord aBaselineAdjust, nscoord aCBSize,
                                   const ReflowInput& aRI,
                                   const LogicalSize& aChildSize);
 };
 
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CSSAlignUtils::AlignJustifyFlags)
+
 } // namespace mozilla
 
 #endif // mozilla_CSSAlignUtils_h
--- a/layout/generic/nsAbsoluteContainingBlock.cpp
+++ b/layout/generic/nsAbsoluteContainingBlock.cpp
@@ -35,16 +35,18 @@ static void PrettyUC(nscoord aSize, char
       snprintf(aBuf, aBufSize, "%d", aSize);
     }
   }
 }
 #endif
 
 using namespace mozilla;
 
+typedef mozilla::CSSAlignUtils::AlignJustifyFlags AlignJustifyFlags;
+
 void
 nsAbsoluteContainingBlock::SetInitialChildList(nsIFrame*       aDelegatingFrame,
                                                ChildListID     aListID,
                                                nsFrameList&    aChildList)
 {
   NS_PRECONDITION(mChildListID == aListID, "unexpected child list name");
 #ifdef DEBUG
   nsFrame::VerifyDirtyBitSet(aChildList);
@@ -415,49 +417,51 @@ OffsetToAlignedStaticPos(const ReflowInp
   } else {
     NS_ERROR("Unsupported container for abpsos CSS Box Alignment");
     return 0; // (leave the child at the start of its alignment container)
   }
 
   nscoord alignAreaSizeInAxis = (pcAxis == eLogicalAxisInline)
     ? alignAreaSize.ISize(pcWM)
     : alignAreaSize.BSize(pcWM);
-  // XXXdholbert: Handle <overflow-position> in bug 1311892.  For now, behave
+
+  AlignJustifyFlags flags = AlignJustifyFlags::eNoFlags;
+  uint16_t alignConst =
+    aPlaceholderContainer->CSSAlignmentForAbsPosChild(aKidReflowInput, pcAxis);
+  // XXXdholbert: Handle <overflow-position> in bug 1311892 (by conditionally
+  // setting AlignJustifyFlags::eOverflowSafe in |flags|.)  For now, we behave
   // as if "unsafe" was the specified value (which is basically equivalent to
   // the default behavior, when no value is specified -- though the default
   // behavior also has some [at-risk] extra nuance about scroll containers...)
-  const bool overflowSafe = false;
-
-  uint16_t alignConst =
-    aPlaceholderContainer->CSSAlignmentForAbsPosChild(aKidReflowInput, pcAxis);
-  // XXX strip off <overflow-position> bits until we implement it (bug 1311892)
+  // For now we ignore & strip off <overflow-position> bits, until bug 1311892.
   alignConst &= ~NS_STYLE_ALIGN_FLAG_BITS;
 
   // Find out if placeholder-container & the OOF child have the same start-sides
   // in the placeholder-container's pcAxis.
   WritingMode kidWM = aKidReflowInput.GetWritingMode();
-  bool sameSidePCAndKid = pcWM.ParallelAxisStartsOnSameSide(pcAxis, kidWM);
+  if (pcWM.ParallelAxisStartsOnSameSide(pcAxis, kidWM)) {
+    flags |= AlignJustifyFlags::eSameSide;
+  }
 
   // (baselineAdjust is unused. CSSAlignmentForAbsPosChild() should've
   // converted 'baseline'/'last-baseline' enums to their fallback values.)
   const nscoord baselineAdjust = nscoord(0);
 
   // AlignJustifySelf operates in the kid's writing mode, so we need to
   // represent the child's size and the desired axis in that writing mode:
   LogicalSize kidSizeInOwnWM = aKidSizeInAbsPosCBWM.ConvertTo(kidWM,
                                                               aAbsPosCBWM);
   LogicalAxis kidAxis = (kidWM.IsOrthogonalTo(aAbsPosCBWM)
                          ? GetOrthogonalAxis(aAbsPosCBAxis)
                          : aAbsPosCBAxis);
 
   nscoord offset =
-    CSSAlignUtils::AlignJustifySelf(alignConst, overflowSafe,
-                                    kidAxis, sameSidePCAndKid, baselineAdjust,
-                                    alignAreaSizeInAxis, aKidReflowInput,
-                                    kidSizeInOwnWM);
+    CSSAlignUtils::AlignJustifySelf(alignConst, kidAxis, flags,
+                                    baselineAdjust, alignAreaSizeInAxis,
+                                    aKidReflowInput, kidSizeInOwnWM);
 
   // "offset" is in terms of the CSS Box Alignment container (i.e. it's in
   // terms of pcWM). But our return value needs to in terms of the containing
   // block's writing mode, which might have the opposite directionality in the
   // given axis. In that case, we just need to negate "offset" when returning,
   // to make it have the right effect as an offset for coordinates in the
   // containing block's writing mode.
   if (!pcWM.ParallelAxisStartsOnSameSide(pcAxis, aAbsPosCBWM)) {
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -30,22 +30,24 @@
 #include "nsStyleContext.h"
 #include "mozilla/dom/GridBinding.h"
 
 #if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 8
 #define CLANG_CRASH_BUG 1
 #endif
 
 using namespace mozilla;
+
 typedef nsAbsoluteContainingBlock::AbsPosReflowFlags AbsPosReflowFlags;
 typedef nsGridContainerFrame::TrackSize TrackSize;
 const uint32_t nsGridContainerFrame::kTranslatedMaxLine =
   uint32_t(nsStyleGridLine::kMaxLine - nsStyleGridLine::kMinLine);
 const uint32_t nsGridContainerFrame::kAutoLine = kTranslatedMaxLine + 3457U;
 typedef nsTHashtable< nsPtrHashKey<nsIFrame> > FrameHashtable;
+typedef mozilla::CSSAlignUtils::AlignJustifyFlags AlignJustifyFlags;
 
 // https://drafts.csswg.org/css-sizing/#constraints
 enum class SizingConstraint
 {
   eMinContent,  // sizing under min-content constraint
   eMaxContent,  // sizing under max-content constraint
   eNoConstraint // no constraint, used during Reflow
 };
@@ -2581,89 +2583,102 @@ GetDisplayFlagsForGridItem(nsIFrame* aFr
   if (pos->mZIndex.GetUnit() == eStyleUnit_Integer) {
     return nsIFrame::DISPLAY_CHILD_FORCE_STACKING_CONTEXT;
   }
   return nsIFrame::DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT;
 }
 
 // Align an item's margin box in its aAxis inside aCBSize.
 static void
-AlignJustifySelf(uint8_t aAlignment, bool aOverflowSafe, LogicalAxis aAxis,
-                 bool aSameSide, nscoord aBaselineAdjust, nscoord aCBSize,
+AlignJustifySelf(uint8_t aAlignment, LogicalAxis aAxis,
+                 AlignJustifyFlags aFlags,
+                 nscoord aBaselineAdjust, nscoord aCBSize,
                  const ReflowInput& aRI, const LogicalSize& aChildSize,
                  LogicalPoint* aPos)
 {
   MOZ_ASSERT(aAlignment != NS_STYLE_ALIGN_AUTO, "unexpected 'auto' "
              "computed value for normal flow grid item");
 
   // NOTE: this is the resulting frame offset (border box).
   nscoord offset =
-    CSSAlignUtils::AlignJustifySelf(aAlignment, aOverflowSafe, aAxis,
-                                    aSameSide, aBaselineAdjust, aCBSize,
+    CSSAlignUtils::AlignJustifySelf(aAlignment, aAxis, aFlags,
+                                    aBaselineAdjust, aCBSize,
                                     aRI, aChildSize);
 
   // Set the position (aPos) for the requested alignment.
   if (offset != 0) {
     WritingMode wm = aRI.GetWritingMode();
     nscoord& pos = aAxis == eLogicalAxisBlock ? aPos->B(wm) : aPos->I(wm);
-    pos += MOZ_LIKELY(aSameSide) ? offset : -offset;
+    pos += MOZ_LIKELY(aFlags & AlignJustifyFlags::eSameSide) ? offset : -offset;
   }
 }
 
 static void
 AlignSelf(const nsGridContainerFrame::GridItemInfo& aGridItem,
           uint8_t aAlignSelf, nscoord aCBSize, const WritingMode aCBWM,
           const ReflowInput& aRI, const LogicalSize& aSize,
           LogicalPoint* aPos)
 {
   auto alignSelf = aAlignSelf;
-  bool overflowSafe = alignSelf & NS_STYLE_ALIGN_SAFE;
+
+  AlignJustifyFlags flags = AlignJustifyFlags::eNoFlags;
+  if (alignSelf & NS_STYLE_ALIGN_SAFE) {
+    flags |= AlignJustifyFlags::eOverflowSafe;
+  }
   alignSelf &= ~NS_STYLE_ALIGN_FLAG_BITS;
+
+  WritingMode childWM = aRI.GetWritingMode();
+  if (aCBWM.ParallelAxisStartsOnSameSide(eLogicalAxisBlock, childWM)) {
+    flags |= AlignJustifyFlags::eSameSide;
+  }
+
   // Grid's 'align-self' axis is never parallel to the container's inline axis.
   if (alignSelf == NS_STYLE_ALIGN_LEFT || alignSelf == NS_STYLE_ALIGN_RIGHT) {
     alignSelf = NS_STYLE_ALIGN_START;
   }
   if (MOZ_LIKELY(alignSelf == NS_STYLE_ALIGN_NORMAL)) {
     alignSelf = NS_STYLE_ALIGN_STRETCH;
   }
-  WritingMode childWM = aRI.GetWritingMode();
-  // |sameSide| is true if the container's start side in this axis is the same
-  // as the child's start side, in the child's parallel axis.
-  bool sameSide = aCBWM.ParallelAxisStartsOnSameSide(eLogicalAxisBlock,
-                                                     childWM);
+
   nscoord baselineAdjust = 0;
   if (alignSelf == NS_STYLE_ALIGN_BASELINE ||
       alignSelf == NS_STYLE_ALIGN_LAST_BASELINE) {
     alignSelf = aGridItem.GetSelfBaseline(alignSelf, eLogicalAxisBlock,
                                           &baselineAdjust);
   }
 
   bool isOrthogonal = aCBWM.IsOrthogonalTo(childWM);
   LogicalAxis axis = isOrthogonal ? eLogicalAxisInline : eLogicalAxisBlock;
-  AlignJustifySelf(alignSelf, overflowSafe, axis, sameSide, baselineAdjust,
+  AlignJustifySelf(alignSelf, axis, flags, baselineAdjust,
                    aCBSize, aRI, aSize, aPos);
 }
 
 static void
 JustifySelf(const nsGridContainerFrame::GridItemInfo& aGridItem,
             uint8_t aJustifySelf, nscoord aCBSize, const WritingMode aCBWM,
             const ReflowInput& aRI, const LogicalSize& aSize,
             LogicalPoint* aPos)
 {
   auto justifySelf = aJustifySelf;
-  bool overflowSafe = justifySelf & NS_STYLE_JUSTIFY_SAFE;
+
+  AlignJustifyFlags flags = AlignJustifyFlags::eNoFlags;
+  if (justifySelf & NS_STYLE_JUSTIFY_SAFE) {
+    flags |= AlignJustifyFlags::eOverflowSafe;
+  }
   justifySelf &= ~NS_STYLE_JUSTIFY_FLAG_BITS;
+
+  WritingMode childWM = aRI.GetWritingMode();
+  if (aCBWM.ParallelAxisStartsOnSameSide(eLogicalAxisInline, childWM)) {
+    flags |= AlignJustifyFlags::eSameSide;
+  }
+
   if (MOZ_LIKELY(justifySelf == NS_STYLE_ALIGN_NORMAL)) {
     justifySelf = NS_STYLE_ALIGN_STRETCH;
   }
-  WritingMode childWM = aRI.GetWritingMode();
-  // |sameSide| is true if the container's start side in this axis is the same
-  // as the child's start side, in the child's parallel axis.
-  bool sameSide = aCBWM.ParallelAxisStartsOnSameSide(eLogicalAxisInline,
-                                                     childWM);
+
   nscoord baselineAdjust = 0;
   // Grid's 'justify-self' axis is always parallel to the container's inline
   // axis, so justify-self:left|right always applies.
   switch (justifySelf) {
     case NS_STYLE_JUSTIFY_LEFT:
       justifySelf = aCBWM.IsBidiLTR() ? NS_STYLE_JUSTIFY_START
                                       : NS_STYLE_JUSTIFY_END;
       break;
@@ -2675,17 +2690,17 @@ JustifySelf(const nsGridContainerFrame::
     case NS_STYLE_JUSTIFY_LAST_BASELINE:
       justifySelf = aGridItem.GetSelfBaseline(justifySelf, eLogicalAxisInline,
                                               &baselineAdjust);
       break;
   }
 
   bool isOrthogonal = aCBWM.IsOrthogonalTo(childWM);
   LogicalAxis axis = isOrthogonal ? eLogicalAxisBlock : eLogicalAxisInline;
-  AlignJustifySelf(justifySelf, overflowSafe, axis, sameSide, baselineAdjust,
+  AlignJustifySelf(justifySelf, axis, flags, baselineAdjust,
                    aCBSize, aRI, aSize, aPos);
 }
 
 static uint16_t
 GetAlignJustifyValue(uint16_t aAlignment, const WritingMode aWM,
                      const bool aIsAlign, bool* aOverflowSafe)
 {
   *aOverflowSafe = aAlignment & NS_STYLE_ALIGN_SAFE;