Skip to content

Commit

Permalink
[IFC] InlineLevelBox::LayoutBounds is a glorified AscentAndDescent
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=255387

Reviewed by Antti Koivisto.

1. Move AscentAndDescent from InlineLineBoxBuilder.cpp under InlineLevelBox
2. Turn both InlineLevelBox::LayoutBounds and InlineLevelBox's m_ascent/m_descent into a AscentAndDescent

* Source/WebCore/layout/formattingContexts/inline/InlineLevelBox.h:
(WebCore::Layout::InlineLevelBox::AscentAndDescent::height const):
(WebCore::Layout::InlineLevelBox::AscentAndDescent::operator== const):
(WebCore::Layout::InlineLevelBox::ascent const):
(WebCore::Layout::InlineLevelBox::descent const):
(WebCore::Layout::InlineLevelBox::LayoutBounds::ascent const):
(WebCore::Layout::InlineLevelBox::LayoutBounds::descent const):
(WebCore::Layout::InlineLevelBox::LayoutBounds::height const):
(WebCore::Layout::InlineLevelBox::LayoutBounds::operator== const):
(WebCore::Layout::InlineLevelBox::setAscentAndDescent):
(WebCore::Layout::InlineLevelBox::setLayoutBounds):
(WebCore::Layout::InlineLevelBox::LayoutBounds::LayoutBounds):
(WebCore::Layout::InlineLevelBox::AscentAndDescent::round):
(WebCore::Layout::InlineLevelBox::setAscent): Deleted.
(WebCore::Layout::InlineLevelBox::setDescent): Deleted.
* Source/WebCore/layout/formattingContexts/inline/InlineLineBoxBuilder.cpp:
(WebCore::Layout::primaryFontMetricsForInlineBox):
(WebCore::Layout::ascentAndDescentWithTextEdgeForInlineBox):
(WebCore::Layout::LineBoxBuilder::enclosingAscentDescentWithFallbackFonts const):
(WebCore::Layout::LineBoxBuilder::setLayoutBoundsForInlineBox const):
(WebCore::Layout::LineBoxBuilder::setVerticalPropertiesForInlineLevelBox const):
(WebCore::Layout::LineBoxBuilder::constructInlineLevelBoxes):
(WebCore::Layout::LineBoxBuilder::adjustInlineBoxHeightsForLineBoxContainIfApplicable):
(WebCore::Layout::LineBoxBuilder::adjustIdeographicBaselineIfApplicable):
(WebCore::Layout::LineBoxBuilder::computeLineBoxGeometry const):
(): Deleted.
(WebCore::Layout::AscentAndDescent::height const): Deleted.
(WebCore::Layout::AscentAndDescent::round const): Deleted.
* Source/WebCore/layout/formattingContexts/inline/InlineLineBoxBuilder.h:
* Source/WebCore/layout/formattingContexts/inline/InlineLineBoxVerticalAligner.cpp:
(WebCore::Layout::LineBoxVerticalAligner::computeLogicalHeightAndAlign const):
(WebCore::Layout::LineBoxVerticalAligner::simplifiedVerticalAlignment const):
(WebCore::Layout::LineBoxVerticalAligner::computeLineBoxLogicalHeight const):
(WebCore::Layout::LineBoxVerticalAligner::computeRootInlineBoxVerticalPosition const):
(WebCore::Layout::LineBoxVerticalAligner::layoutBoundsForInlineBoxSubtree const):
(WebCore::Layout::LineBoxVerticalAligner::alignInlineLevelBoxes const):
(WebCore::Layout::LineBoxVerticalAligner::adjustForAnnotationIfNeeded const):

Canonical link: https://commits.webkit.org/262942@main
  • Loading branch information
