Skip to content

Commit 9115d1b

Browse files
committed
Checkbox boundary (outline) appears misaligned in Safari on goindigo.in
https://bugs.webkit.org/show_bug.cgi?id=311035 <rdar://172742551> Reviewed by Antti Koivisto. 1. Make inline outline painting hug the actual content shape by iterating leaf boxes instead of using the line box rect. Each leaf rect is at least as tall as the inline box, but expands for overflowing content (e.g. tall images or SVGs inside a span). 2. Apply ink overflow inflation on the inline box's ink overflow rect (which includes children's extents after propagation) rather than on the inline box's own visual rect. This ensures visual overflow extends around overflowing atomic children that are taller than the inline box. * LayoutTests/fast/repaint/hidpi-inline-outline-atomic-child-overflow-expected.html: Added. * LayoutTests/fast/repaint/hidpi-inline-outline-atomic-child-overflow.html: Added. * Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.cpp: (WebCore::Layout::InlineDisplayContentBuilder::collectInkOverflowForInlineBoxes): * Source/WebCore/rendering/OutlinePainter.cpp: (WebCore::OutlinePainter::paintOutline const): Canonical link: https://commits.webkit.org/310323@main
1 parent 5ddde6f commit 9115d1b

4 files changed

Lines changed: 62 additions & 12 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<style>
3+
body {
4+
margin: 20px;
5+
}
6+
div {
7+
outline: 3px solid blue;
8+
font: 45px/1 Ahem;
9+
color: transparent;
10+
width: 45px;
11+
}
12+
</style>
13+
<div>x</div>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<script src="../../resources/ui-helper.js"></script>
2+
<style>
3+
body { margin: 20px; }
4+
</style>
5+
<div><span id="target"><div style="display: inline-block; width: 45px; height: 41px;"></div></span></div>
6+
<script>
7+
window.testRunner?.waitUntilDone();
8+
window.testRunner?.dontForceRepaint();
9+
10+
async function runTest() {
11+
await UIHelper.renderingUpdate();
12+
document.getElementById("target").style.outline = "3px solid blue";
13+
await UIHelper.renderingUpdate();
14+
await UIHelper.renderingUpdate();
15+
window.testRunner?.notifyDone();
16+
}
17+
18+
window.addEventListener('load', runTest);
19+
</script>

Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,9 +1101,9 @@ void InlineDisplayContentBuilder::collectInkOverflowForInlineBoxes(std::span<Inl
11011101
if (!accumulatedInkOverflowRect.isEmpty())
11021102
displayBox.adjustInkOverflow(accumulatedInkOverflowRect);
11031103
auto& layoutBox = displayBox.layoutBox();
1104-
auto visualRect = FloatRect { displayBox.visualRectIgnoringBlockDirection() };
1105-
adjustInkOverflowForInlineBox(layoutBox, root(), layoutBox.style(), visualRect);
1106-
displayBox.adjustInkOverflow(visualRect);
1104+
auto inkOverflowRect = displayBox.inkOverflow();
1105+
adjustInkOverflowForInlineBox(layoutBox, root(), layoutBox.style(), inkOverflowRect);
1106+
displayBox.adjustInkOverflow(inkOverflowRect);
11071107
}
11081108

11091109
// We stop collecting ink overflow for at root inline box (i.e. don't inflate the root inline box with the inline content here).

Source/WebCore/rendering/OutlinePainter.cpp

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -153,18 +153,36 @@ void OutlinePainter::paintOutline(const RenderInline& renderer, const LayoutPoin
153153
auto isFlipped = containingBlock->writingMode().isBlockFlipped();
154154
Vector<LayoutRect> rects;
155155
for (auto box = InlineIterator::lineLeftmostInlineBoxFor(renderer); box; box.traverseInlineBoxLineRightward()) {
156-
auto lineBox = box->lineBox();
157-
auto logicalTop = std::max(lineBox->contentLogicalTop(), box->logicalTop());
158-
auto logicalBottom = std::min(lineBox->contentLogicalBottom(), box->logicalBottom());
159-
auto enclosingVisualRect = FloatRect { box->logicalLeftIgnoringInlineDirection(), logicalTop, box->logicalWidth(), logicalBottom - logicalTop };
156+
// Start with the inline box's own rect as the base, ensuring the outline
157+
// covers margins, paddings and borders of nested inline boxes.
158+
auto inlineBoxLogicalTop = box->logicalTop();
159+
auto inlineBoxLogicalBottom = box->logicalBottom();
160+
auto baseRect = FloatRect { box->logicalLeftIgnoringInlineDirection(), inlineBoxLogicalTop, box->logicalWidth(), inlineBoxLogicalBottom - inlineBoxLogicalTop };
160161

161162
if (!isHorizontalWritingMode)
162-
enclosingVisualRect = enclosingVisualRect.transposedRect();
163-
163+
baseRect = baseRect.transposedRect();
164164
if (isFlipped)
165-
containingBlock->flipForWritingMode(enclosingVisualRect);
166-
167-
rects.append(LayoutRect { enclosingVisualRect });
165+
containingBlock->flipForWritingMode(baseRect);
166+
rects.append(LayoutRect { baseRect });
167+
168+
// Collect a rect for each leaf box inside this inline box fragment,
169+
// so the outline hugs the actual content shape. Each rect expands
170+
// beyond the inline box for overflowing content.
171+
for (auto leaf = box->firstLeafBox(); leaf && leaf != box->endLeafBox(); ++leaf) {
172+
auto logicalTop = std::min(leaf->logicalTop(), inlineBoxLogicalTop);
173+
auto logicalBottom = std::max(leaf->logicalBottom(), inlineBoxLogicalBottom);
174+
if (logicalTop == inlineBoxLogicalTop && logicalBottom == inlineBoxLogicalBottom)
175+
continue; // Already covered by the base rect.
176+
auto enclosingVisualRect = FloatRect { leaf->logicalLeftIgnoringInlineDirection(), logicalTop, leaf->logicalWidth(), logicalBottom - logicalTop };
177+
178+
if (!isHorizontalWritingMode)
179+
enclosingVisualRect = enclosingVisualRect.transposedRect();
180+
181+
if (isFlipped)
182+
containingBlock->flipForWritingMode(enclosingVisualRect);
183+
184+
rects.append(LayoutRect { enclosingVisualRect });
185+
}
168186
}
169187
paintOutlineWithLineRects(renderer, paintOffset, rects);
170188
}

0 commit comments

Comments
 (0)