Bug 1269046 part 8: Rewrite CSSAlignUtils::AlignJustifySelf to use a single "flags" arg instead of boolean args. r?mats draft
authorDaniel Holbert <dholbert@cs.stanford.edu>
Sun, 30 Oct 2016 22:14:17 -0700
changeset 431693 a07f6bebf2e4dfcabcb00be79f28792b460e4c60
parent 431692 7eac54fe0163fa04a557dece967e1a520bfd30a1
child 431694 e2cf60d41d1b91f0505904002dff0f628c886897
push id34081
push userdholbert@mozilla.com
push dateMon, 31 Oct 2016 05:22:31 +0000
reviewersmats
bugs1269046
milestone52.0a1
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;