Commit 5ed6243a authored by Xiaocheng Hu's avatar Xiaocheng Hu Committed by Commit Bot

Use the correct layout invalidation root in StyleEngine::InvalidateStyleAndLayoutForFontUpdates

The function currently uses the LayoutObject of the documentElement as
the layout invalidation root, which is incorrect because there can be
objects not in its subtree. For example, a modal dialog.

This patch fixes it by using the LayoutView, the root of the layout
tree, as the layout invalidation root.

Bug: 1092411
Change-Id: Ic2475fe1fc9fd9029699a410b4f03a9f3812e240
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2255738Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#781132}
parent c84ac70b
......@@ -138,4 +138,46 @@ TEST_F(FontUpdateInvalidationTest,
main_resource.Finish();
}
// https://crbug.com/1092411
TEST_F(FontUpdateInvalidationTest, LayoutInvalidationOnModalDialog) {
SimRequest main_resource("https://example.com", "text/html");
SimRequest font_resource("https://example.com/Ahem.woff2", "font/woff2");
LoadURL("https://example.com");
main_resource.Write(R"HTML(
<!doctype html>
<style>
@font-face {
font-family: custom-font;
src: url(https://example.com/Ahem.woff2) format("woff2");
}
#target {
font: 25px/1 custom-font, monospace;
}
</style>
<dialog><span id=target>0123456789</span></dialog>
<script>document.querySelector('dialog').showModal();</script>
)HTML");
// First render the page without the custom font
Compositor().BeginFrame();
Element* target = GetDocument().getElementById("target");
EXPECT_GT(250, target->OffsetWidth());
// Then load the font and invalidate layout
font_resource.Complete(ReadAhemWoff2());
GetDocument().GetStyleEngine().InvalidateStyleAndLayoutForFontUpdates();
// <dialog> descendants should be invalidated
EXPECT_EQ(kNoStyleChange, target->GetStyleChangeType());
EXPECT_TRUE(target->GetLayoutObject()->NeedsLayout());
// <dialog> descendants should be re-rendered with the custom font
Compositor().BeginFrame();
EXPECT_EQ(250, target->OffsetWidth());
main_resource.Finish();
}
} // namespace blink
......@@ -884,18 +884,15 @@ void StyleEngine::InvalidateStyleAndLayoutForFontUpdates() {
TRACE_EVENT0("blink", "StyleEngine::InvalidateStyleAndLayoutForFontUpdates");
fonts_need_update_ = false;
Element* root = GetDocument().documentElement();
if (!root)
return;
{
if (Element* root = GetDocument().documentElement()) {
TRACE_EVENT0("blink", "Node::MarkSubtreeNeedsStyleRecalcForFontUpdates");
root->MarkSubtreeNeedsStyleRecalcForFontUpdates();
}
if (LayoutObject* root_object = root->GetLayoutObject()) {
if (LayoutView* layout_view = GetDocument().GetLayoutView()) {
TRACE_EVENT0("blink", "LayoutObject::InvalidateSubtreeForFontUpdates");
root_object->InvalidateSubtreeLayoutForFontUpdates();
layout_view->InvalidateSubtreeLayoutForFontUpdates();
}
}
......
<!doctype html>
<link rel="author" title="Xiaocheng Hu" href="xiaochengh@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-font-loading/#font-face-load">
<link rel="help" href="https://crbug.com/1092411">
<meta name="assert" content="Ensure that content of a modal dialog is re-rendered with loaded web font." />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
#target {
font: 25px/1 custom-font, monospace;
}
</style>
<dialog><span id=target>0123456789</span></dialog>
<script>
document.querySelector('dialog').showModal();
function raf() {
return new Promise(resolve => requestAnimationFrame(resolve));
}
promise_test(async () => {
await raf();
const face = new FontFace('custom-font', 'url(/fonts/Ahem.ttf)');
document.fonts.add(face);
await face.load();
assert_equals(target.offsetWidth, 250);
}, 'Modal dialog content should be re-rendered with loaded web font');
</script>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment