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.
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):
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
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
newImage(thus requiring a name change), and with added shaping methods:getWidth,getVerticesetc. 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.