Unicode text layouting and rendering engine in Terra with a C API.
Written by Cosmin Apreutesei. Public Domain.
A pure-Lua prototype of this library is at github.com/luapower/tr.
Discuss at luapower.com/forum or at github.com/luapower/terra-tr/issues.
Leverages harfbuzz, freetype, fribidi and libunibreak for text shaping,
glyph rasterization, bidi reordering and line breaking respectively.
Scaling and blitting a raster image onto another is out of the scope of
the library. A module for doing that with `cairo` is included separately.
NOTE: This is the implementation module. In here, invalid input data is
undefined behavior and changing layout properties does not keep the
internal state consistent. Use `tr_api` instead which takes care of that.
Processing stages from rich text description to pixels on screen:
* itemization : split text into an array of segments (or segs).
* shaping : shape segments into arrays of glyphs (called glyph runs).
* line-wrapping : word-wrap segments and group them into an array of lines.
* bidi-reordering : re-order mixed-direction segments on each line.
* line-spacing : compute each line's `y` based on the heights of its segments.
* aligning : align lines horizontally and vertically inside a box.
* clipping : mark which lines and segments as visible inside a box.
* rasterization : convert glyph outlines into bitmaps that are cached.
* painting : draw the visible text plus any selections and carets.
The API for driving this process is:
tr_itemize.t shape() itemization and shaping.
tr_wrap.t wrap() line-wrapping.
tr_align.t spaceout() line-spacing.
tr_align.t align() justification and aligning.
tr_clip.t clip() clipping.
tr_paint.t paint() painting, with on-demand rasterization.
The renderer object keeps four LRU caches: one for glyph runs, one for
glyph images, one for memory fonts and one for memory-mapped fonts.
Shaping looks-into and adds-to the glyph run cache. Rasterization
looks-into and adds-to the glyph image cache. Fonts are loaded and cached
when the span's font_id is set in tr_api. Glyph runs and fonts are
ref-counted in the cache so while the layout is alive, even if the cache
size limit is reached, segs won't lose their glyph runs and fonts will
remain available for reshaping and rasterization.
Also, there's two levels of rasterization: for glyph images and for entire
glyph runs. With subpixel resolution, more than one image might end up
being created for each subpixel offset encountered, which is why
rasterization is done on-demand by painting.
See the source code for more info.