Bug 1269046 part 8: Rewrite CSSAlignUtils::AlignJustifySelf to use a single "flags" arg instead of boolean args. r?mats
MozReview-Commit-ID: 5loE21U7FF6
--- 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;