Skip to content

Decouple text shaping from glyph rendering to support custom shapers/renderers #994

Description

@jamesthomasgriffin

Problem

The Rasterizer and Font class have tangled responsibilities.

Proposal

Replace them with FontMetrics and GlyphAtlas which cleanly separate font metrics and shaping from rendering. FontMetrics does not know anything about msdfs, or GPU buffers; and GlyphAtlas does not know anything about UTF8 or fonts.

The Font class could live on as a composite of these two, providing partial backwards compatibility.

FontMetrics loads the font, and performs font shaping. I.e. from a UTF8 string, it generates a list of vertices (4 for each glyph in a documented order) alongside a list of glyph ids). It should also provide curve data for individual glyphs.

GlyphAtlas should a) take the curve data for a given id and fill the atlas accordingly, and b) take lists of vertices and glyph ids and get them rendered.

So a Lua implementation of a text drawing function could look like (ignoring world placement and caching of local buffers etc):

local function drawText(pass, str, fontMetrics, glyphAtlas, wrap)
    local vertices, ids = fontMetrics:getVertices(str, wrap)
    glyphAtlas:loadGlyphs(ids, fontMetrics)  -- fontMetrics is needed to provide curves for any unseen id
    glyphAtlas:draw(pass, vertices, ids)
end

local font = newFont("my_font.ttf", 32) -- scales font height to 32
local atlas = newMSDFAtlas(64) -- glyph raster height is 64

function draw(pass)
    drawText(pass, "Hello world", font, atlas, 1000)
end

This creates an opening for users, they can generate or edit their own vertices, and they can provide their own curves to the GlyphAtlas.

Some applications

  • use an alternative heavyweight font shaping library that replaces FontMetrics to get the best support for the most advanced font shaping,
  • load SVGs, with curve data coming from path attributes and shaping coming from the SVG tree,
  • edit the vertex buffer produced by FontMetrics to animate individual letters/words for emphasis, or change the colours to support animated linear gradients,
  • add font fallbacks, or the ability to add vector icons into the existing GlyphAtlas.

There is also the option to provide multiple implementations of GlyphAtlas, one could work using MSDFs, another using SLUG (or Robin maybe?), or in the orthographic, fixed size case, a basic rasterizer. All can share the same interface.

Notes

  • the interface of FontMetrics would be nearly the same as Rasterizer, but without newImage (thus requiring a name change), and with added shaping methods: getWidth, getVertices etc. So migration shouldn't be too hard, though there is the scaling ambiguity between the metric methods provided by Rasterizer and Font now they are combined. If Font lived on then it could maintain its interface.
  • the interface of GlyphAtlas would be new, but quite simple, perhaps just load and draw methods.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions