.. | ||
docs | ||
atlas.odin | ||
draw.odin | ||
LICENSE.md | ||
LRU.odin | ||
mappings.odin | ||
misc.odin | ||
parser.odin | ||
Readme.md | ||
shaped_text.odin | ||
shaper.odin | ||
VEFontCache.odin |
VE Font Cache : Odin Port
This is a port of the library based on fork
Its original purpose was for use in game engines, however its rendeirng quality and performance is more than adequate for many other applications.
See: docs/Readme.md for the library's interface
Changes from orignal
- Font Parser & Glyph shaper are abstracted to their own interface
- Font face parser info encapsulated in parser_info struct.
- ve_fontcache_loadfile not ported (ust use core:os or os2, then call load_font)
- Macro defines have been coverted (mostly) to runtime parameters
- Support for hot_reloading
TODOs
Thirdparty support:
- Setup freetype, harfbuzz, depedency management within the library
Documentation:
- Pureref outline of draw_text exectuion
- Markdown general documentation
Content:
- Port over the original demo utilizing sokol libraries instead
- Provide a sokol_gfx backend package
Additional Features:
- Support for freetype
- Support for harfbuzz
- Ability to set a draw transform, viewport and projection
- By default the library's position is in unsigned normalized render space
- Could implement a similar design to sokol_gp's interface
- Allow curve_quality to be set on a per-font basis
Optimization:
- Look into setting up multi-threading by giving each thread a context
- There is a heavy performance bottleneck in iterating the text/shape/glyphs on the cpu (single-thread) vs the actual rendering
- draw_text can provide in the context a job list per thread for the user to thenk hookup to their own threading solution to handle.
- Context would need to be segregated into staged data structures for each thread to utilize
- Each should have their own?
- draw_list
- draw_layer
- atlas.next_idx
- glyph_draw_buffer
- shape_cache
- This would need to converge to the singlar draw_list on a per layer basis (then user reqeusts a draw_list layer there could a yield to wait for the jobs to finish); if the interface expects the user to issue the commands single-threaded unless, we just assume the user is going to feed the gpu the commands & data through separate threads as well (not ideal ux).
- Each should have their own?
- How the contexts are given jobs should be left up to the user (can recommend a screen quadrant based approach in demo examples)
Failed Attempts:
- Attempted to chunk the text to more granular 'shapes' from
draw_list
before doing the actual call todraw_text_shape
. This lead to a larger performance cost due to the additional iteration across the text string. - Attempted to cache the shape draw_list for future calls. Led to larger performance cost due to additional iteration in the
merge_draw_list
.- The shapes glyphs must still be traversed to identify if the glyph is cached. This arguably could be handled in
shape_text_uncached
, however that would require a significan't amount of refactoring to identify... (and would be more unergonomic when shapers libs are processing the text)
- The shapes glyphs must still be traversed to identify if the glyph is cached. This arguably could be handled in