alanbaradlay committed Apr 14, 2023
1 parent b877662 commit a055bb1
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 53 deletions.
35 changes: 21 additions & 14 deletions Source/WebCore/layout/formattingContexts/inline/InlineLevelBox.h
Expand Up @@ -47,17 +47,20 @@ class InlineLevelBox {
static InlineLevelBox createLineBreakBox(const Box&, const RenderStyle&, InlineLayoutUnit logicalLeft);
static InlineLevelBox createGenericInlineLevelBox(const Box&, const RenderStyle&, InlineLayoutUnit logicalLeft);

InlineLayoutUnit ascent() const { return m_ascent; }
std::optional<InlineLayoutUnit> descent() const { return m_descent; }
// See https://www.w3.org/TR/css-inline-3/#layout-bounds
struct LayoutBounds {
InlineLayoutUnit height() const { return ascent + descent; }
bool operator==(const LayoutBounds& other) const { return ascent == other.ascent && descent == other.descent; }

struct AscentAndDescent {
InlineLayoutUnit ascent { 0 };
InlineLayoutUnit descent { 0 };

InlineLayoutUnit height() const { return ascent + descent; }
bool operator==(const AscentAndDescent& other) const { return ascent == other.ascent && descent == other.descent; }
// FIXME: Remove this.
// We need floor/ceil to match legacy layout integral positioning.
void round();
};
LayoutBounds layoutBounds() const { return m_layoutBounds; }
InlineLayoutUnit ascent() const { return m_ascentAndDescent.ascent; }
InlineLayoutUnit descent() const { return m_ascentAndDescent.descent; }
// See https://www.w3.org/TR/css-inline-3/#layout-bounds
AscentAndDescent layoutBounds() const { return m_layoutBounds; }

bool hasContent() const { return m_hasContent; }
void setHasContent();
Expand Down Expand Up @@ -135,9 +138,8 @@ class InlineLevelBox {
void setLogicalHeight(InlineLayoutUnit logicalHeight) { m_logicalRect.setHeight(roundToInt(logicalHeight)); }
void setLogicalTop(InlineLayoutUnit logicalTop) { m_logicalRect.setTop(logicalTop >= 0 ? roundToInt(logicalTop) : -roundToInt(-logicalTop)); }
void setLogicalLeft(InlineLayoutUnit logicalLeft) { m_logicalRect.setLeft(logicalLeft); }
void setAscent(InlineLayoutUnit ascent) { m_ascent = roundToInt(ascent); }
void setDescent(InlineLayoutUnit descent) { m_descent = roundToInt(descent); }
void setLayoutBounds(const LayoutBounds& layoutBounds) { m_layoutBounds = { InlineLayoutUnit(roundToInt(layoutBounds.ascent)), InlineLayoutUnit(roundToInt(layoutBounds.descent)) }; }
void setAscentAndDescent(AscentAndDescent ascentAndDescent) { m_ascentAndDescent = { InlineLayoutUnit(roundToInt(ascentAndDescent.ascent)), InlineLayoutUnit(roundToInt(ascentAndDescent.descent)) }; }
void setLayoutBounds(const AscentAndDescent& layoutBounds) { m_layoutBounds = { InlineLayoutUnit(roundToInt(layoutBounds.ascent)), InlineLayoutUnit(roundToInt(layoutBounds.descent)) }; }
void setInlineBoxContentOffsetForLeadingTrim(InlineLayoutUnit offset) { m_inlineBoxContentOffsetForLeadingTrim = offset; }

void setIsFirstBox() { m_isFirstWithinLayoutBox = true; }
Expand All @@ -147,10 +149,9 @@ class InlineLevelBox {
CheckedRef<const Box> m_layoutBox;
// This is the combination of margin and border boxes. Inline level boxes are vertically aligned using their margin boxes.
InlineRect m_logicalRect;
LayoutBounds m_layoutBounds;
AscentAndDescent m_layoutBounds;
AscentAndDescent m_ascentAndDescent;
InlineLayoutUnit m_inlineBoxContentOffsetForLeadingTrim { 0.f };
InlineLayoutUnit m_ascent { 0 };
std::optional<InlineLayoutUnit> m_descent;
bool m_hasContent { false };
// These bits are about whether this inline level box is the first/last generated box of the associated Layout::Box
// (e.g. always true for atomic inline level boxes, but inline boxes spanning over multiple lines can produce separate first/last boxes).
Expand Down Expand Up @@ -287,6 +288,12 @@ inline bool InlineLevelBox::lineBoxContain() const
return true;
}

inline void InlineLevelBox::AscentAndDescent::round()
{
ascent = floorf(ascent);
descent = ceilf(descent);
}

}
}

Expand Up @@ -90,16 +90,7 @@ TextUtil::FallbackFontList LineBoxBuilder::collectFallbackFonts(const InlineLeve
return fallbackFonts;
}

struct AscentAndDescent {
InlineLayoutUnit ascent { 0 };
InlineLayoutUnit descent { 0 };

InlineLayoutUnit height() const { return ascent + descent; }
// FIXME: Remove this.
// We need floor/ceil to match legacy layout integral positioning.
AscentAndDescent round() const { return { floorf(ascent), ceilf(descent) }; }
};
static AscentAndDescent primaryFontMetricsForInlineBox(const InlineLevelBox& inlineBox, FontBaseline fontBaseline = AlphabeticBaseline)
static InlineLevelBox::AscentAndDescent primaryFontMetricsForInlineBox(const InlineLevelBox& inlineBox, FontBaseline fontBaseline = AlphabeticBaseline)
{
ASSERT(inlineBox.isInlineBox());
auto& fontMetrics = inlineBox.primarymetricsOfPrimaryFont();
Expand All @@ -116,7 +107,7 @@ static bool isTextEdgeLeading(const InlineLevelBox& inlineBox)
return textEdge.over == TextEdgeType::Leading;
}

static AscentAndDescent ascentAndDescentWithTextEdgeForInlineBox(const InlineLevelBox& inlineBox, const FontMetrics& fontMetrics, FontBaseline fontBaseline)
static InlineLevelBox::AscentAndDescent ascentAndDescentWithTextEdgeForInlineBox(const InlineLevelBox& inlineBox, const FontMetrics& fontMetrics, FontBaseline fontBaseline)
{
ASSERT(inlineBox.isInlineBox());

Expand Down Expand Up @@ -163,7 +154,7 @@ static AscentAndDescent ascentAndDescentWithTextEdgeForInlineBox(const InlineLev
return { ascent(), descent() };
}

AscentAndDescent LineBoxBuilder::enclosingAscentDescentWithFallbackFonts(const InlineLevelBox& inlineBox, const TextUtil::FallbackFontList& fallbackFontsForContent, FontBaseline fontBaseline) const
InlineLevelBox::AscentAndDescent LineBoxBuilder::enclosingAscentDescentWithFallbackFonts(const InlineLevelBox& inlineBox, const TextUtil::FallbackFontList& fallbackFontsForContent, FontBaseline fontBaseline) const
{
ASSERT(!fallbackFontsForContent.isEmpty());
ASSERT(inlineBox.isInlineBox());
Expand Down Expand Up @@ -235,15 +226,16 @@ void LineBoxBuilder::setLayoutBoundsForInlineBox(InlineLevelBox& inlineBox, Font

void LineBoxBuilder::setVerticalPropertiesForInlineLevelBox(const LineBox& lineBox, InlineLevelBox& inlineLevelBox) const
{
auto setAscentAndDescent = [&] (auto ascentAndDescent, bool applyLegacyRounding = true) {
auto adjustedAscentAndDescent = applyLegacyRounding ? ascentAndDescent.round() : ascentAndDescent;
inlineLevelBox.setAscent(adjustedAscentAndDescent.ascent);
inlineLevelBox.setDescent(adjustedAscentAndDescent.descent);
inlineLevelBox.setLayoutBounds({ adjustedAscentAndDescent.ascent, adjustedAscentAndDescent.descent });
auto setVerticalProperties = [&] (InlineLevelBox::AscentAndDescent ascentAndDescent, bool applyLegacyRounding = true) {
if (applyLegacyRounding)
ascentAndDescent.round();
inlineLevelBox.setAscentAndDescent(ascentAndDescent);
inlineLevelBox.setLayoutBounds(ascentAndDescent);
inlineLevelBox.setLogicalHeight(ascentAndDescent.height());
};

if (inlineLevelBox.isInlineBox()) {
auto ascentAndDescent = [&]() -> AscentAndDescent {
auto ascentAndDescent = [&]() -> InlineLevelBox::AscentAndDescent {
auto leadingTrim = inlineLevelBox.leadingTrim();
auto fontBaseline = lineBox.baselineType();
if (inlineLevelBox.isRootInlineBox() || leadingTrim == LeadingTrim::Normal)
Expand All @@ -256,8 +248,8 @@ void LineBoxBuilder::setVerticalPropertiesForInlineLevelBox(const LineBox& lineB
return { ascent, descent };
}();

setAscentAndDescent(ascentAndDescent);
inlineLevelBox.setLogicalHeight(ascentAndDescent.height());
setVerticalProperties(ascentAndDescent);
// Override default layout bounds.
setLayoutBoundsForInlineBox(inlineLevelBox, lineBox.baselineType());

// With leading-trim, the inline box top is not always where the content starts.
Expand All @@ -267,8 +259,7 @@ void LineBoxBuilder::setVerticalPropertiesForInlineLevelBox(const LineBox& lineB
}
if (inlineLevelBox.isLineBreakBox()) {
auto parentAscentAndDescent = primaryFontMetricsForInlineBox(lineBox.parentInlineBox(inlineLevelBox), lineBox.baselineType());
setAscentAndDescent(parentAscentAndDescent);
inlineLevelBox.setLogicalHeight(parentAscentAndDescent.height());
setVerticalProperties(parentAscentAndDescent);
return;
}
if (inlineLevelBox.isListMarker()) {
Expand All @@ -277,15 +268,15 @@ void LineBoxBuilder::setVerticalPropertiesForInlineLevelBox(const LineBox& lineB
auto& listMarkerBoxGeometry = formattingContext().geometryForBox(layoutBox);
auto marginBoxHeight = listMarkerBoxGeometry.marginBoxHeight();

inlineLevelBox.setLogicalHeight(marginBoxHeight);
if (lineBox.baselineType() == IdeographicBaseline) {
// FIXME: We should rely on the integration baseline.
setAscentAndDescent(primaryFontMetricsForInlineBox(lineBox.parentInlineBox(inlineLevelBox), lineBox.baselineType()));
setVerticalProperties(primaryFontMetricsForInlineBox(lineBox.parentInlineBox(inlineLevelBox), lineBox.baselineType()));
inlineLevelBox.setLogicalHeight(marginBoxHeight);
return;
}
if (auto ascent = downcast<ElementBox>(layoutBox).baselineForIntegration())
return setAscentAndDescent(AscentAndDescent { *ascent, marginBoxHeight - *ascent });
setAscentAndDescent(AscentAndDescent { marginBoxHeight, { } });
return setVerticalProperties({ *ascent, marginBoxHeight - *ascent });
setVerticalProperties({ marginBoxHeight, { } });
return;
}
if (inlineLevelBox.isAtomicInlineLevelBox()) {
Expand All @@ -310,8 +301,7 @@ void LineBoxBuilder::setVerticalPropertiesForInlineLevelBox(const LineBox& lineB
}
return marginBoxHeight;
}();
setAscentAndDescent(AscentAndDescent { ascent, marginBoxHeight - ascent }, false);
inlineLevelBox.setLogicalHeight(marginBoxHeight);
setVerticalProperties({ ascent, marginBoxHeight - ascent }, false);
return;
}
ASSERT_NOT_REACHED();
Expand Down Expand Up @@ -472,7 +462,7 @@ void LineBoxBuilder::adjustInlineBoxHeightsForLineBoxContainIfApplicable(LineBox
continue;
auto& inlineBoxGeometry = formattingContext().geometryForBox(inlineLevelBox.layoutBox());
auto ascent = inlineLevelBox.ascent() + inlineBoxGeometry.marginBorderAndPaddingBefore();
auto descent = valueOrDefault(inlineLevelBox.descent()) + inlineBoxGeometry.marginBorderAndPaddingAfter();
auto descent = inlineLevelBox.descent() + inlineBoxGeometry.marginBorderAndPaddingAfter();
inlineBoxBoundsMap.set(&inlineLevelBox, TextUtil::EnclosingAscentDescent { ascent, descent });
}
}
Expand Down Expand Up @@ -603,8 +593,7 @@ void LineBoxBuilder::adjustIdeographicBaselineIfApplicable(LineBox& lineBox)
auto inlineLevelBoxHeight = inlineLevelBox.logicalHeight();
InlineLayoutUnit ideographicBaseline = roundToInt(inlineLevelBoxHeight / 2);
// Move the baseline position but keep the same logical height.
inlineLevelBox.setAscent(ideographicBaseline);
inlineLevelBox.setDescent(inlineLevelBoxHeight - ideographicBaseline);
inlineLevelBox.setAscentAndDescent({ ideographicBaseline, inlineLevelBoxHeight - ideographicBaseline });
inlineLevelBox.setLayoutBounds({ ideographicBaseline, inlineLevelBoxHeight - ideographicBaseline });
}

Expand Down Expand Up @@ -649,7 +638,7 @@ void LineBoxBuilder::computeLineBoxGeometry(LineBox& lineBox) const
auto& rootInlineBox = lineBox.rootInlineBox();
switch (rootStyle.textEdge().under) {
case TextEdgeType::Text:
return rootInlineBox.layoutBounds().descent - *rootInlineBox.descent();
return rootInlineBox.layoutBounds().descent - rootInlineBox.descent();
case TextEdgeType::Alphabetic:
return rootInlineBox.layoutBounds().descent;
case TextEdgeType::CJKIdeographic:
Expand Down
Expand Up @@ -36,7 +36,6 @@ namespace Layout {
class Box;
class ElementBox;
class LayoutState;
struct AscentAndDescent;

class LineBoxBuilder {
public:
Expand All @@ -49,7 +48,7 @@ class LineBoxBuilder {
void setLayoutBoundsForInlineBox(InlineLevelBox&, FontBaseline) const;
void adjustInlineBoxHeightsForLineBoxContainIfApplicable(LineBox&);
void computeLineBoxGeometry(LineBox&) const;
AscentAndDescent enclosingAscentDescentWithFallbackFonts(const InlineLevelBox&, const TextUtil::FallbackFontList& fallbackFontsForContent, FontBaseline) const;
InlineLevelBox::AscentAndDescent enclosingAscentDescentWithFallbackFonts(const InlineLevelBox&, const TextUtil::FallbackFontList& fallbackFontsForContent, FontBaseline) const;
TextUtil::FallbackFontList collectFallbackFonts(const InlineLevelBox& parentInlineBox, const Line::Run&, const RenderStyle&);

void constructInlineLevelBoxes(LineBox&);
Expand Down
Expand Up @@ -200,7 +200,7 @@ LineBoxVerticalAligner::LineBoxAlignmentContent LineBoxVerticalAligner::computeL
case VerticalAlign::TextBottom: {
// Note that text-bottom aligns with the inline box's font metrics bottom (descent) and not the layout bounds bottom.
auto parentInlineBoxLayoutBounds = parentInlineBox.layoutBounds();
auto parentInlineBoxLogicalBottom = parentInlineBoxLayoutBounds.height() - parentInlineBoxLayoutBounds.descent + *parentInlineBox.descent();
auto parentInlineBoxLogicalBottom = parentInlineBoxLayoutBounds.height() - parentInlineBoxLayoutBounds.descent + parentInlineBox.descent();
logicalTop = parentInlineBoxLogicalBottom - layoutBounds.height();
break;
}
Expand Down Expand Up @@ -310,7 +310,7 @@ void LineBoxVerticalAligner::computeRootInlineBoxVerticalPosition(LineBox& lineB
baselineOffsetFromParentBaseline = parentInlineBox.ascent() - layoutBounds.ascent;
break;
case VerticalAlign::TextBottom:
baselineOffsetFromParentBaseline = layoutBounds.descent - *parentInlineBox.descent();
baselineOffsetFromParentBaseline = layoutBounds.descent - parentInlineBox.descent();
break;
case VerticalAlign::Sub:
baselineOffsetFromParentBaseline = -(parentInlineBox.fontSize() / 5 + 1);
Expand Down Expand Up @@ -364,7 +364,7 @@ void LineBoxVerticalAligner::computeRootInlineBoxVerticalPosition(LineBox& lineB
rootInlineBox.setLogicalTop(rootInlineBoxLogicalTop);
}

InlineLevelBox::LayoutBounds LineBoxVerticalAligner::layoutBoundsForInlineBoxSubtree(const LineBox::InlineLevelBoxList& nonRootInlineLevelBoxes, size_t inlineBoxIndex) const
InlineLevelBox::AscentAndDescent LineBoxVerticalAligner::layoutBoundsForInlineBoxSubtree(const LineBox::InlineLevelBoxList& nonRootInlineLevelBoxes, size_t inlineBoxIndex) const
{
// https://w3c.github.io/csswg-drafts/css2/#propdef-vertical-align
//
Expand All @@ -376,7 +376,7 @@ InlineLevelBox::LayoutBounds LineBoxVerticalAligner::layoutBoundsForInlineBoxSub
// The top of the aligned subtree is the highest of the tops of the boxes in the subtree, and the bottom is analogous.
ASSERT(nonRootInlineLevelBoxes[inlineBoxIndex].isInlineBox());
auto& formattingGeometry = this->formattingGeometry();
auto enclosingLayoutBounds = InlineLevelBox::LayoutBounds { };
auto enclosingLayoutBounds = InlineLevelBox::AscentAndDescent { };
auto& inlineBoxParent = nonRootInlineLevelBoxes[inlineBoxIndex].layoutBox().parent();
for (size_t index = inlineBoxIndex + 1; index < nonRootInlineLevelBoxes.size(); ++index) {
auto& descendantInlineLevelBox = nonRootInlineLevelBoxes[index];
Expand Down
Expand Up @@ -54,7 +54,7 @@ class LineBoxVerticalAligner {
void computeRootInlineBoxVerticalPosition(LineBox&, const LineBoxAlignmentContent&) const;
void alignInlineLevelBoxes(LineBox&, InlineLayoutUnit lineBoxLogicalHeight) const;
InlineLayoutUnit adjustForAnnotationIfNeeded(LineBox&, InlineLayoutUnit lineBoxHeight) const;
InlineLevelBox::LayoutBounds layoutBoundsForInlineBoxSubtree(const LineBox::InlineLevelBoxList& nonRootInlineLevelBoxes, size_t inlineBoxIndex) const;
InlineLevelBox::AscentAndDescent layoutBoundsForInlineBoxSubtree(const LineBox::InlineLevelBoxList& nonRootInlineLevelBoxes, size_t inlineBoxIndex) const;

const InlineFormattingGeometry& formattingGeometry() const { return m_inlineFormattingGeometry; }
const InlineFormattingContext& formattingContext() const { return m_inlineFormattingContext; }
Expand Down

0 comments on commit a055bb1

Please sign in to comment.