Skip to content

Conversation

@kjarosh
Copy link
Member

@kjarosh kjarosh commented Nov 16, 2025

Implement device fonts support on web using canvas font renderer. Device fonts are rendered on canvas and then used as a bitmap in Ruffle.

This PR is divided roughly into 2 parts:

  1. support bitmap glyphs and glyphs rendered externally in core,
  2. implement canvas font renderer in web.

This solves the current issue of missing device fonts on web—Ruffle currently uses the default, embedded Noto Sans font and allows providing custom fonts as device fonts. When the "canvas" font renderer is enabled, glyphs are rendered on an offscreen canvas by the device, and stored in a bitmap.

This is currently experimental, as some things may not work properly or are missing, such as:

  1. no hit test implemented yet,
  2. each glyph is stored in a separate bitmap instead of being stored in an atlas,
  3. each glyph is rendered with 64px height and then scaled down/up as a bitmap instead of being rendered with different resolutions.

This is being put behind a setting deviceFontRenderer with value canvas (instead of the default embedded).

TODO:

  1. add a test for the canvas font renderer would be nice
  2. check why OFFICE CRAZY | the game doesn't render any letter. #10073 doesn't work with this.

Values such as scale, ascent, descent, leading belong to the same
category of font metrics, and conceptually it makes sense to represent
them as one object, as they cannot be separated.
GlyphRef can both reference a &Glyph directly or a Ref<Glyph>, which is
required to abstract away glyphs generated dynamically and cached.
This is useful for e.g. rendering text on web using canvas.
This patch adds support for bitmap glyphs in addition to shape-based
glyphs. Bitmap glyphs are useful for supporting device text rendered by
the OS.
External font renderer provides/renders glyphs on demand, when core
requests them. The logic of rendering glyphs can be external to core
and is abstracted away so that frontends can provide their font
renderers for device text.
CanvasFontRenderer is an implementation of a font renderer that can
render glyphs using an offscreen canvas.  This allows Ruffle to support
device text properly on web.
Using this config option the user can select how device fonts should be
rendered.
When DeviceFontRenderer::Canvas is set, no fonts will be set up, and
instead CanvasFontRenderer will be used to render all device fonts.
@kjarosh kjarosh added A-web Area: Web & Extensions text Issues relating to text rendering/input T-compat Type: Compatibility with Flash Player device-fonts Issues related to device fonts. They are usually very system-dependent. newsworthy labels Nov 16, 2025
fn to_font_str(italic: bool, bold: bool, size: f64, font_family: &str) -> String {
let italic = if italic { "italic " } else { "" };
let bold = if bold { "bold " } else { "" };
format!("{italic}{bold}{size}px {font_family}")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might missing quotes around the family?

@danielhjacobs
Copy link
Contributor

danielhjacobs commented Nov 20, 2025

Is it possible to switch to using the current text rendering if for the browser in use typeof OffscreenCanvas === "undefined", even if the config's deviceFontRenderer is "canvas"? Since we say we support Firefox 94 or higher and Safari 14.1 or higher but per https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas#browser_compatibility this is Firefox 105, Safari 16.4.

@kjarosh
Copy link
Member Author

kjarosh commented Nov 20, 2025

I think we can fall back to a regular canvas then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-web Area: Web & Extensions device-fonts Issues related to device fonts. They are usually very system-dependent. newsworthy T-compat Type: Compatibility with Flash Player text Issues relating to text rendering/input

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants