Diff
Modified: trunk/Source/WebCore/ChangeLog (266275 => 266276)
--- trunk/Source/WebCore/ChangeLog 2020-08-28 08:46:45 UTC (rev 266275)
+++ trunk/Source/WebCore/ChangeLog 2020-08-28 13:37:03 UTC (rev 266276)
@@ -1,3 +1,59 @@
+2020-08-28 Zalan Bujtas <[email protected]>
+
+ [LFC][IFC] Move inline alignment code to LineBox
+ https://bugs.webkit.org/show_bug.cgi?id=215117
+
+ Reviewed by Antti Koivisto.
+
+ LineBox is responsible for aligning the runs both vertically and horizontally (LineContentAligner -> LineBox).
+ (Note that LineBox::m_runRectList is transitional and will eventually be converted to inline boxes.)
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * layout/inlineformatting/InlineFormattingContext.cpp:
+ (WebCore::Layout::InlineFormattingContext::lineLayout):
+ (WebCore::Layout::InlineFormattingContext::setDisplayBoxesForLine):
+ (WebCore::Layout::HangingContent::width const): Deleted.
+ (WebCore::Layout::HangingContent::isConditional const): Deleted.
+ (WebCore::Layout::HangingContent::setIsConditional): Deleted.
+ (WebCore::Layout::HangingContent::expand): Deleted.
+ (): Deleted.
+ (WebCore::Layout::HangingContent::reset): Deleted.
+ (WebCore::Layout::LineContentAligner::inlineRectList const): Deleted.
+ (WebCore::Layout::LineContentAligner::formattingContext const): Deleted.
+ (WebCore::Layout::LineContentAligner::layoutState const): Deleted.
+ (WebCore::Layout::LineContentAligner::LineContentAligner): Deleted.
+ (WebCore::Layout::LineContentAligner::alignHorizontally): Deleted.
+ (WebCore::Layout::LineContentAligner::alignVertically): Deleted.
+ (WebCore::Layout::LineContentAligner::adjustBaselineAndLineHeight): Deleted.
+ (WebCore::Layout::LineContentAligner::collectHangingContent const): Deleted.
+ * layout/inlineformatting/InlineFormattingContext.h:
+ * layout/inlineformatting/InlineLineBox.h:
+ (WebCore::Layout::LineBox::inlineRectList const):
+ (WebCore::Layout::LineBox::logicalBottom const):
+ (WebCore::Layout::LineBox::logicalRect const):
+ (WebCore::Layout::LineBox::scrollableOverflow const):
+ (WebCore::Layout::LineBox::formattingContext const):
+ (WebCore::Layout::LineBox::layoutState const):
+ (WebCore::Layout::LineBox::setLogicalHeight): Deleted.
+ (WebCore::Layout::LineBox::setLogicalWidth): Deleted.
+ (WebCore::Layout::LineBox::moveHorizontally): Deleted.
+ (WebCore::Layout::LineBox::expandHorizontally): Deleted.
+ (WebCore::Layout::LineBox::shrinkHorizontally): Deleted.
+ (WebCore::Layout::LineBox::expandVertically): Deleted.
+ (WebCore::Layout::LineBox::shrinkVertically): Deleted.
+ (WebCore::Layout::LineBox::isConsideredEmpty const): Deleted.
+ (WebCore::Layout::LineBox::setIsConsideredEmpty): Deleted.
+ (WebCore::Layout::LineBox::setIsConsideredNonEmpty): Deleted.
+ (WebCore::Layout::LineBox::LineBox): Deleted.
+ (WebCore::Layout::LineBox::resetAlignmentBaseline): Deleted.
+ * layout/inlineformatting/InlineLineBuilder.h:
+ (WebCore::Layout::LineBuilder::lineLogicalWidth const):
+ (WebCore::Layout::LineBuilder::availableWidth const):
+ * layout/inlineformatting/LineLayoutContext.cpp:
+ (WebCore::Layout::LineLayoutContext::close):
+ * layout/inlineformatting/LineLayoutContext.h:
+
2020-08-28 Chris Lord <[email protected]>
Add WebGL(2) context support to OffscreenCanvas
@@ -44,7 +100,7 @@
* workers/service/context/ServiceWorkerThread.cpp:
(WebCore::ServiceWorkerThread::ServiceWorkerThread):
-2020-08-27 Zalan Bujtas <[email protected]>
+2020-08-28 Zalan Bujtas <[email protected]>
[LFC][IFC] LineBuilder:Run should not have vertical geometry
https://bugs.webkit.org/show_bug.cgi?id=215068
Modified: trunk/Source/WebCore/Sources.txt (266275 => 266276)
--- trunk/Source/WebCore/Sources.txt 2020-08-28 08:46:45 UTC (rev 266275)
+++ trunk/Source/WebCore/Sources.txt 2020-08-28 13:37:03 UTC (rev 266276)
@@ -1436,6 +1436,7 @@
layout/inlineformatting/InlineFormattingContextQuirks.cpp
layout/inlineformatting/InlineFormattingState.cpp
layout/inlineformatting/InlineItem.cpp
+layout/inlineformatting/InlineLineBox.cpp
layout/inlineformatting/InlineLineBreaker.cpp
layout/inlineformatting/InlineLineBuilder.cpp
layout/inlineformatting/InlineTextItem.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (266275 => 266276)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2020-08-28 08:46:45 UTC (rev 266275)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2020-08-28 13:37:03 UTC (rev 266276)
@@ -9560,6 +9560,7 @@
6F5B7EAA2300A79E0067D9C3 /* TableGrid.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TableGrid.cpp; sourceTree = "<group>"; };
6F6383F42427AF4900DABA53 /* LayoutInitialContainingBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LayoutInitialContainingBlock.h; sourceTree = "<group>"; };
6F6638D4249E268B001925FC /* TableWrapperBlockFormattingContextQuirks.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TableWrapperBlockFormattingContextQuirks.cpp; sourceTree = "<group>"; };
+ 6F69A79924D6FAB800E6B85D /* InlineLineBox.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InlineLineBox.cpp; sourceTree = "<group>"; };
6F73918C2106CEDD006AF262 /* LayoutUnits.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LayoutUnits.h; sourceTree = "<group>"; };
6F77868523491AC6004D9636 /* DisplayPainter.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DisplayPainter.cpp; sourceTree = "<group>"; };
6F77868723491AD7004D9636 /* DisplayPainter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisplayPainter.h; sourceTree = "<group>"; };
@@ -17420,6 +17421,7 @@
115CFA7C208B8E10001E6991 /* InlineFormattingState.h */,
6F7B8CEC23626E6600C9FF15 /* InlineItem.cpp */,
6FE7CFA02177EEF1005B1573 /* InlineItem.h */,
+ 6F69A79924D6FAB800E6B85D /* InlineLineBox.cpp */,
6FB2400323DFF12700796458 /* InlineLineBox.h */,
6FE198132178397B00446F08 /* InlineLineBreaker.cpp */,
6FE198152178397C00446F08 /* InlineLineBreaker.h */,
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp (266275 => 266276)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2020-08-28 08:46:45 UTC (rev 266275)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2020-08-28 13:37:03 UTC (rev 266276)
@@ -31,6 +31,7 @@
#include "FloatingContext.h"
#include "FontCascade.h"
#include "InlineFormattingState.h"
+#include "InlineLineBox.h"
#include "InlineTextItem.h"
#include "InvalidationState.h"
#include "LayoutBox.h"
@@ -76,301 +77,6 @@
return nullptr;
}
-struct HangingContent {
-public:
- void reset();
-
- InlineLayoutUnit width() const { return m_width; }
- bool isConditional() const { return m_isConditional; }
-
- void setIsConditional() { m_isConditional = true; }
- void expand(InlineLayoutUnit width) { m_width += width; }
-
-private:
- bool m_isConditional { false };
- InlineLayoutUnit m_width { 0 };
-};
-
-void HangingContent::reset()
-{
- m_isConditional = false;
- m_width = 0;
-}
-
-class LineContentAligner {
-public:
- LineContentAligner(const InlineFormattingContext&, LineBox&, const LineBuilder::RunList&, InlineLayoutUnit availableWidth);
-
- enum class IsLastLineWithInlineContent { No, Yes };
- void alignHorizontally(TextAlignMode, IsLastLineWithInlineContent);
- void alignVertically();
- void adjustBaselineAndLineHeight();
-
- using InlineRunRectList = Vector<Display::InlineRect, 10>;
- const InlineRunRectList& inlineRectList() const { return m_runRectList; }
-
-private:
- HangingContent collectHangingContent(IsLastLineWithInlineContent) const;
-
- const InlineFormattingContext& formattingContext() const { return m_inlineFormattingContext; }
- LayoutState& layoutState() const { return formattingContext().layoutState(); }
-
- const InlineFormattingContext& m_inlineFormattingContext;
- LineBox& m_lineBox;
- const LineBuilder::RunList& m_runs;
- InlineRunRectList m_runRectList;
- InlineLayoutUnit m_availableWidth;
-};
-
-LineContentAligner::LineContentAligner(const InlineFormattingContext& inlineFormattingContext, LineBox& lineBox, const LineBuilder::RunList& runs, InlineLayoutUnit availableWidth)
- : m_inlineFormattingContext(inlineFormattingContext)
- , m_lineBox(lineBox)
- , m_runs(runs)
- , m_availableWidth(availableWidth)
-{
- for (auto& run : m_runs) {
- auto runHeight = [&]() -> InlineLayoutUnit {
- auto& fontMetrics = run.style().fontMetrics();
- if (run.isText() || run.isLineBreak())
- return fontMetrics.height();
-
- if (run.isContainerStart() || run.isContainerEnd())
- return fontMetrics.height();
-
- auto& layoutBox = run.layoutBox();
- auto& boxGeometry = inlineFormattingContext.geometryForBox(layoutBox);
- if (layoutBox.isReplacedBox() || layoutBox.isFloatingPositioned())
- return boxGeometry.contentBoxHeight();
-
- // Non-replaced inline box (e.g. inline-block). It looks a bit misleading but their margin box is considered the content height here.
- return boxGeometry.marginBoxHeight();
- };
- m_runRectList.append({ 0, run.logicalLeft(), run.logicalWidth(), runHeight() });
- }
-}
-
-void LineContentAligner::alignHorizontally(TextAlignMode horizontalAlignment, IsLastLineWithInlineContent isLastLine)
-{
- auto hangingContent = collectHangingContent(isLastLine);
- auto availableWidth = m_availableWidth + hangingContent.width();
- if (m_runs.isEmpty() || availableWidth <= 0)
- return;
-
- if (horizontalAlignment == TextAlignMode::Justify) {
- auto accumulatedExpansion = InlineLayoutUnit { };
- for (size_t index = 0; index < m_runs.size(); ++index) {
- m_runRectList[index].moveHorizontally(accumulatedExpansion);
-
- auto horizontalExpansion = m_runs[index].expansion().horizontalExpansion;
- m_runRectList[index].expandHorizontally(horizontalExpansion);
- accumulatedExpansion += horizontalExpansion;
- }
- return;
- }
-
- auto adjustmentForAlignment = [&] (auto availableWidth) -> Optional<InlineLayoutUnit> {
- switch (horizontalAlignment) {
- case TextAlignMode::Left:
- case TextAlignMode::WebKitLeft:
- case TextAlignMode::Start:
- return { };
- case TextAlignMode::Right:
- case TextAlignMode::WebKitRight:
- case TextAlignMode::End:
- return std::max<InlineLayoutUnit>(availableWidth, 0);
- case TextAlignMode::Center:
- case TextAlignMode::WebKitCenter:
- return std::max<InlineLayoutUnit>(availableWidth / 2, 0);
- case TextAlignMode::Justify:
- ASSERT_NOT_REACHED();
- break;
- }
- ASSERT_NOT_REACHED();
- return { };
- };
-
- if (auto adjustment = adjustmentForAlignment(availableWidth)) {
- // FIXME: line box should not need to be moved, only the runs.
- m_lineBox.moveHorizontally(*adjustment);
- for (auto& runRect : m_runRectList)
- runRect.moveHorizontally(*adjustment);
- }
-}
-
-void LineContentAligner::alignVertically()
-{
- auto scrollableOverflowRect = m_lineBox.logicalRect();
- for (size_t index = 0; index < m_runs.size(); ++index) {
- auto& run = m_runs[index];
- auto& runRect = m_runRectList[index];
- auto logicalTop = InlineLayoutUnit { };
- auto& layoutBox = run.layoutBox();
- auto verticalAlign = layoutBox.style().verticalAlign();
- auto ascent = layoutBox.style().fontMetrics().ascent();
-
- switch (verticalAlign) {
- case VerticalAlign::Baseline:
- if (run.isLineBreak() || run.isText())
- logicalTop = m_lineBox.alignmentBaseline() - ascent;
- else if (run.isContainerStart()) {
- auto& boxGeometry = formattingContext().geometryForBox(layoutBox);
- logicalTop = m_lineBox.alignmentBaseline() - ascent - boxGeometry.borderTop() - boxGeometry.paddingTop().valueOr(0);
- } else if (layoutBox.isInlineBlockBox() && layoutBox.establishesInlineFormattingContext()) {
- auto& formattingState = layoutState().establishedInlineFormattingState(downcast<ContainerBox>(layoutBox));
- // Spec makes us generate at least one line -even if it is empty.
- auto inlineBlockBaseline = formattingState.displayInlineContent()->lineBoxes.last().baseline();
- // The inline-block's baseline offset is relative to its content box. Let's convert it relative to the margin box.
- // _______________ <- margin box
- // |
- // | ____________ <- border box
- // | |
- // | | _________ <- content box
- // | | | ^
- // | | | | <- baseline offset
- // | | | |
- // text | | | v text
- // -----|-|-|---------- <- baseline
- //
- auto& boxGeometry = formattingContext().geometryForBox(layoutBox);
- auto baselineFromMarginBox = boxGeometry.marginBefore() + boxGeometry.borderTop() + boxGeometry.paddingTop().valueOr(0) + inlineBlockBaseline;
- logicalTop = m_lineBox.alignmentBaseline() - baselineFromMarginBox;
- } else {
- auto& boxGeometry = formattingContext().geometryForBox(layoutBox);
- logicalTop = m_lineBox.alignmentBaseline() - (boxGeometry.verticalBorder() + boxGeometry.verticalPadding().valueOr(0_lu) + runRect.height() + boxGeometry.marginAfter());
- }
- break;
- case VerticalAlign::Top:
- logicalTop = 0_lu;
- break;
- case VerticalAlign::Bottom:
- logicalTop = m_lineBox.logicalBottom() - runRect.height();
- break;
- default:
- ASSERT_NOT_IMPLEMENTED_YET();
- break;
- }
- runRect.setTop(logicalTop);
- // Adjust scrollable overflow if the run overflows the line.
- scrollableOverflowRect.expandVerticallyToContain(runRect);
- // Convert runs from relative to the line top/left to the formatting root's border box top/left.
- runRect.moveVertically(m_lineBox.logicalTop());
- runRect.moveHorizontally(m_lineBox.logicalLeft());
- }
- m_lineBox.setScrollableOverflow(scrollableOverflowRect);
-}
-
-void LineContentAligner::adjustBaselineAndLineHeight()
-{
- unsigned inlineContainerNestingLevel = 0;
- auto hasSeenDirectTextOrLineBreak = false;
- for (auto& run : m_runs) {
- auto& layoutBox = run.layoutBox();
- auto& style = layoutBox.style();
- if (run.isText() || run.isLineBreak()) {
- if (inlineContainerNestingLevel) {
- // We've already adjusted the line height/baseline through the parent inline container.
- continue;
- }
- if (hasSeenDirectTextOrLineBreak) {
- // e.g div>first text</div> or <div><span>nested<span>first direct text</div>.
- continue;
- }
- hasSeenDirectTextOrLineBreak = true;
- continue;
- }
-
- if (run.isContainerStart()) {
- ++inlineContainerNestingLevel;
- // Inline containers stretch the line by their font size.
- // Vertical margins, paddings and borders don't contribute to the line height.
- auto& fontMetrics = style.fontMetrics();
- if (style.verticalAlign() == VerticalAlign::Baseline) {
- auto halfLeading = LineBox::halfLeadingMetrics(fontMetrics, style.computedLineHeight());
- // Both halfleading ascent and descent could be negative (tall font vs. small line-height value)
- if (halfLeading.descent > 0)
- m_lineBox.setDescentIfGreater(halfLeading.descent);
- if (halfLeading.ascent > 0)
- m_lineBox.setAscentIfGreater(halfLeading.ascent);
- m_lineBox.setLogicalHeightIfGreater(m_lineBox.ascentAndDescent().height());
- } else
- m_lineBox.setLogicalHeightIfGreater(fontMetrics.height());
- continue;
- }
-
- if (run.isContainerEnd()) {
- // The line's baseline and height have already been adjusted at ContainerStart.
- ASSERT(inlineContainerNestingLevel);
- --inlineContainerNestingLevel;
- continue;
- }
-
- if (run.isBox()) {
- auto& boxGeometry = formattingContext().geometryForBox(layoutBox);
- auto marginBoxHeight = boxGeometry.marginBoxHeight();
-
- switch (style.verticalAlign()) {
- case VerticalAlign::Baseline: {
- if (layoutBox.isInlineBlockBox() && layoutBox.establishesInlineFormattingContext()) {
- // Inline-blocks with inline content always have baselines.
- auto& formattingState = layoutState().establishedInlineFormattingState(downcast<ContainerBox>(layoutBox));
- // There has to be at least one line -even if it is empty.
- auto& lastLineBox = formattingState.displayInlineContent()->lineBoxes.last();
- auto beforeHeight = boxGeometry.marginBefore() + boxGeometry.borderTop() + boxGeometry.paddingTop().valueOr(0);
- m_lineBox.setAlignmentBaselineIfGreater(beforeHeight + lastLineBox.baseline());
- m_lineBox.setLogicalHeightIfGreater(marginBoxHeight);
- } else {
- // Non inline-block boxes sit on the baseline (including their bottom margin).
- m_lineBox.setAscentIfGreater(marginBoxHeight);
- // Ignore negative descent (yes, negative descent is a thing).
- m_lineBox.setLogicalHeightIfGreater(marginBoxHeight + std::max<InlineLayoutUnit>(0, m_lineBox.ascentAndDescent().descent));
- }
- break;
- }
- case VerticalAlign::Top:
- // Top align content never changes the baseline, it only pushes the bottom of the line further down.
- m_lineBox.setLogicalHeightIfGreater(marginBoxHeight);
- break;
- case VerticalAlign::Bottom: {
- // Bottom aligned, tall content pushes the baseline further down from the line top.
- auto lineLogicalHeight = m_lineBox.logicalHeight();
- if (marginBoxHeight > lineLogicalHeight) {
- m_lineBox.setLogicalHeightIfGreater(marginBoxHeight);
- m_lineBox.setAlignmentBaselineIfGreater(m_lineBox.alignmentBaseline() + (marginBoxHeight - lineLogicalHeight));
- }
- break;
- }
- default:
- ASSERT_NOT_IMPLEMENTED_YET();
- break;
- }
- continue;
- }
- }
-}
-
-HangingContent LineContentAligner::collectHangingContent(IsLastLineWithInlineContent isLastLineWithInlineContent) const
-{
- auto hangingContent = HangingContent { };
- if (isLastLineWithInlineContent == IsLastLineWithInlineContent::Yes)
- hangingContent.setIsConditional();
- for (auto& run : WTF::makeReversedRange(m_runs)) {
- if (run.isContainerStart() || run.isContainerEnd())
- continue;
- if (run.isLineBreak()) {
- hangingContent.setIsConditional();
- continue;
- }
- if (!run.hasTrailingWhitespace())
- break;
- // Check if we have a preserved or hung whitespace.
- if (run.style().whiteSpace() != WhiteSpace::PreWrap)
- break;
- // This is either a normal or conditionally hanging trailing whitespace.
- hangingContent.expand(run.trailingWhitespaceWidth());
- }
- return hangingContent;
-}
-
void InlineFormattingContext::layoutInFlowContent(InvalidationState& invalidationState, const ConstraintsForInFlowContent& constraints)
{
LOG_WITH_STREAM(FormattingContextLayout, stream << "[Start] -> inline formatting context -> formatting root(" << &root() << ")");
@@ -446,55 +152,25 @@
auto partialLeadingContentLength = previousLine ? previousLine->overflowContentLength : WTF::nullopt;
auto lineContent = lineLayoutContext.layoutInlineContent(line, needsLayoutRange, partialLeadingContentLength);
auto lineContentRange = lineContent.inlineItemRange;
-
- // FIXME: This is temporary and will eventually get merged to LineBox.
auto isLastLineWithInlineContent = [&] {
+ if (lineContent.partialContent)
+ return false;
if (lineContentRange.end == needsLayoutRange.end)
- return LineContentAligner::IsLastLineWithInlineContent::Yes;
- if (lineContent.partialContent)
- return LineContentAligner::IsLastLineWithInlineContent::No;
+ return true;
// Omit floats to see if this is the last line with inline content.
for (auto i = needsLayoutRange.end; i--;) {
if (!inlineItems[i].isFloat())
- return i == lineContentRange.end - 1 ? LineContentAligner::IsLastLineWithInlineContent::Yes : LineContentAligner::IsLastLineWithInlineContent::No;
+ return i == lineContentRange.end - 1;
}
// There has to be at least one non-float item.
ASSERT_NOT_REACHED();
- return LineContentAligner::IsLastLineWithInlineContent::No;
+ return false;
}();
- line.close(isLastLineWithInlineContent == LineContentAligner::IsLastLineWithInlineContent::Yes);
+ line.close(isLastLineWithInlineContent);
+ auto lineRect = Display::InlineRect { lineConstraints.logicalTopLeft, line.lineLogicalWidth(), lineConstraints.lineHeight};
+ auto lineBox = LineBox { *this, lineRect, lineContent.runs, line.isVisuallyEmpty() ? LineBox::IsLineVisuallyEmpty::Yes : LineBox::IsLineVisuallyEmpty::No, isLastLineWithInlineContent ? LineBox::IsLastLineWithInlineContent::Yes : LineBox::IsLastLineWithInlineContent::No };
+ setDisplayBoxesForLine(lineContent, lineBox, constraints.horizontal);
- auto lineBox = LineBox { Display::InlineRect { lineConstraints.logicalTopLeft, line.contentLogicalWidth(), lineConstraints.lineHeight }, LineBox::halfLeadingMetrics(root().style().fontMetrics(), lineConstraints.lineHeight) };
- auto contentAligner = LineContentAligner { *this, lineBox, line.runs(), line.availableWidth() };
- auto alignLineContent = [&] {
- contentAligner.adjustBaselineAndLineHeight();
- if (line.isVisuallyEmpty()) {
- lineBox.resetAlignmentBaseline();
- lineBox.setLogicalHeight({ });
- }
- // Remove descent when all content is baseline aligned but none of them have descent.
- if (quirks().lineDescentNeedsCollapsing(line.runs())) {
- lineBox.shrinkVertically(lineBox.ascentAndDescent().descent);
- lineBox.resetDescent();
- }
- contentAligner.alignVertically();
-
- auto computedHorizontalAlignment = [&] {
- if (root().style().textAlign() != TextAlignMode::Justify)
- return root().style().textAlign();
- // Text is justified according to the method specified by the text-justify property,
- // in order to exactly fill the line box. Unless otherwise specified by text-align-last,
- // the last line before a forced break or the end of the block is start-aligned.
- if (line.runs().last().isLineBreak() || isLastLineWithInlineContent == LineContentAligner::IsLastLineWithInlineContent::Yes)
- return TextAlignMode::Start;
- return TextAlignMode::Justify;
- };
- contentAligner.alignHorizontally(computedHorizontalAlignment(), isLastLineWithInlineContent);
- };
-
- alignLineContent();
- setDisplayBoxesForLine(line, contentAligner.inlineRectList(), lineBox, lineContent, constraints.horizontal);
-
if (!lineContentRange.isEmpty()) {
ASSERT(needsLayoutRange.start < lineContentRange.end);
lineLogicalTop = lineBox.logicalBottom();
@@ -517,7 +193,7 @@
continue;
}
// Floats prevented us placing any content on the line.
- ASSERT(line.runs().isEmpty());
+ ASSERT(lineContent.runs.isEmpty());
ASSERT(line.hasIntrusiveFloat());
// Move the next line below the intrusive float.
auto floatingContext = FloatingContext { root(), *this, formattingState().floatingState() };
@@ -807,10 +483,9 @@
return LineConstraints { { lineLogicalLeft, lineLogicalTop }, lineLogicalRight - lineLogicalLeft, initialLineHeight, lineIsConstrainedByFloat };
}
-void InlineFormattingContext::setDisplayBoxesForLine(const LineBuilder& line, const LineContentAligner::InlineRunRectList& runRectList, const LineBox& lineBox, const LineLayoutContext::LineContent& lineContent, const HorizontalConstraints& horizontalConstraints)
+void InlineFormattingContext::setDisplayBoxesForLine(const LineLayoutContext::LineContent& lineContent, const LineBox& lineBox, const HorizontalConstraints& horizontalConstraints)
{
auto& formattingState = this->formattingState();
-
if (!lineContent.floats.isEmpty()) {
auto floatingContext = FloatingContext { root(), *this, formattingState.floatingState() };
// Move floats to their final position.
@@ -836,7 +511,8 @@
auto lineIndex = inlineContent.lineBoxes.size();
auto lineInkOverflow = lineBox.scrollableOverflow();
// Compute box final geometry.
- auto& lineRuns = line.runs();
+ auto& runRectList = lineBox.inlineRectList();
+ auto& lineRuns = lineContent.runs;
for (size_t index = 0; index < lineRuns.size(); ++index) {
auto& lineRun = lineRuns.at(index);
auto logicalRect = runRectList[index];
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h (266275 => 266276)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h 2020-08-28 08:46:45 UTC (rev 266275)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h 2020-08-28 13:37:03 UTC (rev 266276)
@@ -36,6 +36,7 @@
class InlineFormattingState;
class InvalidationState;
+class LineBox;
// This class implements the layout logic for inline formatting contexts.
// https://www.w3.org/TR/CSS22/visuren.html#inline-formatting
@@ -94,7 +95,7 @@
bool lineIsConstrainedByFloat { false };
};
LineConstraints constraintsForLine(const HorizontalConstraints&, InlineLayoutUnit lineLogicalTop);
- void setDisplayBoxesForLine(const LineBuilder&, const Vector<Display::InlineRect, 10>&, const LineBox&, const LineLayoutContext::LineContent&, const HorizontalConstraints&);
+ void setDisplayBoxesForLine(const LineLayoutContext::LineContent&, const LineBox&, const HorizontalConstraints&);
void invalidateFormattingState(const InvalidationState&);
const InlineFormattingState& formattingState() const { return downcast<InlineFormattingState>(FormattingContext::formattingState()); }
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextQuirks.cpp (266275 => 266276)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextQuirks.cpp 2020-08-28 08:46:45 UTC (rev 266275)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextQuirks.cpp 2020-08-28 13:37:03 UTC (rev 266276)
@@ -24,7 +24,9 @@
*/
#include "config.h"
+#include "DisplayBox.h"
#include "InlineFormattingContext.h"
+#include "InlineLineBox.h"
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
Added: trunk/Source/WebCore/layout/inlineformatting/InlineLineBox.cpp (0 => 266276)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBox.cpp (rev 0)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBox.cpp 2020-08-28 13:37:03 UTC (rev 266276)
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InlineLineBox.h"
+
+#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+
+namespace WebCore {
+namespace Layout {
+
+struct HangingContent {
+public:
+ void reset();
+
+ InlineLayoutUnit width() const { return m_width; }
+ bool isConditional() const { return m_isConditional; }
+
+ void setIsConditional() { m_isConditional = true; }
+ void expand(InlineLayoutUnit width) { m_width += width; }
+
+private:
+ bool m_isConditional { false };
+ InlineLayoutUnit m_width { 0 };
+};
+
+void HangingContent::reset()
+{
+ m_isConditional = false;
+ m_width = 0;
+}
+
+LineBox::LineBox(const InlineFormattingContext& inlineFormattingContext, const Display::InlineRect& lineRect, const LineBuilder::RunList& runs, IsLineVisuallyEmpty isLineVisuallyEmpty, IsLastLineWithInlineContent isLastLineWithInlineContent)
+ : m_inlineFormattingContext(inlineFormattingContext)
+ , m_runs(runs)
+ , m_rect(lineRect)
+ , m_scrollableOverflow(lineRect)
+{
+#if ASSERT_ENABLED
+ m_hasValidAlignmentBaseline = true;
+#endif
+ auto& rootStyle = inlineFormattingContext.root().style();
+ auto halfLeadingMetrics = this->halfLeadingMetrics(rootStyle.fontMetrics(), lineRect.height());
+
+ m_alignmentBaseline = halfLeadingMetrics.ascent;
+ m_rootInlineBox = InlineBox { halfLeadingMetrics };
+
+ auto contentLogicalWidth = InlineLayoutUnit { };
+ for (auto& run : m_runs) {
+ auto runHeight = [&]() -> InlineLayoutUnit {
+ auto& fontMetrics = run.style().fontMetrics();
+ if (run.isText() || run.isLineBreak())
+ return fontMetrics.height();
+
+ if (run.isContainerStart() || run.isContainerEnd())
+ return fontMetrics.height();
+
+ auto& layoutBox = run.layoutBox();
+ auto& boxGeometry = inlineFormattingContext.geometryForBox(layoutBox);
+ if (layoutBox.isReplacedBox() || layoutBox.isFloatingPositioned())
+ return boxGeometry.contentBoxHeight();
+
+ // Non-replaced inline box (e.g. inline-block). It looks a bit misleading but their margin box is considered the content height here.
+ return boxGeometry.marginBoxHeight();
+ };
+ m_runRectList.append({ 0, run.logicalLeft(), run.logicalWidth(), runHeight() });
+ contentLogicalWidth += run.logicalWidth();
+ }
+ m_scrollableOverflow.setWidth(std::max(lineRect.width(), contentLogicalWidth));
+ alignVertically();
+ alignHorizontally(lineRect.width() - contentLogicalWidth, isLastLineWithInlineContent);
+
+ if (isLineVisuallyEmpty == IsLineVisuallyEmpty::Yes) {
+ m_rect.setHeight({ });
+ m_rootInlineBox.ascentAndDescent = { };
+ }
+}
+
+void LineBox::alignHorizontally(InlineLayoutUnit availableWidth, IsLastLineWithInlineContent isLastLine)
+{
+ auto hangingContent = collectHangingContent(isLastLine);
+ availableWidth += hangingContent.width();
+ if (m_runs.isEmpty() || availableWidth <= 0)
+ return;
+
+ auto computedHorizontalAlignment = [&] {
+ auto& rootStyle = formattingContext().root().style();
+ if (rootStyle.textAlign() != TextAlignMode::Justify)
+ return rootStyle.textAlign();
+ // Text is justified according to the method specified by the text-justify property,
+ // in order to exactly fill the line box. Unless otherwise specified by text-align-last,
+ // the last line before a forced break or the end of the block is start-aligned.
+ if (m_runs.last().isLineBreak() || isLastLine == IsLastLineWithInlineContent::Yes)
+ return TextAlignMode::Start;
+ return TextAlignMode::Justify;
+ }();
+
+ if (computedHorizontalAlignment == TextAlignMode::Justify) {
+ auto accumulatedExpansion = InlineLayoutUnit { };
+ for (size_t index = 0; index < m_runs.size(); ++index) {
+ m_runRectList[index].moveHorizontally(accumulatedExpansion);
+
+ auto horizontalExpansion = m_runs[index].expansion().horizontalExpansion;
+ m_runRectList[index].expandHorizontally(horizontalExpansion);
+ accumulatedExpansion += horizontalExpansion;
+ }
+ return;
+ }
+
+ auto adjustmentForAlignment = [&] (auto availableWidth) -> Optional<InlineLayoutUnit> {
+ switch (computedHorizontalAlignment) {
+ case TextAlignMode::Left:
+ case TextAlignMode::WebKitLeft:
+ case TextAlignMode::Start:
+ return { };
+ case TextAlignMode::Right:
+ case TextAlignMode::WebKitRight:
+ case TextAlignMode::End:
+ return std::max<InlineLayoutUnit>(availableWidth, 0);
+ case TextAlignMode::Center:
+ case TextAlignMode::WebKitCenter:
+ return std::max<InlineLayoutUnit>(availableWidth / 2, 0);
+ case TextAlignMode::Justify:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ ASSERT_NOT_REACHED();
+ return { };
+ };
+
+ if (auto adjustment = adjustmentForAlignment(availableWidth)) {
+ // FIXME: line box should not need to be moved, only the runs.
+ m_rect.moveHorizontally(*adjustment);
+ for (auto& runRect : m_runRectList)
+ runRect.moveHorizontally(*adjustment);
+ }
+}
+
+void LineBox::alignVertically()
+{
+ adjustBaselineAndLineHeight();
+ for (size_t index = 0; index < m_runs.size(); ++index) {
+ auto& run = m_runs[index];
+ auto& runRect = m_runRectList[index];
+ auto logicalTop = InlineLayoutUnit { };
+ auto& layoutBox = run.layoutBox();
+ auto verticalAlign = layoutBox.style().verticalAlign();
+ auto ascent = layoutBox.style().fontMetrics().ascent();
+
+ switch (verticalAlign) {
+ case VerticalAlign::Baseline:
+ if (run.isLineBreak() || run.isText())
+ logicalTop = alignmentBaseline() - ascent;
+ else if (run.isContainerStart()) {
+ auto& boxGeometry = formattingContext().geometryForBox(layoutBox);
+ logicalTop = alignmentBaseline() - ascent - boxGeometry.borderTop() - boxGeometry.paddingTop().valueOr(0);
+ } else if (layoutBox.isInlineBlockBox() && layoutBox.establishesInlineFormattingContext()) {
+ auto& formattingState = layoutState().establishedInlineFormattingState(downcast<ContainerBox>(layoutBox));
+ // Spec makes us generate at least one line -even if it is empty.
+ auto inlineBlockBaseline = formattingState.displayInlineContent()->lineBoxes.last().baseline();
+ // The inline-block's baseline offset is relative to its content box. Let's convert it relative to the margin box.
+ // _______________ <- margin box
+ // |
+ // | ____________ <- border box
+ // | |
+ // | | _________ <- content box
+ // | | | ^
+ // | | | | <- baseline offset
+ // | | | |
+ // text | | | v text
+ // -----|-|-|---------- <- baseline
+ //
+ auto& boxGeometry = formattingContext().geometryForBox(layoutBox);
+ auto baselineFromMarginBox = boxGeometry.marginBefore() + boxGeometry.borderTop() + boxGeometry.paddingTop().valueOr(0) + inlineBlockBaseline;
+ logicalTop = alignmentBaseline() - baselineFromMarginBox;
+ } else {
+ auto& boxGeometry = formattingContext().geometryForBox(layoutBox);
+ logicalTop = alignmentBaseline() - (boxGeometry.verticalBorder() + boxGeometry.verticalPadding().valueOr(0_lu) + runRect.height() + boxGeometry.marginAfter());
+ }
+ break;
+ case VerticalAlign::Top:
+ logicalTop = 0_lu;
+ break;
+ case VerticalAlign::Bottom:
+ logicalTop = logicalBottom() - runRect.height();
+ break;
+ default:
+ ASSERT_NOT_IMPLEMENTED_YET();
+ break;
+ }
+ runRect.setTop(logicalTop);
+ // Adjust scrollable overflow if the run overflows the line.
+ m_scrollableOverflow.expandVerticallyToContain(runRect);
+ // Convert runs from relative to the line top/left to the formatting root's border box top/left.
+ runRect.moveVertically(this->logicalTop());
+ runRect.moveHorizontally(logicalLeft());
+ }
+}
+
+void LineBox::adjustBaselineAndLineHeight()
+{
+ unsigned inlineContainerNestingLevel = 0;
+ auto hasSeenDirectTextOrLineBreak = false;
+ for (auto& run : m_runs) {
+ auto& layoutBox = run.layoutBox();
+ auto& style = layoutBox.style();
+ if (run.isText() || run.isLineBreak()) {
+ // For text content we set the baseline either through the initial strut (set by the formatting context root) or
+ // through the inline container (start). Normally the text content itself does not stretch the line.
+ if (inlineContainerNestingLevel) {
+ // We've already adjusted the line height/baseline through the parent inline container.
+ continue;
+ }
+ if (hasSeenDirectTextOrLineBreak) {
+ // e.g div>first text</div> or <div><span>nested<span>first direct text</div>.
+ continue;
+ }
+ hasSeenDirectTextOrLineBreak = true;
+ continue;
+ }
+
+ if (run.isContainerStart()) {
+ ++inlineContainerNestingLevel;
+ // Inline containers stretch the line by their font size.
+ // Vertical margins, paddings and borders don't contribute to the line height.
+ auto& fontMetrics = style.fontMetrics();
+ if (style.verticalAlign() == VerticalAlign::Baseline) {
+ auto halfLeading = LineBox::halfLeadingMetrics(fontMetrics, style.computedLineHeight());
+ // Both halfleading ascent and descent could be negative (tall font vs. small line-height value)
+ if (halfLeading.descent > 0)
+ setDescentIfGreater(halfLeading.descent);
+ if (halfLeading.ascent > 0)
+ setAscentIfGreater(halfLeading.ascent);
+ setLogicalHeightIfGreater(ascentAndDescent().height());
+ } else
+ setLogicalHeightIfGreater(fontMetrics.height());
+ continue;
+ }
+
+ if (run.isContainerEnd()) {
+ // The line's baseline and height have already been adjusted at ContainerStart.
+ ASSERT(inlineContainerNestingLevel);
+ --inlineContainerNestingLevel;
+ continue;
+ }
+
+ if (run.isBox()) {
+ auto& boxGeometry = formattingContext().geometryForBox(layoutBox);
+ auto marginBoxHeight = boxGeometry.marginBoxHeight();
+
+ switch (style.verticalAlign()) {
+ case VerticalAlign::Baseline: {
+ if (layoutBox.isInlineBlockBox() && layoutBox.establishesInlineFormattingContext()) {
+ // Inline-blocks with inline content always have baselines.
+ auto& formattingState = layoutState().establishedInlineFormattingState(downcast<ContainerBox>(layoutBox));
+ // There has to be at least one line -even if it is empty.
+ auto& lastLineBox = formattingState.displayInlineContent()->lineBoxes.last();
+ auto beforeHeight = boxGeometry.marginBefore() + boxGeometry.borderTop() + boxGeometry.paddingTop().valueOr(0);
+ setAlignmentBaselineIfGreater(beforeHeight + lastLineBox.baseline());
+ setLogicalHeightIfGreater(marginBoxHeight);
+ } else {
+ // Non inline-block boxes sit on the baseline (including their bottom margin).
+ setAscentIfGreater(marginBoxHeight);
+ // Ignore negative descent (yes, negative descent is a thing).
+ setLogicalHeightIfGreater(marginBoxHeight + std::max<InlineLayoutUnit>(0, ascentAndDescent().descent));
+ }
+ break;
+ }
+ case VerticalAlign::Top:
+ // Top align content never changes the baseline, it only pushes the bottom of the line further down.
+ setLogicalHeightIfGreater(marginBoxHeight);
+ break;
+ case VerticalAlign::Bottom: {
+ // Bottom aligned, tall content pushes the baseline further down from the line top.
+ auto lineLogicalHeight = logicalHeight();
+ if (marginBoxHeight > lineLogicalHeight) {
+ setLogicalHeightIfGreater(marginBoxHeight);
+ setAlignmentBaselineIfGreater(alignmentBaseline() + (marginBoxHeight - lineLogicalHeight));
+ }
+ break;
+ }
+ default:
+ ASSERT_NOT_IMPLEMENTED_YET();
+ break;
+ }
+ continue;
+ }
+ }
+}
+
+HangingContent LineBox::collectHangingContent(IsLastLineWithInlineContent isLastLineWithInlineContent) const
+{
+ auto hangingContent = HangingContent { };
+ if (isLastLineWithInlineContent == IsLastLineWithInlineContent::Yes)
+ hangingContent.setIsConditional();
+ for (auto& run : WTF::makeReversedRange(m_runs)) {
+ if (run.isContainerStart() || run.isContainerEnd())
+ continue;
+ if (run.isLineBreak()) {
+ hangingContent.setIsConditional();
+ continue;
+ }
+ if (!run.hasTrailingWhitespace())
+ break;
+ // Check if we have a preserved or hung whitespace.
+ if (run.style().whiteSpace() != WhiteSpace::PreWrap)
+ break;
+ // This is either a normal or conditionally hanging trailing whitespace.
+ hangingContent.expand(run.trailingWhitespaceWidth());
+ }
+ return hangingContent;
+}
+
+}
+}
+
+#endif
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBox.h (266275 => 266276)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBox.h 2020-08-28 08:46:45 UTC (rev 266275)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBox.h 2020-08-28 13:37:03 UTC (rev 266276)
@@ -29,10 +29,14 @@
#include "DisplayBox.h"
#include "DisplayInlineRect.h"
+#include "InlineLineBuilder.h"
namespace WebCore {
namespace Layout {
+class InlineFormattingContext;
+struct HangingContent;
+
struct AscentAndDescent {
InlineLayoutUnit height() const { return ascent + descent; }
@@ -50,20 +54,25 @@
AscentAndDescent ascentAndDescent;
};
- LineBox(const Display::InlineRect&, const AscentAndDescent&);
- LineBox() = default;
+ enum class IsLastLineWithInlineContent { No, Yes };
+ enum class IsLineVisuallyEmpty { No, Yes };
+ LineBox(const InlineFormattingContext&, const Display::InlineRect&, const LineBuilder::RunList&, IsLineVisuallyEmpty, IsLastLineWithInlineContent);
- const Display::InlineRect& logicalRect() const { return m_rect; }
- const Display::InlineRect& scrollableOverflow() const { return m_scrollableOverflow; }
+ using InlineRunRectList = Vector<Display::InlineRect, 10>;
+ const InlineRunRectList& inlineRectList() const { return m_runRectList; }
InlineLayoutUnit logicalLeft() const { return m_rect.left(); }
InlineLayoutUnit logicalRight() const { return m_rect.right(); }
InlineLayoutUnit logicalTop() const { return m_rect.top(); }
InlineLayoutUnit logicalBottom() const { return m_rect.bottom(); }
-
InlineLayoutUnit logicalWidth() const { return m_rect.width(); }
InlineLayoutUnit logicalHeight() const { return m_rect.height(); }
+ const Display::InlineRect& logicalRect() const { return m_rect; }
+ const Display::InlineRect& scrollableOverflow() const { return m_scrollableOverflow; }
+
+ static AscentAndDescent halfLeadingMetrics(const FontMetrics&, InlineLayoutUnit lineLogicalHeight);
+
// Aligment baseline from line logical top.
//
// ------------------- line logical top ------------------- (top align)
@@ -80,63 +89,39 @@
// v
// ------------------- line logical bottom -------------------
InlineLayoutUnit alignmentBaseline() const;
+
+private:
const AscentAndDescent& ascentAndDescent() const { return m_rootInlineBox.ascentAndDescent; }
void setAlignmentBaselineIfGreater(InlineLayoutUnit);
void setAscentIfGreater(InlineLayoutUnit);
void setDescentIfGreater(InlineLayoutUnit);
-
- void resetAlignmentBaseline();
- void resetDescent() { m_rootInlineBox.ascentAndDescent.descent = { }; }
-
- void setLogicalHeight(InlineLayoutUnit logicalHeight) { m_rect.setHeight(logicalHeight); }
-
void setLogicalHeightIfGreater(InlineLayoutUnit);
- void setLogicalWidth(InlineLayoutUnit logicalWidth) { m_rect.setWidth(logicalWidth); }
void setScrollableOverflow(const Display::InlineRect& rect) { m_scrollableOverflow = rect; }
- void moveHorizontally(InlineLayoutUnit delta) { m_rect.moveHorizontally(delta); }
+ void alignHorizontally(InlineLayoutUnit availableWidth, IsLastLineWithInlineContent);
+ void alignVertically();
+ void adjustBaselineAndLineHeight();
- void expandHorizontally(InlineLayoutUnit delta) { m_rect.expandHorizontally(delta); }
- void shrinkHorizontally(InlineLayoutUnit delta) { expandHorizontally(-delta); }
+ HangingContent collectHangingContent(IsLastLineWithInlineContent) const;
- void expandVertically(InlineLayoutUnit delta) { m_rect.expandVertically(delta); }
- void shrinkVertically(InlineLayoutUnit delta) { expandVertically(-delta); }
+ const InlineFormattingContext& formattingContext() const { return m_inlineFormattingContext; }
+ LayoutState& layoutState() const { return formattingContext().layoutState(); }
- // https://www.w3.org/TR/CSS22/visuren.html#inline-formatting
- // Line boxes that contain no text, no preserved white space, no inline elements with non-zero margins, padding, or borders,
- // and no other in-flow content (such as images, inline blocks or inline tables), and do not end with a preserved newline
- // must be treated as zero-height line boxes for the purposes of determining the positions of any elements inside of them,
- // and must be treated as not existing for any other purpose.
- // Note that it does not necessarily mean visually non-empty line. <span style="font-size: 0px">this is still considered non-empty</span>
- bool isConsideredEmpty() const { return m_isConsideredEmpty; }
- void setIsConsideredEmpty() { m_isConsideredEmpty = true; }
- void setIsConsideredNonEmpty() { m_isConsideredEmpty = false; }
-
- static AscentAndDescent halfLeadingMetrics(const FontMetrics&, InlineLayoutUnit lineLogicalHeight);
-
private:
#if ASSERT_ENABLED
bool m_hasValidAlignmentBaseline { false };
#endif
+ const InlineFormattingContext& m_inlineFormattingContext;
+ const LineBuilder::RunList& m_runs;
Display::InlineRect m_rect;
Display::InlineRect m_scrollableOverflow;
InlineLayoutUnit m_alignmentBaseline { 0 };
- bool m_isConsideredEmpty { true };
InlineBox m_rootInlineBox;
+ InlineRunRectList m_runRectList;
};
-inline LineBox::LineBox(const Display::InlineRect& rect, const AscentAndDescent& ascentAndDescent)
- : m_rect(rect)
- , m_alignmentBaseline(ascentAndDescent.ascent)
- , m_rootInlineBox(ascentAndDescent)
-{
-#if ASSERT_ENABLED
- m_hasValidAlignmentBaseline = true;
-#endif
-}
-
inline LineBox::InlineBox::InlineBox(const AscentAndDescent& ascentAndDescent)
: ascentAndDescent(ascentAndDescent)
{
@@ -178,16 +163,6 @@
return m_alignmentBaseline;
}
-inline void LineBox::resetAlignmentBaseline()
-{
-#if ASSERT_ENABLED
- m_hasValidAlignmentBaseline = true;
-#endif
- m_alignmentBaseline = 0_lu;
- m_rootInlineBox.ascentAndDescent.descent = { };
- m_rootInlineBox.ascentAndDescent.ascent = { };
-}
-
inline AscentAndDescent LineBox::halfLeadingMetrics(const FontMetrics& fontMetrics, InlineLayoutUnit lineLogicalHeight)
{
auto ascent = fontMetrics.ascent();
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h (266275 => 266276)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h 2020-08-28 08:46:45 UTC (rev 266275)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h 2020-08-28 13:37:03 UTC (rev 266276)
@@ -29,7 +29,6 @@
#include "DisplayRun.h"
#include "InlineItem.h"
-#include "InlineLineBox.h"
#include "InlineTextItem.h"
namespace WebCore {
@@ -37,7 +36,6 @@
class InlineFormattingContext;
class InlineSoftLineBreakItem;
-class LineContentAligner;
class LineBuilder {
public:
@@ -56,8 +54,9 @@
bool isVisuallyEmpty() const { return m_isVisuallyEmpty; }
- InlineLayoutUnit availableWidth() const { return m_lineLogicalWidth - contentLogicalWidth(); }
+ InlineLayoutUnit lineLogicalWidth() const { return m_lineLogicalWidth; }
InlineLayoutUnit contentLogicalWidth() const { return m_contentLogicalWidth; }
+ InlineLayoutUnit availableWidth() const { return lineLogicalWidth() - contentLogicalWidth(); }
InlineLayoutUnit trimmableTrailingWidth() const { return m_trimmableTrailingContent.width(); }
bool isTrailingRunFullyTrimmable() const { return m_trimmableTrailingContent.isTrailingRunFullyTrimmable(); }
Modified: trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp (266275 => 266276)
--- trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp 2020-08-28 08:46:45 UTC (rev 266275)
+++ trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp 2020-08-28 13:37:03 UTC (rev 266276)
@@ -28,6 +28,7 @@
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+#include "DisplayBox.h"
#include "InlineFormattingContext.h"
#include "LayoutBox.h"
#include "TextUtil.h"
@@ -334,7 +335,7 @@
ASSERT(lineRange.end <= layoutRange.end);
// Adjust hyphenated line count.
m_successiveHyphenatedLineCount = partialContent && partialContent->trailingContentHasHyphen ? m_successiveHyphenatedLineCount + 1 : 0;
- return LineContent { partialContent, lineRange, WTFMove(m_floats) };
+ return LineContent { partialContent, lineRange, WTFMove(m_floats), line.runs() };
}
void LineLayoutContext::nextContentForLine(LineCandidate& lineCandidate, unsigned currentInlineItemIndex, const InlineItemRange& layoutRange, Optional<unsigned> partialLeadingContentLength, InlineLayoutUnit availableLineWidth, InlineLayoutUnit currentLogicalRight)
Modified: trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.h (266275 => 266276)
--- trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.h 2020-08-28 08:46:45 UTC (rev 266275)
+++ trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.h 2020-08-28 13:37:03 UTC (rev 266276)
@@ -58,6 +58,7 @@
};
using FloatList = Vector<Float>;
FloatList floats;
+ const LineBuilder::RunList& runs;
};
LineContent layoutInlineContent(LineBuilder&, const InlineItemRange&, Optional<unsigned> partialLeadingContentLength);