mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1269046 part 1: Spin out some grid alignment code into a helper method, in a new CSSAlignUtils class. r=mats
MozReview-Commit-ID: 1Eh2CreOLTC
This commit is contained in:
parent
d7a39cb724
commit
2a8bcc81e7
148
layout/generic/CSSAlignUtils.cpp
Normal file
148
layout/generic/CSSAlignUtils.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Utility code for performing CSS Box Alignment */
|
||||
|
||||
#include "CSSAlignUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
static nscoord
|
||||
SpaceToFill(WritingMode aWM, const LogicalSize& aSize, nscoord aMargin,
|
||||
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,
|
||||
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");
|
||||
|
||||
// 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;
|
||||
break;
|
||||
case NS_STYLE_ALIGN_SELF_END: // align/justify-self: self-end
|
||||
aAlignment = MOZ_LIKELY(aSameSide) ? NS_STYLE_ALIGN_END
|
||||
: NS_STYLE_ALIGN_START;
|
||||
break;
|
||||
case NS_STYLE_ALIGN_FLEX_START: // same as 'start' for Grid
|
||||
aAlignment = NS_STYLE_ALIGN_START;
|
||||
break;
|
||||
case NS_STYLE_ALIGN_FLEX_END: // same as 'end' for Grid
|
||||
aAlignment = NS_STYLE_ALIGN_END;
|
||||
break;
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
marginStart = margin.BStart(wm);
|
||||
marginEnd = margin.BEnd(wm);
|
||||
} else {
|
||||
marginStart = margin.BEnd(wm);
|
||||
marginEnd = margin.BStart(wm);
|
||||
}
|
||||
} else {
|
||||
if (MOZ_LIKELY(aSameSide)) {
|
||||
marginStart = margin.IStart(wm);
|
||||
marginEnd = margin.IEnd(wm);
|
||||
} else {
|
||||
marginStart = margin.IEnd(wm);
|
||||
marginEnd = margin.IStart(wm);
|
||||
}
|
||||
}
|
||||
|
||||
const auto& styleMargin = aRI.mStyleMargin->mMargin;
|
||||
bool hasAutoMarginStart;
|
||||
bool hasAutoMarginEnd;
|
||||
if (aAxis == eLogicalAxisBlock) {
|
||||
hasAutoMarginStart = styleMargin.GetBStartUnit(wm) == eStyleUnit_Auto;
|
||||
hasAutoMarginEnd = styleMargin.GetBEndUnit(wm) == eStyleUnit_Auto;
|
||||
} 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) ||
|
||||
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);
|
||||
} else if (hasAutoMarginStart) {
|
||||
aAlignment = aSameSide ? 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))) {
|
||||
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:
|
||||
MOZ_FALLTHROUGH; // ComputeSize() deals with it
|
||||
case NS_STYLE_ALIGN_START:
|
||||
offset = marginStart;
|
||||
break;
|
||||
case NS_STYLE_ALIGN_END: {
|
||||
nscoord size = aAxis == eLogicalAxisBlock ? aChildSize.BSize(wm)
|
||||
: aChildSize.ISize(wm);
|
||||
offset = aCBSize - (size + marginEnd);
|
||||
break;
|
||||
}
|
||||
case NS_STYLE_ALIGN_CENTER: {
|
||||
nscoord size = aAxis == eLogicalAxisBlock ? aChildSize.BSize(wm)
|
||||
: aChildSize.ISize(wm);
|
||||
offset = (aCBSize - size + marginStart - marginEnd) / 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("unknown align-/justify-self value");
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
47
layout/generic/CSSAlignUtils.h
Normal file
47
layout/generic/CSSAlignUtils.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Utility code for performing CSS Box Alignment */
|
||||
|
||||
#ifndef mozilla_CSSAlignUtils_h
|
||||
#define mozilla_CSSAlignUtils_h
|
||||
|
||||
#include "mozilla/WritingModes.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class CSSAlignUtils {
|
||||
public:
|
||||
/**
|
||||
* 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,
|
||||
nscoord aBaselineAdjust, nscoord aCBSize,
|
||||
const ReflowInput& aRI,
|
||||
const LogicalSize& aChildSize);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_CSSAlignUtils_h
|
@ -109,6 +109,7 @@ EXPORTS += [
|
||||
]
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
'CSSAlignUtils.h',
|
||||
'ReflowInput.h',
|
||||
'ReflowOutput.h',
|
||||
'WritingModes.h',
|
||||
@ -125,6 +126,7 @@ EXPORTS.mozilla.layout += [
|
||||
UNIFIED_SOURCES += [
|
||||
'AsyncScrollBase.cpp',
|
||||
'BlockReflowInput.cpp',
|
||||
'CSSAlignUtils.cpp',
|
||||
'DetailsFrame.cpp',
|
||||
'FrameChildList.cpp',
|
||||
'MathMLTextRunFactory.cpp',
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include <algorithm> // for std::stable_sort
|
||||
#include <limits>
|
||||
#include "mozilla/CSSAlignUtils.h"
|
||||
#include "mozilla/Function.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/PodOperations.h" // for PodZero
|
||||
@ -2583,15 +2584,6 @@ GetDisplayFlagsForGridItem(nsIFrame* aFrame)
|
||||
return nsIFrame::DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT;
|
||||
}
|
||||
|
||||
static nscoord
|
||||
SpaceToFill(WritingMode aWM, const LogicalSize& aSize, nscoord aMargin,
|
||||
LogicalAxis aAxis, nscoord aCBSize)
|
||||
{
|
||||
nscoord size = aAxis == eLogicalAxisBlock ? aSize.BSize(aWM)
|
||||
: aSize.ISize(aWM);
|
||||
return aCBSize - (size + aMargin);
|
||||
}
|
||||
|
||||
// Align an item's margin box in its aAxis inside aCBSize.
|
||||
static void
|
||||
AlignJustifySelf(uint8_t aAlignment, bool aOverflowSafe, LogicalAxis aAxis,
|
||||
@ -2601,120 +2593,16 @@ AlignJustifySelf(uint8_t aAlignment, bool aOverflowSafe, LogicalAxis aAxis,
|
||||
{
|
||||
MOZ_ASSERT(aAlignment != NS_STYLE_ALIGN_AUTO, "unexpected 'auto' "
|
||||
"computed value for normal flow grid item");
|
||||
MOZ_ASSERT(aAlignment != NS_STYLE_ALIGN_LEFT &&
|
||||
aAlignment != NS_STYLE_ALIGN_RIGHT,
|
||||
"caller should map that to the corresponding START/END");
|
||||
|
||||
// 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;
|
||||
break;
|
||||
case NS_STYLE_ALIGN_SELF_END: // align/justify-self: self-end
|
||||
aAlignment = MOZ_LIKELY(aSameSide) ? NS_STYLE_ALIGN_END
|
||||
: NS_STYLE_ALIGN_START;
|
||||
break;
|
||||
case NS_STYLE_ALIGN_FLEX_START: // same as 'start' for Grid
|
||||
aAlignment = NS_STYLE_ALIGN_START;
|
||||
break;
|
||||
case NS_STYLE_ALIGN_FLEX_END: // same as 'end' for Grid
|
||||
aAlignment = NS_STYLE_ALIGN_END;
|
||||
break;
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
marginStart = margin.BStart(wm);
|
||||
marginEnd = margin.BEnd(wm);
|
||||
} else {
|
||||
marginStart = margin.BEnd(wm);
|
||||
marginEnd = margin.BStart(wm);
|
||||
}
|
||||
} else {
|
||||
if (MOZ_LIKELY(aSameSide)) {
|
||||
marginStart = margin.IStart(wm);
|
||||
marginEnd = margin.IEnd(wm);
|
||||
} else {
|
||||
marginStart = margin.IEnd(wm);
|
||||
marginEnd = margin.IStart(wm);
|
||||
}
|
||||
}
|
||||
|
||||
const auto& styleMargin = aRI.mStyleMargin->mMargin;
|
||||
bool hasAutoMarginStart;
|
||||
bool hasAutoMarginEnd;
|
||||
if (aAxis == eLogicalAxisBlock) {
|
||||
hasAutoMarginStart = styleMargin.GetBStartUnit(wm) == eStyleUnit_Auto;
|
||||
hasAutoMarginEnd = styleMargin.GetBEndUnit(wm) == eStyleUnit_Auto;
|
||||
} 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) ||
|
||||
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);
|
||||
} else if (hasAutoMarginStart) {
|
||||
aAlignment = aSameSide ? NS_STYLE_ALIGN_END : NS_STYLE_ALIGN_START;
|
||||
}
|
||||
}
|
||||
// NOTE: this is the resulting frame offset (border box).
|
||||
nscoord offset =
|
||||
CSSAlignUtils::AlignJustifySelf(aAlignment, aOverflowSafe, aAxis,
|
||||
aSameSide, aBaselineAdjust, aCBSize,
|
||||
aRI, aChildSize);
|
||||
|
||||
// Set the position (aPos) for the requested alignment.
|
||||
nscoord offset = 0; // NOTE: this is the resulting frame offset (border box).
|
||||
switch (aAlignment) {
|
||||
case NS_STYLE_ALIGN_BASELINE:
|
||||
case NS_STYLE_ALIGN_LAST_BASELINE:
|
||||
if (MOZ_LIKELY(aSameSide == (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:
|
||||
MOZ_FALLTHROUGH; // ComputeSize() deals with it
|
||||
case NS_STYLE_ALIGN_START:
|
||||
offset = marginStart;
|
||||
break;
|
||||
case NS_STYLE_ALIGN_END: {
|
||||
nscoord size = aAxis == eLogicalAxisBlock ? aChildSize.BSize(wm)
|
||||
: aChildSize.ISize(wm);
|
||||
offset = aCBSize - (size + marginEnd);
|
||||
break;
|
||||
}
|
||||
case NS_STYLE_ALIGN_CENTER: {
|
||||
nscoord size = aAxis == eLogicalAxisBlock ? aChildSize.BSize(wm)
|
||||
: aChildSize.ISize(wm);
|
||||
offset = (aCBSize - size + marginStart - marginEnd) / 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("unknown align-/justify-self value");
|
||||
}
|
||||
if (offset != 0) {
|
||||
WritingMode wm = aRI.GetWritingMode();
|
||||
nscoord& pos = aAxis == eLogicalAxisBlock ? aPos->B(wm) : aPos->I(wm);
|
||||
pos += MOZ_LIKELY(aSameSide) ? offset : -offset;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user