Skip to content

SVG <text> does not use fallback fonts for missing glyphs #11031

Description

@kuchikuu

SVG <text> does not use fallback fonts for missing glyphs

Summary

Some characters are rendered as missing-glyph boxes when used inside SVG <text> with a generic font such as serif.

The same character renders correctly as normal HTML text. Explicitly selecting a font that contains the character also makes it render correctly inside SVG.

For example, the treble clef character U+1D11E does not render correctly in this SVG:

Minimal example:

<!doctype html>
<meta charset="utf-8">

<svg xmlns="http://www.w3.org/2000/svg" width="120" height="140">
  <text x="10" y="100" font-family="serif" font-size="86">
    &#x1D11E;
  </text>
</svg>

The same character renders correctly outside SVG:

<!doctype html>
<meta charset="utf-8">

<span style="font-size: 86px; font-family: serif;">&#x1D11E;</span>

It also renders correctly inside SVG when the font is specified explicitly:

<svg xmlns="http://www.w3.org/2000/svg" width="120" height="140">
  <text x="10" y="100" font-family="Noto Music" font-size="86">
    &#x1D11E;
  </text>
</svg>

I reproduced the same missing-glyph behaviour with several other symbols and characters when they require a fallback font.

Steps to reproduce

  1. Save the first HTML example to a file.
  2. Open it in Ladybird.
  3. The treble clef is displayed as a missing-glyph box.
  4. Open the second example with the normal HTML <span>.
  5. The treble clef is displayed correctly.
  6. Change the SVG font-family from serif to Noto Music.
  7. The treble clef is displayed correctly.

Expected behaviour

SVG <text> should use an available fallback font when the selected font does not contain the requested character.

The treble clef should render correctly with font-family="serif" in the same way it does in normal HTML text.

Build information

System: Debian GNU/Linux 13 (trixie)
commit: bf6c4c7

More examples:

Different tests:

<!doctype html>
<meta charset="utf-8">
<title>Ladybird SVG musical symbol fallback test</title>

<style>
  body { font-family: sans-serif; margin: 20px; }
  .test { margin-bottom: 24px; }
  .label { margin-bottom: 6px; font-weight: bold; }
  svg { display: block; width: 760px; height: 120px; border: 1px solid #ccc; }
  text { font-size: 68px; }
</style>

<div class="test">
  <div class="label">HTML reference — serif</div>
  <div style="font: 68px serif;">𝄞 𝄢 𝅝 𝅗𝅥 𝅘𝅥 𝅘𝅥𝅮 ♭ ♮ ♯ ♪ ♫</div>
</div>

<div class="test">
  <div class="label">SVG — no font specified</div>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 120"><text x="15" y="85">𝄞 𝄢 𝅝 𝅗𝅥 𝅘𝅥 𝅘𝅥𝅮 ♭ ♮ ♯ ♪ ♫</text></svg>
</div>

<div class="test">
  <div class="label">SVG — generic serif</div>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 120"><text x="15" y="85" font-family="serif">𝄞 𝄢 𝅝 𝅗𝅥 𝅘𝅥 𝅘𝅥𝅮 ♭ ♮ ♯ ♪ ♫</text></svg>
</div>

<div class="test">
  <div class="label">SVG — missing font, then serif fallback</div>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 120"><text x="15" y="85" font-family="'Definitely Missing Font', serif">𝄞 𝄢 𝅝 𝅗𝅥 𝅘𝅥 𝅘𝅥𝅮 ♭ ♮ ♯ ♪ ♫</text></svg>
</div>

<div class="test">
  <div class="label">SVG — missing font, then Noto Music fallback</div>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 120"><text x="15" y="85" font-family="'Definitely Missing Font', 'Noto Music', serif">𝄞 𝄢 𝅝 𝅗𝅥 𝅘𝅥 𝅘𝅥𝅮 ♭ ♮ ♯ ♪ ♫</text></svg>
</div>

<div class="test">
  <div class="label">SVG — explicit Noto Music</div>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 120"><text x="15" y="85" font-family="Noto Music">𝄞 𝄢 𝅝 𝅗𝅥 𝅘𝅥 𝅘𝅥𝅮 ♭ ♮ ♯ ♪ ♫</text></svg>
</div>

Other symbols:

<!doctype html>
<meta charset="utf-8">
<title>Ladybird SVG font fallback test</title>

<style>
  body { font-family: sans-serif; margin: 20px; }
  .test { margin-bottom: 22px; }
  .label { margin-bottom: 5px; font-weight: bold; }
  svg { display: block; width: 1100px; height: 100px; }
  text { font-size: 56px; }
</style>

<div class="test">
  <div class="label">HTML — generic serif</div>
  <div style="font: 56px serif;">∑ ∫ √ ∞ ≠ ♔ ♕ ✓ ★ ☀ Ω Ж ש م 中 𝔄 𝕭 𝟘 𐐀 𓀀 😀</div>
</div>

<div class="test">
  <div class="label">SVG — no font specified</div>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1100 100"><text x="10" y="68">∑ ∫ √ ∞ ≠ ♔ ♕ ✓ ★ ☀ Ω Ж ש م 中 𝔄 𝕭 𝟘 𐐀 𓀀 😀</text></svg>
</div>

<div class="test">
  <div class="label">SVG — generic serif</div>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1100 100"><text x="10" y="68" font-family="serif">∑ ∫ √ ∞ ≠ ♔ ♕ ✓ ★ ☀ Ω Ж ש م 中 𝔄 𝕭 𝟘 𐐀 𓀀 😀</text></svg>
</div>

<div class="test">
  <div class="label">SVG — missing font, then serif</div>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1100 100"><text x="10" y="68" font-family="'Definitely Missing Font', serif">∑ ∫ √ ∞ ≠ ♔ ♕ ✓ ★ ☀ Ω Ж ש م 中 𝔄 𝕭 𝟘 𐐀 𓀀 😀</text></svg>
</div>

<div class="test">
  <div class="label">SVG — Noto Sans Symbols 2</div>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1100 100"><text x="10" y="68" font-family="'Noto Sans Symbols 2', serif">∑ ∫ √ ∞ ≠ ♔ ♕ ✓ ★ ☀ Ω Ж ש م 中 𝔄 𝕭 𝟘 𐐀 𓀀 😀</text></svg>
</div>

<div class="test">
  <div class="label">SVG — Noto Sans Math</div>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1100 100"><text x="10" y="68" font-family="'Noto Sans Math', serif">∑ ∫ √ ∞ ≠ ♔ ♕ ✓ ★ ☀ Ω Ж ש م 中 𝔄 𝕭 𝟘 𐐀 𓀀 😀</text></svg>
</div>

<div class="test">
  <div class="label">SVG — Noto Color Emoji</div>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1100 100"><text x="10" y="68" font-family="'Noto Color Emoji', serif">☀ ★ ✓ 😀 😎 🚚 🎹 🦆</text></svg>
</div>
Image Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions