mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-25 17:25:08 +02:00
LibWeb: Preserve non-ASCII characters in canvas text preparation
The whitespace-normalization loop in prepare_text() called
StringBuilder::append() on each code point, which resolves to the
`char` overload and truncates non-ASCII characters. measureText("ó")
therefore returned a width of 0, despite fillText painting the glyph.
Use append_code_point() instead, and add a regression test for both
precomposed and decomposed accented text.
This commit is contained in:
committed by
Andreas Kling
parent
792a8c3a9c
commit
4f54b16315
Notes:
github-actions[bot]
2026-04-25 12:56:50 +00:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/LadybirdBrowser/ladybird/commit/4f54b163151 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/9092
@@ -785,7 +785,7 @@ CanvasRenderingContext2D::PreparedText CanvasRenderingContext2D::prepare_text(Ut
|
||||
// 2. Replace all ASCII whitespace in text with U+0020 SPACE characters.
|
||||
StringBuilder builder { StringBuilder::Mode::UTF16, text.length_in_code_units() };
|
||||
for (auto c : text) {
|
||||
builder.append(Infra::is_ascii_whitespace(c) ? ' ' : c);
|
||||
builder.append_code_point(Infra::is_ascii_whitespace(c) ? ' ' : c);
|
||||
}
|
||||
auto replaced_text = builder.to_utf16_string();
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
precomposed accent has positive width: true
|
||||
precomposed and decomposed accent widths match: true
|
||||
word width includes precomposed accent: true
|
||||
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: "LatoTest";
|
||||
src: url("../../../Assets/Lato-Bold.ttf");
|
||||
}
|
||||
</style>
|
||||
<span style="font-family: LatoTest; position: absolute; visibility: hidden">Kraków</span>
|
||||
<script src="../include.js"></script>
|
||||
<script>
|
||||
promiseTest(async () => {
|
||||
await document.fonts.ready;
|
||||
|
||||
const canvas = document.createElement("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.font = "48px LatoTest";
|
||||
|
||||
const accented = ctx.measureText("ó");
|
||||
const decomposed = ctx.measureText("o\u0301");
|
||||
println(`precomposed accent has positive width: ${accented.width > 0}`);
|
||||
println(`precomposed and decomposed accent widths match: ${Math.abs(accented.width - decomposed.width) < 1}`);
|
||||
|
||||
const text = "Kraków";
|
||||
const metrics = ctx.measureText(text);
|
||||
println(`word width includes precomposed accent: ${metrics.width > ctx.measureText("Krakw").width}`);
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user