Modified: trunk/Source/WebCore/ChangeLog (269224 => 269225)
--- trunk/Source/WebCore/ChangeLog 2020-10-31 12:53:05 UTC (rev 269224)
+++ trunk/Source/WebCore/ChangeLog 2020-10-31 14:29:57 UTC (rev 269225)
@@ -1,5 +1,35 @@
2020-10-31 Zalan Bujtas <[email protected]>
+ [LFC][IFC] Split inline level box alignment process into multiple phases
+ https://bugs.webkit.org/show_bug.cgi?id=218397
+
+ Reviewed by Antti Koivisto.
+
+ Inline level box alignment inside the line box is described at https://www.w3.org/TR/css-inline-3/#line-layout.
+ The alignment process involves 3 distinct steps:
+ 1. Computing the line box's logical height. This step solely uses the layout bounds geometry of the inline level boxes.
+ 2. Finding the root inline box vertical position. This step is somewhat similar to the final, alignment phase but instead of
+ the logical top, here we compute the baseline offsets. It helps to figure out the root inline box's baseline positing inside the line box.
+ 3. Aligning the inline level boxes by computing their logical top position.
+
+ These 3 steps are implemented by the following 3 functions:
+ 1. computeLineBoxLogicalHeight()
+ 2. computeRootInlineBoxVerticalPosition()
+ 3. alignInlineLevelBoxes()
+ While some of the code in these functions may look redundant, they work with different type of geometries (layout bounds vs. normal ascent/descent/logical height).
+
+ * layout/inlineformatting/InlineFormattingContextGeometry.cpp:
+ (WebCore::Layout::LineBoxBuilder::setVerticalGeometryForInlineBox const):
+ (WebCore::Layout::LineBoxBuilder::alignInlineLevelBoxesVerticallyAndComputeLineBoxHeight):
+ * layout/inlineformatting/InlineLineBox.cpp:
+ (WebCore::Layout::LineBox::logicalRectForTextRun const):
+ (WebCore::Layout::LineBox::logicalRectForInlineLevelBox const):
+ * layout/inlineformatting/InlineLineBox.h:
+ (WebCore::Layout::LineBox::InlineLevelBox::style const):
+ (WebCore::Layout::LineBox::InlineLevelBox::fontMetrics const): Deleted.
+
+2020-10-31 Zalan Bujtas <[email protected]>
+
[LFC][Integration] Generate RootInlineBox::lineTop/lineBottom matching geometries
https://bugs.webkit.org/show_bug.cgi?id=218412
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextGeometry.cpp (269224 => 269225)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextGeometry.cpp 2020-10-31 12:53:05 UTC (rev 269224)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextGeometry.cpp 2020-10-31 14:29:57 UTC (rev 269225)
@@ -47,7 +47,7 @@
private:
void setVerticalGeometryForInlineBox(LineBox::InlineLevelBox&) const;
void constructInlineLevelBoxes(LineBox&, const Line::RunList&);
- void alignInlineLevelBoxesVerticallyAndComputeLineBoxHeight(LineBox&);
+ void computeLineBoxHeightAndalignInlineLevelBoxesVertically(LineBox&);
const InlineFormattingContext& formattingContext() const { return m_inlineFormattingContext; }
const Box& rootBox() const { return formattingContext().root(); }
@@ -162,7 +162,7 @@
if (auto horizontalAlignmentOffset = Layout::horizontalAlignmentOffset(runs, rootBox().style().textAlign(), lineLogicalWidth, contentLogicalWidth, lineContent.isLastLineWithInlineContent))
lineBox.setHorizontalAlignmentOffset(*horizontalAlignmentOffset);
constructInlineLevelBoxes(lineBox, runs);
- alignInlineLevelBoxesVerticallyAndComputeLineBoxHeight(lineBox);
+ computeLineBoxHeightAndalignInlineLevelBoxesVertically(lineBox);
return lineBox;
}
@@ -169,10 +169,14 @@
void LineBoxBuilder::setVerticalGeometryForInlineBox(LineBox::InlineLevelBox& inlineLevelBox) const
{
ASSERT(inlineLevelBox.isInlineBox() || inlineLevelBox.isLineBreakBox());
- auto& fontMetrics = inlineLevelBox.fontMetrics();
+ auto& fontMetrics = inlineLevelBox.style().fontMetrics();
InlineLayoutUnit ascent = fontMetrics.ascent();
InlineLayoutUnit descent = fontMetrics.descent();
auto logicalHeight = ascent + descent;
+ // We need floor/ceil to match legacy layout integral positioning.
+ inlineLevelBox.setBaseline(floorf(ascent));
+ inlineLevelBox.setDescent(ceil(descent));
+ inlineLevelBox.setLogicalHeight(logicalHeight);
// FIXME: Adjust layout bounds with fallback font when applicable.
auto& style = inlineLevelBox.layoutBox().style();
@@ -192,14 +196,8 @@
ascent += halfLeading;
descent += halfLeading;
}
- // We need this to match legacy layout integral positioning.
- ascent = floorf(ascent);
- descent = ceil(descent);
-
- inlineLevelBox.setLayoutBounds(LineBox::InlineLevelBox::LayoutBounds { ascent, descent });
- inlineLevelBox.setBaseline(ascent);
- inlineLevelBox.setDescent(descent);
- inlineLevelBox.setLogicalHeight(logicalHeight);
+ // We need floor/ceil to match legacy layout integral positioning.
+ inlineLevelBox.setLayoutBounds(LineBox::InlineLevelBox::LayoutBounds { floorf(ascent), ceil(descent) });
}
void LineBoxBuilder::constructInlineLevelBoxes(LineBox& lineBox, const Line::RunList& runs)
@@ -296,27 +294,35 @@
}
}
-void LineBoxBuilder::alignInlineLevelBoxesVerticallyAndComputeLineBoxHeight(LineBox& lineBox)
+void LineBoxBuilder::computeLineBoxHeightAndalignInlineLevelBoxesVertically(LineBox& lineBox)
{
// This function (partially) implements:
// 2.2. Layout Within Line Boxes
// https://www.w3.org/TR/css-inline-3/#line-layout
+ // 1. Compute the line box height using the layout bounds geometry. This height computation strictly uses layout bounds and not normal inline level box geometries.
+ // 2. Compute the baseline/logical top position of the root inline box. Aligned boxes push the root inline box around inside the line box.
+ // 3. Finally align the inline level boxes using (mostly) normal inline level box geometries.
auto quirks = formattingContext().quirks();
- Vector<LineBox::InlineLevelBox*> lineBoxRelativeInlineLevelBoxes;
- struct AbsoluteGeometry {
- InlineLayoutUnit top { 0 };
- InlineLayoutUnit bottom { 0 };
- InlineLayoutUnit baselineOffsetFromRootInlineBoxBaseline { 0 };
- const LineBox::InlineLevelBox* inlineLevelBox { nullptr };
- };
- HashMap<LineBox::InlineLevelBox*, AbsoluteGeometry> inlineLevelBoxAbsoluteGeometryMap;
auto& rootInlineBox = lineBox.rootInlineBox();
- inlineLevelBoxAbsoluteGeometryMap.add(&rootInlineBox, AbsoluteGeometry { { }, rootInlineBox.layoutBounds().height(), { }, &rootInlineBox });
- auto maximumTopOffsetFromRootInlineBoxBaseline = rootInlineBox.isEmpty() ? InlineLayoutUnit() : rootInlineBox.layoutBounds().ascent;
- auto alignInlineBoxRelativeInlineLevelBoxes = [&] {
- // FIXME: Add proper support for cases when the inline box with line box relative alignment has a child inline box
- // with non-line box relative alignment.
+ auto computeLineBoxLogicalHeight = [&] {
+ // Line box height computation is based on the layout bounds of the inline boxes and not their logical (ascent/descent) dimensions.
+ struct AbsoluteTopAndBottom {
+ InlineLayoutUnit top { 0 };
+ InlineLayoutUnit bottom { 0 };
+ };
+ HashMap<LineBox::InlineLevelBox*, AbsoluteTopAndBottom> inlineLevelBoxAbsoluteTopAndBottomMap;
+
+ auto minimumLogicalTop = Optional<InlineLayoutUnit> { };
+ auto maximumLogicalBottom = Optional<InlineLayoutUnit> { };
+ if (!rootInlineBox.isEmpty()) {
+ minimumLogicalTop = InlineLayoutUnit { };
+ maximumLogicalBottom = rootInlineBox.layoutBounds().height();
+ inlineLevelBoxAbsoluteTopAndBottomMap.add(&rootInlineBox, AbsoluteTopAndBottom { *minimumLogicalTop, *maximumLogicalBottom });
+ } else
+ inlineLevelBoxAbsoluteTopAndBottomMap.add(&rootInlineBox, AbsoluteTopAndBottom { });
+
+ Vector<LineBox::InlineLevelBox*> lineBoxRelativeInlineLevelBoxes;
for (auto& inlineLevelBox : lineBox.nonRootInlineLevelBoxes()) {
auto& layoutBox = inlineLevelBox->layoutBox();
if (inlineLevelBox->hasLineBoxRelativeAlignment()) {
@@ -324,112 +330,181 @@
continue;
}
auto& parentInlineBox = lineBox.inlineLevelBoxForLayoutBox(layoutBox.parent());
+ // Logical top is relative to the parent inline box's layout bounds.
+ // Note that this logical top is not the final logical top of the inline level box.
+ // This is the logical top in the context of the layout bounds geometry which may be very different from the inline box's normal geometry.
auto logicalTop = InlineLayoutUnit { };
- auto baselineOffsetFromParentBaseline = InlineLayoutUnit { };
switch (inlineLevelBox->verticalAlign()) {
- case VerticalAlign::Baseline:
- logicalTop = parentInlineBox.baseline() - inlineLevelBox->layoutBounds().ascent;
- baselineOffsetFromParentBaseline = { };
+ case VerticalAlign::Baseline: {
+ auto logicalTopOffsetFromParentBaseline = inlineLevelBox->layoutBounds().ascent;
+ logicalTop = parentInlineBox.layoutBounds().ascent - logicalTopOffsetFromParentBaseline;
break;
- case VerticalAlign::TextTop: {
- // Note that TextTop aligns with the inline box's font metrics top (ascent) and not the layout bounds top.
- auto parentAscent = parentInlineBox.fontMetrics().ascent();
- auto parentInlineBoxLogicalTop = parentInlineBox.layoutBounds().ascent - parentAscent;
- logicalTop = parentInlineBoxLogicalTop;
- baselineOffsetFromParentBaseline = parentAscent - inlineLevelBox->layoutBounds().ascent;
- break;
}
- case VerticalAlign::TextBottom: {
- // Note that TextBottom aligns with the inline box's font metrics bottom (descent) and not the layout bounds bottom.
- auto& parentFontMetrics = parentInlineBox.fontMetrics();
- auto parentInlineBoxLayoutBounds = parentInlineBox.layoutBounds();
- auto parentInlineBoxLogicalBottom = parentInlineBoxLayoutBounds.height() - parentInlineBoxLayoutBounds.descent + parentFontMetrics.descent();
- auto layoutBounds = inlineLevelBox->layoutBounds();
- logicalTop = parentInlineBoxLogicalBottom - layoutBounds.height();
- baselineOffsetFromParentBaseline = layoutBounds.descent - parentFontMetrics.descent();
- break;
- }
case VerticalAlign::Middle: {
- auto logicalTopOffsetFromParentBaseline = inlineLevelBox->layoutBounds().height() / 2 + parentInlineBox.fontMetrics().xHeight() / 2;
- logicalTop = parentInlineBox.baseline() - logicalTopOffsetFromParentBaseline;
- baselineOffsetFromParentBaseline = logicalTopOffsetFromParentBaseline - inlineLevelBox->layoutBounds().ascent;
+ auto logicalTopOffsetFromParentBaseline = inlineLevelBox->layoutBounds().height() / 2 + parentInlineBox.style().fontMetrics().xHeight() / 2;
+ logicalTop = parentInlineBox.layoutBounds().ascent - logicalTopOffsetFromParentBaseline;
break;
}
case VerticalAlign::BaselineMiddle: {
auto logicalTopOffsetFromParentBaseline = inlineLevelBox->layoutBounds().height() / 2;
- logicalTop = parentInlineBox.baseline() - logicalTopOffsetFromParentBaseline;
- baselineOffsetFromParentBaseline = logicalTopOffsetFromParentBaseline - inlineLevelBox->layoutBounds().ascent;
+ logicalTop = parentInlineBox.layoutBounds().ascent - logicalTopOffsetFromParentBaseline;
break;
}
case VerticalAlign::Length: {
- auto& style = layoutBox.style();
+ auto& style = inlineLevelBox->style();
auto logicalTopOffsetFromParentBaseline = floatValueForLength(style.verticalAlignLength(), style.computedLineHeight()) + inlineLevelBox->layoutBounds().height();
- logicalTop = parentInlineBox.baseline() - logicalTopOffsetFromParentBaseline;
- baselineOffsetFromParentBaseline = logicalTopOffsetFromParentBaseline - inlineLevelBox->layoutBounds().ascent;
+ logicalTop = parentInlineBox.layoutBounds().ascent - logicalTopOffsetFromParentBaseline;
break;
}
+ case VerticalAlign::TextTop: {
+ // Note that text-top aligns with the inline box's font metrics top (ascent) and not the layout bounds top.
+ logicalTop = parentInlineBox.layoutBounds().ascent - parentInlineBox.baseline();
+ break;
+ }
+ 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().valueOr(InlineLayoutUnit());
+ logicalTop = parentInlineBoxLogicalBottom - inlineLevelBox->layoutBounds().height();
+ break;
+ }
default:
ASSERT_NOT_IMPLEMENTED_YET();
break;
}
- inlineLevelBox->setLogicalTop(logicalTop);
- auto parentInlineBoxAbsoluteGeometry = inlineLevelBoxAbsoluteGeometryMap.get(&parentInlineBox);
- auto absoluteLogicalTop = parentInlineBoxAbsoluteGeometry.top + logicalTop;
+ auto parentInlineBoxAbsoluteTopAndBottom = inlineLevelBoxAbsoluteTopAndBottomMap.get(&parentInlineBox);
+ auto absoluteLogicalTop = parentInlineBoxAbsoluteTopAndBottom.top + logicalTop;
auto absoluteLogicalBottom = absoluteLogicalTop + inlineLevelBox->layoutBounds().height();
- auto absoluteBaselineOffsetFromRootInlineBoxBaseline = parentInlineBoxAbsoluteGeometry.baselineOffsetFromRootInlineBoxBaseline + baselineOffsetFromParentBaseline;
- inlineLevelBoxAbsoluteGeometryMap.add(inlineLevelBox.get(), AbsoluteGeometry { absoluteLogicalTop, absoluteLogicalBottom, absoluteBaselineOffsetFromRootInlineBoxBaseline, inlineLevelBox.get() });
-
- auto affectsRootInlineBoxVerticalPosition = quirks.shouldInlineLevelBoxStretchLineBox(lineBox, *inlineLevelBox);
- if (affectsRootInlineBoxVerticalPosition)
- maximumTopOffsetFromRootInlineBoxBaseline = std::max(maximumTopOffsetFromRootInlineBoxBaseline, absoluteBaselineOffsetFromRootInlineBoxBaseline + inlineLevelBox->layoutBounds().ascent);
+ inlineLevelBoxAbsoluteTopAndBottomMap.add(inlineLevelBox.get(), AbsoluteTopAndBottom { absoluteLogicalTop, absoluteLogicalBottom });
+ // Stretch the min/max absolute values if applicable.
+ if (quirks.shouldInlineLevelBoxStretchLineBox(lineBox, *inlineLevelBox)) {
+ minimumLogicalTop = std::min(minimumLogicalTop.valueOr(absoluteLogicalTop), absoluteLogicalTop);
+ maximumLogicalBottom = std::max(maximumLogicalBottom.valueOr(absoluteLogicalBottom), absoluteLogicalBottom);
+ }
}
- };
- alignInlineBoxRelativeInlineLevelBoxes();
-
- auto lineBoxLogicalHeight = InlineLayoutUnit { };
- auto inlineBoxRelativeLogicalHeight = InlineLayoutUnit { };
- auto computeLineBoxLogicalHeight = [&] {
- // FIXME: Add support for layout bounds based line box height.
- auto minimumLogicalTop = Optional<InlineLayoutUnit> { };
- auto maximumLogicalBottom = Optional<InlineLayoutUnit> { };
- for (auto absoluteGeometry : inlineLevelBoxAbsoluteGeometryMap.values()) {
- auto& inlineLevelBox = *absoluteGeometry.inlineLevelBox;
- if (!quirks.shouldInlineLevelBoxStretchLineBox(lineBox, inlineLevelBox))
- continue;
- minimumLogicalTop = std::min(minimumLogicalTop.valueOr(absoluteGeometry.top), absoluteGeometry.top);
- maximumLogicalBottom = std::max(maximumLogicalBottom.valueOr(absoluteGeometry.bottom), absoluteGeometry.bottom);
- }
- inlineBoxRelativeLogicalHeight = maximumLogicalBottom.valueOr(InlineLayoutUnit()) - minimumLogicalTop.valueOr(InlineLayoutUnit());
- lineBoxLogicalHeight = inlineBoxRelativeLogicalHeight;
- // Now stretch the line box with the line box relative inline level boxes.
+ // The line box height computation is as follows:
+ // 1. Stretch the line box with the non-line-box relative aligned inline box absolute top and bottom values.
+ // 2. Check if the line box relative aligned inline boxes (top, bottom etc) have enough room and stretch the line box further if needed.
+ auto lineBoxLogicalHeight = maximumLogicalBottom.valueOr(InlineLayoutUnit()) - minimumLogicalTop.valueOr(InlineLayoutUnit());
for (auto* lineBoxRelativeInlineLevelBox : lineBoxRelativeInlineLevelBoxes) {
if (!quirks.shouldInlineLevelBoxStretchLineBox(lineBox, *lineBoxRelativeInlineLevelBox))
continue;
lineBoxLogicalHeight = std::max(lineBoxLogicalHeight, lineBoxRelativeInlineLevelBox->layoutBounds().height());
}
+ lineBox.setLogicalHeight(lineBoxLogicalHeight);
};
computeLineBoxLogicalHeight();
- auto adjustRootInlineBoxVerticalPosition = [&] {
- // FIXME: Add support for cases when the stretching inline boxes are not baseline aligned.
- auto rootInlineBoxLogicalTop = maximumTopOffsetFromRootInlineBoxBaseline - rootInlineBox.layoutBounds().ascent;
+ auto computeRootInlineBoxVerticalPosition = [&] {
+ HashMap<LineBox::InlineLevelBox*, InlineLayoutUnit> inlineLevelBoxAbsoluteBaselineOffsetMap;
+ inlineLevelBoxAbsoluteBaselineOffsetMap.add(&rootInlineBox, InlineLayoutUnit { });
+
+ auto maximumTopOffsetFromRootInlineBoxBaseline = rootInlineBox.isEmpty() ? InlineLayoutUnit() : rootInlineBox.layoutBounds().ascent;
+
+ for (auto& inlineLevelBox : lineBox.nonRootInlineLevelBoxes()) {
+ auto absoluteBaselineOffset = InlineLayoutUnit { };
+ if (!inlineLevelBox->hasLineBoxRelativeAlignment()) {
+ auto& layoutBox = inlineLevelBox->layoutBox();
+ auto& parentInlineBox = lineBox.inlineLevelBoxForLayoutBox(layoutBox.parent());
+ auto baselineOffsetFromParentBaseline = InlineLayoutUnit { };
+
+ switch (inlineLevelBox->verticalAlign()) {
+ case VerticalAlign::Baseline:
+ baselineOffsetFromParentBaseline = { };
+ break;
+ case VerticalAlign::Middle: {
+ auto logicalTopOffsetFromParentBaseline = (inlineLevelBox->layoutBounds().height() / 2 + parentInlineBox.style().fontMetrics().xHeight() / 2);
+ baselineOffsetFromParentBaseline = logicalTopOffsetFromParentBaseline - inlineLevelBox->baseline();
+ break;
+ }
+ case VerticalAlign::BaselineMiddle: {
+ auto logicalTopOffsetFromParentBaseline = inlineLevelBox->layoutBounds().height() / 2;
+ baselineOffsetFromParentBaseline = logicalTopOffsetFromParentBaseline - inlineLevelBox->baseline();
+ break;
+ }
+ case VerticalAlign::Length: {
+ auto& style = inlineLevelBox->style();
+ auto verticalAlignOffset = floatValueForLength(style.verticalAlignLength(), style.computedLineHeight());
+ auto logicalTopOffsetFromParentBaseline = verticalAlignOffset + inlineLevelBox->layoutBounds().height();
+ baselineOffsetFromParentBaseline = logicalTopOffsetFromParentBaseline - inlineLevelBox->baseline();
+ break;
+ }
+ case VerticalAlign::TextTop:
+ baselineOffsetFromParentBaseline = parentInlineBox.baseline() - inlineLevelBox->layoutBounds().ascent;
+ break;
+ case VerticalAlign::TextBottom:
+ baselineOffsetFromParentBaseline = inlineLevelBox->layoutBounds().descent - *parentInlineBox.descent();
+ break;
+ default:
+ ASSERT_NOT_IMPLEMENTED_YET();
+ break;
+ }
+ absoluteBaselineOffset = inlineLevelBoxAbsoluteBaselineOffsetMap.get(&parentInlineBox) + baselineOffsetFromParentBaseline;
+ } else {
+ switch (inlineLevelBox->verticalAlign()) {
+ case VerticalAlign::Top: {
+ absoluteBaselineOffset = rootInlineBox.layoutBounds().ascent - inlineLevelBox->layoutBounds().ascent;
+ break;
+ }
+ case VerticalAlign::Bottom: {
+ absoluteBaselineOffset = inlineLevelBox->layoutBounds().descent - rootInlineBox.layoutBounds().descent;
+ break;
+ }
+ default:
+ ASSERT_NOT_IMPLEMENTED_YET();
+ break;
+ }
+ }
+ inlineLevelBoxAbsoluteBaselineOffsetMap.add(inlineLevelBox.get(), absoluteBaselineOffset);
+ auto affectsRootInlineBoxVerticalPosition = quirks.shouldInlineLevelBoxStretchLineBox(lineBox, *inlineLevelBox);
+ if (affectsRootInlineBoxVerticalPosition)
+ maximumTopOffsetFromRootInlineBoxBaseline = std::max(maximumTopOffsetFromRootInlineBoxBaseline, absoluteBaselineOffset + inlineLevelBox->layoutBounds().ascent);
+ }
+ auto rootInlineBoxLogicalTop = maximumTopOffsetFromRootInlineBoxBaseline - rootInlineBox.baseline();
rootInlineBox.setLogicalTop(rootInlineBoxLogicalTop);
};
- adjustRootInlineBoxVerticalPosition();
+ computeRootInlineBoxVerticalPosition();
- auto alignLineBoxRelativeInlineLevelBoxes = [&] {
- for (auto* inlineLevelBox : lineBoxRelativeInlineLevelBoxes) {
+ auto alignInlineLevelBoxes = [&] {
+ for (auto& inlineLevelBox : lineBox.nonRootInlineLevelBoxes()) {
auto& layoutBox = inlineLevelBox->layoutBox();
- auto verticalAlignment = layoutBox.style().verticalAlign();
+ auto& parentInlineBox = lineBox.inlineLevelBoxForLayoutBox(layoutBox.parent());
auto logicalTop = InlineLayoutUnit { };
- auto rootInlineBoxOffset = InlineLayoutUnit { };
- switch (verticalAlignment) {
+ switch (inlineLevelBox->verticalAlign()) {
+ case VerticalAlign::Baseline:
+ logicalTop = parentInlineBox.baseline() - inlineLevelBox->baseline();
+ break;
+ case VerticalAlign::Middle: {
+ auto logicalTopOffsetFromParentBaseline = (inlineLevelBox->logicalHeight() / 2 + parentInlineBox.style().fontMetrics().xHeight() / 2);
+ logicalTop = parentInlineBox.baseline() - logicalTopOffsetFromParentBaseline;
+ break;
+ }
+ case VerticalAlign::BaselineMiddle: {
+ auto logicalTopOffsetFromParentBaseline = inlineLevelBox->logicalHeight() / 2;
+ logicalTop = parentInlineBox.baseline() - logicalTopOffsetFromParentBaseline;
+ break;
+ }
+ case VerticalAlign::Length: {
+ auto& style = inlineLevelBox->style();
+ auto verticalAlignOffset = floatValueForLength(style.verticalAlignLength(), style.computedLineHeight());
+ auto logicalTopOffsetFromParentBaseline = verticalAlignOffset + inlineLevelBox->logicalHeight();
+ logicalTop = parentInlineBox.baseline() - logicalTopOffsetFromParentBaseline;
+ break;
+ }
+ // Note that (text)top/bottom align their layout bounds.
+ case VerticalAlign::TextTop:
+ logicalTop = inlineLevelBox->layoutBounds().ascent - inlineLevelBox->baseline();
+ break;
+ case VerticalAlign::TextBottom:
+ logicalTop = parentInlineBox.logicalHeight() - inlineLevelBox->layoutBounds().descent - inlineLevelBox->baseline();
+ break;
case VerticalAlign::Top:
- logicalTop = { };
+ // Note that this logical top is not relative to the parent inline box.
+ logicalTop = inlineLevelBox->layoutBounds().ascent - inlineLevelBox->baseline();
break;
case VerticalAlign::Bottom:
- logicalTop = lineBoxLogicalHeight - inlineLevelBox->layoutBounds().height();
- rootInlineBoxOffset = inlineLevelBox->layoutBounds().height() - inlineBoxRelativeLogicalHeight;
+ // Note that this logical top is not relative to the parent inline box.
+ logicalTop = lineBox.logicalHeight() - inlineLevelBox->layoutBounds().descent - inlineLevelBox->baseline();
break;
default:
ASSERT_NOT_IMPLEMENTED_YET();
@@ -436,12 +511,9 @@
break;
}
inlineLevelBox->setLogicalTop(logicalTop);
- if (rootInlineBoxOffset > 0)
- rootInlineBox.setLogicalTop(rootInlineBox.logicalTop() + rootInlineBoxOffset);
}
};
- alignLineBoxRelativeInlineLevelBoxes();
- lineBox.setLogicalHeight(lineBoxLogicalHeight);
+ alignInlineLevelBoxes();
}
LineBox InlineFormattingContext::Geometry::lineBoxForLineContent(const LineBuilder::LineContent& lineContent)
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBox.cpp (269224 => 269225)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBox.cpp 2020-10-31 12:53:05 UTC (rev 269224)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBox.cpp 2020-10-31 14:29:57 UTC (rev 269225)
@@ -86,7 +86,7 @@
ASSERT(run.isText() || run.isLineBreak());
auto* parentInlineBox = &inlineLevelBoxForLayoutBox(run.layoutBox().parent());
ASSERT(parentInlineBox->isInlineBox());
- auto& fontMetrics = parentInlineBox->fontMetrics();
+ auto& fontMetrics = parentInlineBox->style().fontMetrics();
auto runlogicalTop = parentInlineBox->logicalTop() + parentInlineBox->baseline() - fontMetrics.ascent();
while (parentInlineBox != m_rootInlineBox.get() && !parentInlineBox->hasLineBoxRelativeAlignment()) {
@@ -103,11 +103,12 @@
auto* inlineBox = &inlineLevelBoxForLayoutBox(layoutBox);
auto inlineBoxLogicalRect = inlineBox->logicalRect();
auto inlineBoxAbsolutelogicalTop = inlineBox->logicalTop();
-
- while (inlineBox != m_rootInlineBox.get() && !inlineBox->hasLineBoxRelativeAlignment()) {
- inlineBox = &inlineLevelBoxForLayoutBox(inlineBox->layoutBox().parent());
- ASSERT(inlineBox->isInlineBox());
- inlineBoxAbsolutelogicalTop += inlineBox->logicalTop();
+ if (!inlineBox->hasLineBoxRelativeAlignment()) {
+ while (inlineBox != m_rootInlineBox.get() && !inlineBox->hasLineBoxRelativeAlignment()) {
+ inlineBox = &inlineLevelBoxForLayoutBox(inlineBox->layoutBox().parent());
+ ASSERT(inlineBox->isInlineBox());
+ inlineBoxAbsolutelogicalTop += inlineBox->logicalTop();
+ }
}
return { inlineBoxAbsolutelogicalTop, inlineBoxLogicalRect.left(), inlineBoxLogicalRect.width(), inlineBoxLogicalRect.height() };
}