Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp (281745 => 281746)
--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp 2021-08-29 17:38:29 UTC (rev 281745)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp 2021-08-29 18:57:47 UTC (rev 281746)
@@ -28,7 +28,10 @@
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+#include "FontCascade.h"
#include "LayoutBoxGeometry.h"
+#include "LayoutInitialContainingBlock.h"
+#include "RuntimeEnabledFeatures.h"
namespace WebCore {
namespace Layout {
@@ -47,7 +50,7 @@
// Every line starts with a root run, even the empty ones.
auto rootInlineBoxRect = lineBox.logicalRectForRootInlineBox();
rootInlineBoxRect.moveBy(lineBoxLogicalTopLeft);
- formattingState.addLineRun({ lineIndex, LineRun::Type::RootInlineBox, root(), rootInlineBoxRect, { }, { }, lineBox.rootInlineBox().hasContent()});
+ formattingState.addLineRun({ lineIndex, LineRun::Type::RootInlineBox, root(), rootInlineBoxRect, rootInlineBoxRect, { }, { }, lineBox.rootInlineBox().hasContent()});
// Spanning inline boxes start at the very beginning of the line.
auto lineSpanningInlineBoxIndex = formattingState.lineRuns().size();
@@ -65,13 +68,29 @@
case InlineItem::Type::Text: {
auto textRunRect = lineBox.logicalRectForTextRun(lineRun);
textRunRect.moveBy(lineBoxLogicalTopLeft);
- formattingState.addLineRun({ lineIndex, LineRun::Type::Text, layoutBox, textRunRect, lineRun.expansion(), lineRun.textContent() });
+
+ auto inkOverflow = [&] {
+ auto& style = layoutBox.style();
+ auto initialContaingBlockSize = RuntimeEnabledFeatures::sharedFeatures().layoutFormattingContextIntegrationEnabled()
+ ? formattingState.layoutState().viewportSize()
+ : formattingState.layoutState().geometryForBox(layoutBox.initialContainingBlock()).contentBox().size();
+ auto strokeOverflow = std::ceil(style.computedStrokeWidth(ceiledIntSize(initialContaingBlockSize)));
+ auto inkOverflow = textRunRect;
+ inkOverflow.inflate(strokeOverflow);
+ auto letterSpacing = style.fontCascade().letterSpacing();
+ if (letterSpacing < 0) {
+ // Last letter's negative spacing shrinks logical rect. Push it to ink overflow.
+ inkOverflow.expand(-letterSpacing, { });
+ }
+ return inkOverflow;
+ };
+ formattingState.addLineRun({ lineIndex, LineRun::Type::Text, layoutBox, textRunRect, inkOverflow(), lineRun.expansion(), lineRun.textContent() });
break;
}
case InlineItem::Type::SoftLineBreak: {
auto softLineBreakRunRect = lineBox.logicalRectForTextRun(lineRun);
softLineBreakRunRect.moveBy(lineBoxLogicalTopLeft);
- formattingState.addLineRun({ lineIndex, LineRun::Type::SoftLineBreak, layoutBox, softLineBreakRunRect, lineRun.expansion(), lineRun.textContent() });
+ formattingState.addLineRun({ lineIndex, LineRun::Type::SoftLineBreak, layoutBox, softLineBreakRunRect, softLineBreakRunRect, lineRun.expansion(), lineRun.textContent() });
break;
}
case InlineItem::Type::HardLineBreak: {
@@ -78,7 +97,7 @@
// Only hard linebreaks have associated layout boxes.
auto lineBreakBoxRect = lineBox.logicalRectForLineBreakBox(layoutBox);
lineBreakBoxRect.moveBy(lineBoxLogicalTopLeft);
- formattingState.addLineRun({ lineIndex, LineRun::Type::LineBreakBox, layoutBox, lineBreakBoxRect, lineRun.expansion(), { } });
+ formattingState.addLineRun({ lineIndex, LineRun::Type::LineBreakBox, layoutBox, lineBreakBoxRect, lineBreakBoxRect, lineRun.expansion(), { } });
auto& boxGeometry = formattingState.boxGeometry(layoutBox);
boxGeometry.setLogicalTopLeft(toLayoutPoint(lineBreakBoxRect.topLeft()));
@@ -90,7 +109,7 @@
auto& boxGeometry = formattingState.boxGeometry(layoutBox);
auto logicalBorderBox = lineBox.logicalBorderBoxForAtomicInlineLevelBox(layoutBox, boxGeometry);
logicalBorderBox.moveBy(lineBoxLogicalTopLeft);
- formattingState.addLineRun({ lineIndex, LineRun::Type::AtomicInlineLevelBox, layoutBox, logicalBorderBox, lineRun.expansion(), { } });
+ formattingState.addLineRun({ lineIndex, LineRun::Type::AtomicInlineLevelBox, layoutBox, logicalBorderBox, logicalBorderBox, lineRun.expansion(), { } });
auto borderBoxLogicalTopLeft = logicalBorderBox.topLeft();
// Note that inline boxes are relative to the line and their top position can be negative.
@@ -105,7 +124,7 @@
inlineBoxBorderBox.moveBy(lineBoxLogicalTopLeft);
if (lineBox.hasContent()) {
// FIXME: It's expected to not have any runs on empty lines. We should reconsider this.
- formattingState.addLineRun({ lineIndex, LineRun::Type::NonRootInlineBox, layoutBox, inlineBoxBorderBox, { }, { }, lineBox.inlineLevelBoxForLayoutBox(layoutBox).hasContent() });
+ formattingState.addLineRun({ lineIndex, LineRun::Type::NonRootInlineBox, layoutBox, inlineBoxBorderBox, inlineBoxBorderBox, { }, { }, lineBox.inlineLevelBoxForLayoutBox(layoutBox).hasContent() });
}
auto inlineBoxSize = LayoutSize { LayoutUnit::fromFloatCeil(inlineBoxBorderBox.width()), LayoutUnit::fromFloatCeil(inlineBoxBorderBox.height()) };
@@ -143,7 +162,7 @@
auto inlineBoxBorderBox = lineBox.logicalBorderBoxForInlineBox(layoutBox, boxGeometry);
inlineBoxBorderBox.moveBy(lineBoxLogicalTopLeft);
- formattingState.lineRuns().insert(lineSpanningInlineBoxIndex++, { lineIndex, LineRun::Type::NonRootInlineBox, layoutBox, inlineBoxBorderBox, { }, { }, inlineLevelBox.hasContent(), true });
+ formattingState.lineRuns().insert(lineSpanningInlineBoxIndex++, { lineIndex, LineRun::Type::NonRootInlineBox, layoutBox, inlineBoxBorderBox, inlineBoxBorderBox, { }, { }, inlineLevelBox.hasContent(), true });
auto inlineBoxSize = LayoutSize { LayoutUnit::fromFloatCeil(inlineBoxBorderBox.width()), LayoutUnit::fromFloatCeil(inlineBoxBorderBox.height()) };
auto logicalRect = Rect { LayoutPoint { inlineBoxBorderBox.topLeft() }, inlineBoxSize };
Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineRun.h (281745 => 281746)
--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineRun.h 2021-08-29 17:38:29 UTC (rev 281745)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineRun.h 2021-08-29 18:57:47 UTC (rev 281746)
@@ -69,7 +69,7 @@
GenericInlineLevelBox
};
struct Expansion;
- LineRun(size_t lineIndex, Type, const Box&, const InlineRect&, Expansion, std::optional<Text> = std::nullopt, bool hasContent = true, bool isLineSpanning = false);
+ LineRun(size_t lineIndex, Type, const Box&, const InlineRect&, const InlineRect& inkOverflow, Expansion, std::optional<Text> = std::nullopt, bool hasContent = true, bool isLineSpanning = false);
bool isText() const { return m_type == Type::Text; }
bool isSoftLineBreak() const { return m_type == Type::SoftLineBreak; }
@@ -88,6 +88,7 @@
bool isLineSpanning() const { return m_isLineSpanning; }
const InlineRect& logicalRect() const { return m_logicalRect; }
+ const InlineRect& inkOverflow() const { return m_inkOverflow; }
InlineLayoutUnit logicalTop() const { return logicalRect().top(); }
InlineLayoutUnit logicalBottom() const { return logicalRect().bottom(); }
@@ -115,6 +116,7 @@
const Type m_type;
WeakPtr<const Layout::Box> m_layoutBox;
InlineRect m_logicalRect;
+ InlineRect m_inkOverflow;
bool m_hasContent { true };
// FIXME: This is temporary until after iterators can skip over line spanning/root inline boxes.
bool m_isLineSpanning { false };
@@ -122,11 +124,12 @@
std::optional<Text> m_text;
};
-inline LineRun::LineRun(size_t lineIndex, Type type, const Layout::Box& layoutBox, const InlineRect& logicalRect, Expansion expansion, std::optional<Text> text, bool hasContent, bool isLineSpanning)
+inline LineRun::LineRun(size_t lineIndex, Type type, const Layout::Box& layoutBox, const InlineRect& logicalRect, const InlineRect& inkOverflow, Expansion expansion, std::optional<Text> text, bool hasContent, bool isLineSpanning)
: m_lineIndex(lineIndex)
, m_type(type)
, m_layoutBox(makeWeakPtr(layoutBox))
, m_logicalRect(logicalRect)
+ , m_inkOverflow(inkOverflow)
, m_hasContent(hasContent)
, m_isLineSpanning(isLineSpanning)
, m_expansion(expansion)
Modified: trunk/Source/WebCore/layout/integration/LayoutIntegrationInlineContentBuilder.cpp (281745 => 281746)
--- trunk/Source/WebCore/layout/integration/LayoutIntegrationInlineContentBuilder.cpp 2021-08-29 17:38:29 UTC (rev 281745)
+++ trunk/Source/WebCore/layout/integration/LayoutIntegrationInlineContentBuilder.cpp 2021-08-29 18:57:47 UTC (rev 281746)
@@ -258,10 +258,13 @@
// Inline boxes are relative to the line box while final runs need to be relative to the parent box
// FIXME: Shouldn't we just leave them be relative to the line box?
auto runRect = FloatRect { lineRun.logicalRect() };
+ auto inkOverflow = FloatRect { lineRun.inkOverflow() };
auto& geometry = m_layoutState.geometryForBox(layoutBox);
runRect.setSize({ geometry.borderBoxWidth(), geometry.borderBoxHeight() });
- if (lineLevelVisualAdjustmentsForRuns[lineIndex].needsIntegralPosition)
+ if (lineLevelVisualAdjustmentsForRuns[lineIndex].needsIntegralPosition) {
runRect.setY(roundToInt(runRect.y()));
+ inkOverflow.setY(roundToInt(inkOverflow.y()));
+ }
// FIXME: Add support for non-text ink overflow.
// FIXME: Add support for cases when the run is after ellipsis.
if (lineRun.isInlineBox()) {
@@ -273,10 +276,10 @@
inlineContent.nonRootInlineBoxes.append({ lineIndex, layoutBox, lineRunRect, hasScrollableContent() });
if (!lineRun.isLineSpanning()) {
// FIXME: Run iterators with (text)runs spanning over multiple lines expect no "in-between" runs (e.g. line spanning or root inline boxes).
- inlineContent.runs.append({ lineIndex, layoutBox, runRect, runRect, { }, { } });
+ inlineContent.runs.append({ lineIndex, layoutBox, runRect, inkOverflow, { }, { } });
}
} else
- inlineContent.runs.append({ lineIndex, layoutBox, runRect, runRect, { }, { } });
+ inlineContent.runs.append({ lineIndex, layoutBox, runRect, inkOverflow, { }, { } });
};
auto createDisplayTextRunForRange = [&](auto& lineRun, auto startOffset, auto endOffset) {
@@ -285,8 +288,11 @@
auto lineIndex = lineRun.lineIndex();
auto& lineBoxLogicalRect = lines[lineIndex].lineBoxLogicalRect();
auto runRect = FloatRect { lineRun.logicalRect() };
- if (lineLevelVisualAdjustmentsForRuns[lineIndex].needsIntegralPosition)
+ auto inkOverflow = FloatRect { lineRun.inkOverflow() };
+ if (lineLevelVisualAdjustmentsForRuns[lineIndex].needsIntegralPosition) {
runRect.setY(roundToInt(runRect.y()));
+ inkOverflow.setY(roundToInt(inkOverflow.y()));
+ }
auto& style = layoutBox.style();
auto text = lineRun.text();
@@ -314,24 +320,11 @@
return String();
};
- auto computedInkOverflow = [&] (auto runRect) {
- auto inkOverflow = runRect;
- auto initialContaingBlockSize = m_layoutState.viewportSize();
- auto strokeOverflow = std::ceil(style.computedStrokeWidth(ceiledIntSize(initialContaingBlockSize)));
- inkOverflow.inflate(strokeOverflow);
- auto letterSpacing = style.fontCascade().letterSpacing();
- if (letterSpacing < 0) {
- // Last letter's negative spacing shrinks logical rect. Push it to ink overflow.
- inkOverflow.expand(-letterSpacing, { });
- }
- return inkOverflow;
- };
RELEASE_ASSERT(startOffset >= text->start() && startOffset < text->end());
RELEASE_ASSERT(endOffset > text->start() && endOffset <= text->end());
auto textContent = Run::TextContent { startOffset, endOffset - startOffset, text->content(), adjustedContentToRender(), text->needsHyphen() };
auto expansion = Run::Expansion { lineRun.expansion().behavior, lineRun.expansion().horizontalExpansion };
- auto displayRun = Run { lineIndex, layoutBox, runRect, computedInkOverflow(runRect), expansion, textContent };
- inlineContent.runs.append(displayRun);
+ inlineContent.runs.append({ lineIndex, layoutBox, runRect, inkOverflow, expansion, textContent });
};
inlineContent.runs.reserveInitialCapacity(lineRuns.size());