C types
86 types, extracted from the source at build time so this list cannot drift from it.
Bidi
The Unicode bidirectional algorithm, for text that mixes left-to-right and right-to-left scripts. Even embedding levels run left to right, odd levels right to left.
daegun_bidi_runstypedef struct daegun_bidi_runs daegun_bidi_runs;A set of shaped runs covering mixed-direction text, in the order they should be drawn.
Produced by
daegun_font_shape_bidianddaegun_font_shape_bidi_with. Free it withdaegun_bidi_runs_free. The runs inside are borrowed – never pass one todaegun_run_free.
Borrowed views
daegun_bytestypedef struct { const uint8_t *data; size_t len; } daegun_bytes;A run of bytes daegun owns, lent to you. Valid until the handle it came from is freed.
daegun_strtypedef struct { const char *data; size_t len; } daegun_str;A UTF-8 string daegun owns, lent to you. NUL-terminated and length-carrying both. An interior NUL – which a font's name table may contain – is replaced with U+FFFD, so strlen cannot mislead you and
lenstill describes the whole string.
Color
Fonts that carry their own color: COLR layer graphs, CPAL palettes and bitmap strikes. A color glyph renders to RGBA pixels rather than to single-channel coverage.
daegun_bandtypedef struct { uint32_t first_curve; uint32_t curve_count; } daegun_band;One horizontal or vertical slice of a glyph, naming a run in the band-curve index.
daegun_batchtypedef struct daegun_batch daegun_batch;A GPU batch: the curves, bands and hulls waiting to be uploaded.
Created with
daegun_batch_newand filled by the GPU glyph calls. Free it withdaegun_batch_free. One batch serves every size on screen, because a slot is keyed on glyph and axes rather than on a pixel size.daegun_color_slottypedef struct { daegun_glyph_slot slot; float tint[4]; } daegun_color_slot;One flat-colored shape of a color glyph: the curves, and the shape's own tint in the 0..1 straight-alpha form daegun_glyph_instance.tint takes. Draw them in the order they came back – they paint back to front and the shader does no depth testing.
daegun_color_slotstypedef struct daegun_color_slots daegun_color_slots;The per-layer GPU slots of a color glyph, each with its own tint.
Produced by
daegun_font_gpu_color_glyph. Free it withdaegun_color_slots_free. Draw them in the order returned – back to front, since the shader does no depth testing.daegun_colr_layertypedef struct { uint16_t gid; uint8_t r, g, b, a; bool is_foreground; } daegun_colr_layer;One COLR v0 layer. is_foreground means the layer takes YOUR text color rather than one from the palette, and the four channels are then meaningless.
daegun_colr_layerstypedef struct daegun_colr_layers daegun_colr_layers;The COLR v0 layers of a glyph: a stack of ordinary glyphs, each with a palette color.
Produced by
daegun_font_colr_layersanddaegun_font_colr_layers_for_palette. Free it withdaegun_colr_layers_free. Read them withdaegun_colr_layers_dataand draw them in that order, back to front.daegun_curve_pointtypedef struct { float x; float y; } daegun_curve_point;One point of a quadratic, in em space.
daegun_drawntypedef struct daegun_drawn daegun_drawn;The result of drawing one glyph: which path it took, and what it produced.
Produced by
daegun_font_draw_glyph. Free it withdaegun_drawn_free. Askdaegun_drawn_kindbefore reading a bitmap, slot or scene out of it.daegun_glyph_bitmaptypedef struct daegun_glyph_bitmap daegun_glyph_bitmap;An embedded bitmap strike from a color font, as PNG.
Produced by
daegun_font_glyph_bitmap. Free it withdaegun_glyph_bitmap_free. Distinct fromdaegun_bitmap, which is coverage daegun rasterized itself.daegun_glyph_slottypedef struct { uint32_t band_base; uint32_t h_bands; uint32_t v_bands; uint32_t hull_base; float box_min[2]; float box_max[2]; } daegun_glyph_slot;Where a glyph's geometry landed in a batch.
daegun_hull_vertextypedef struct { float pos[2]; float dilate[4]; } daegun_hull_vertex;One vertex of the polygon actually drawn, with the per-corner dilation the shader needs.
daegun_painttypedef struct daegun_paint daegun_paint;A COLR v1 paint graph: the tree of fills, gradients, transforms and blends that draws a color glyph.
Produced by
daegun_font_colr_v1_paint. Free it withdaegun_paint_free. Read the flattened node array withdaegun_paint_nodes; children are named by index, so nothing needs chasing.daegun_paint_nodetypedef struct { int32_t kind; /* DAEGUN_PAINT_* */ uint32_t child_start; uint32_t child_count; uint32_t stops_start; uint32_t stops_count; uint16_t glyph_id; uint8_t is_foreground; uint8_t r, g, b, alpha; uint8_t extend; uint8_t composite_mode; uint8_t has_center; double numbers[8]; } daegun_paint_node;One node of a COLR v1 paint graph: an operation, its parameters, and the indices of its children.
COLR v1 describes a color glyph as a tree – solid fills, linear and radial gradients, transforms, clips and blends.
daegun_paint_nodesreturns that tree flattened into an array, with nodes referring to each other by index rather than by pointer, so it can be walked without chasing allocations.daegun_palette_infotypedef struct { uint16_t index; bool light_safe; bool dark_safe; bool has_name_id; uint16_t name_id; } daegun_palette_info;light_safe and dark_safe are both false on a COLR v0 face, which states no flags – an absence of information rather than a claim that the palette suits neither.
daegun_palettestypedef struct daegun_palettes daegun_palettes;The CPAL palettes a font carries, with the flags saying which background each suits.
Produced by
daegun_font_palette_info. Free it withdaegun_palettes_free. Use it to honour a font's dark-mode palette rather than always taking palette 0.daegun_policytypedef struct { int32_t prefer; /* DAEGUN_PREFER_* */ bool strict; bool has_cpu_below_ppem; float cpu_below_ppem; bool avoid_software_gpu; } daegun_policy;Zeroing this is the default.
daegun_scenetypedef struct daegun_scene daegun_scene;A rendered color glyph: straight-alpha RGBA8 pixels, ready to blit.
Produced by
daegun_font_render_colr_glyphand bydaegun_scene_builder_render. Free it withdaegun_scene_free. Read it withdaegun_scene_rgba, which also reports how many paint operations were skipped – non-zero means the result is incomplete.
D3D11 backend
Direct3D 11 on Windows. The same 19 functions every backend has, opened by name at run time.
daegun_d3d11_geometrytypedef struct daegun_d3d11_geometry daegun_d3d11_geometry;An opaque Direct3D 11 geometry handle.
Glyph curves uploaded to the Direct3D 11 device. Build a batch, create geometry from it once, then draw from that geometry many times – rebuilding it per frame throws away the point of the GPU path. Free it before the renderer.
daegun_d3d11_renderertypedef struct daegun_d3d11_renderer daegun_d3d11_renderer;An opaque Direct3D 11 renderer handle.
The Direct3D 11 device daegun draws through. Created with
_renderer_new, which answersDAEGUN_UNSUPPORTEDwhere the platform is absent rather than failing to load. Free it last, after every target and geometry made from it.daegun_d3d11_targettypedef struct daegun_d3d11_target daegun_d3d11_target;An opaque Direct3D 11 target handle.
A Direct3D 11 render target: the pixels drawn into. Read them back with
_target_pixelsor_read_pixels, and free it before the renderer it came from.
D3D12 backend
Direct3D 12 on Windows. The same 19 functions every backend has, opened by name at run time.
daegun_d3d12_geometrytypedef struct daegun_d3d12_geometry daegun_d3d12_geometry;An opaque Direct3D 12 geometry handle.
Glyph curves uploaded to the Direct3D 12 device. Build a batch, create geometry from it once, then draw from that geometry many times – rebuilding it per frame throws away the point of the GPU path. Free it before the renderer.
daegun_d3d12_renderertypedef struct daegun_d3d12_renderer daegun_d3d12_renderer;An opaque Direct3D 12 renderer handle.
The Direct3D 12 device daegun draws through. Created with
_renderer_new, which answersDAEGUN_UNSUPPORTEDwhere the platform is absent rather than failing to load. Free it last, after every target and geometry made from it.daegun_d3d12_targettypedef struct daegun_d3d12_target daegun_d3d12_target;An opaque Direct3D 12 target handle.
A Direct3D 12 render target: the pixels drawn into. Read them back with
_target_pixelsor_read_pixels, and free it before the renderer it came from.
Glyphs
Going from characters to glyph ids, and asking about one glyph. A glyph id indexes this font and means something different in any other.
daegun_u32_listtypedef struct daegun_u32_list daegun_u32_list;An owned list of 32-bit values, usually code points or byte offsets.
Returned by coverage and segmentation calls. Read the elements with
daegun_u32_list_data, which borrows – the pointer dies with the list – and free it withdaegun_u32_list_free.
Handles
daegun_fonttypedef struct daegun_font daegun_font;Opaque. You never see the layout, so it is free to change without breaking you.
Hinting
Grid fitting, which nudges outlines onto pixel boundaries so stems stay crisp at small sizes.
daegun_cff_hintstypedef struct daegun_cff_hints daegun_cff_hints;The stem positions a CFF glyph declares.
Produced by
daegun_font_cff_hints; absent for TrueType outlines, which hint through instructions instead. Free it withdaegun_cff_hints_free.daegun_hinted_outlinetypedef struct daegun_hinted_outline daegun_hinted_outline;A glyph outline after grid fitting, in pixel space at one size.
Produced by
daegun_font_hinted_glyph. Free it withdaegun_hinted_outline_free. Replay it onto a pen withdaegun_hinted_outline_draw.
Justification
Fitting a line to a width using what the font offers – elongating Arabic kashida, substituting alternate forms – rather than only stretching the spaces.
daegun_jstf_modstypedef struct daegun_jstf_mods daegun_jstf_mods;One set of justification modifications a font offers for a script.
Names which of the font's own adjustments to apply – kashida elongation, alternate forms – and is what
daegun_font_shape_justifiedtakes. It comes out ofdaegun_font_justification_priorities, which lists them in the order the font wants them tried, and is owned by those priorities rather than freed on its own.daegun_jstf_prioritiestypedef struct daegun_jstf_priorities daegun_jstf_priorities;The ordered adjustments a font suggests for justifying a script.
Produced by
daegun_font_justification_priorities. Free it withdaegun_jstf_priorities_free.daegun_justifiedtypedef struct daegun_justified daegun_justified;The result of fitting a line to a width: the shaped run, the width reached, and whether it fell short.
Produced by
daegun_font_justify. Free it withdaegun_justified_free. The run inside is borrowed – read it withdaegun_justified_run, and never pass it todaegun_run_free.
Layout
Breaking and positioning a whole paragraph, plus the Unicode segmentation the process needs. Sizes in and out are on the 1000-unit em.
daegun_bidi_paragraphtypedef struct daegun_bidi_paragraph daegun_bidi_paragraph;A resolved paragraph, kept so one line at a time can be asked about – rebuilding it per line would redo the whole resolution each time.
daegun_layouttypedef struct daegun_layout daegun_layout;A laid-out paragraph: its lines, and the positioned runs within them.
Produced by
daegun_font_layout. Free it withdaegun_layout_free. All positions are on the 1000-unit em.daegun_layout_optionstypedef struct { /* The measure, in the SAME 1000-upm units daegun_run_advances reports – not pixels. A value * smaller than one glyph does not wrap harder, it simply cannot be met. * * A line MAY exceed it when a single unbreakable run does; daegun_layout_info's inline_size is * the widest line, not a promise about this number. */ double max_inline_size; int32_t align; /* DAEGUN_ALIGN_* */ int32_t writing_mode; /* DAEGUN_WRITING_* */ int32_t text_orientation; /* DAEGUN_ORIENTATION_* */ int32_t base_direction; /* 0 ltr, 1 rtl, -1 decide */ const char *language; /* may be NULL */ bool has_line_height; double line_height; int32_t strategy; /* DAEGUN_BREAK_* */ bool has_max_lines; size_t max_lines; } daegun_layout_options;The measure, in the SAME 1000-upm units daegun_run_advances reports – not pixels. A value smaller than one glyph does not wrap harder, it simply cannot be met. A line MAY exceed it when a single unbreakable run does; daegun_layout_info's inline_size is the widest line, not a promise about this number.
daegun_visual_runstypedef struct daegun_visual_runs daegun_visual_runs;The single-direction runs one line splits into, in the order they should be drawn.
Produced by
daegun_text_line_visual_runs. Free it withdaegun_visual_runs_free. Walk them withdaegun_visual_runs_countanddaegun_visual_runs_at; the character indices you get back are borrowed.
Metal backend
Metal on Apple platforms. Every backend exposes the same 19 functions with the same semantics, so code written against one ports to another by changing the prefix. Available only where the platform is; a machine without it answers DAEGUN_UNSUPPORTED rather than failing to load.
daegun_metal_geometrytypedef struct daegun_metal_geometry daegun_metal_geometry;An opaque Metal geometry handle.
Glyph curves uploaded to the Metal device. Build a batch, create geometry from it once, then draw from that geometry many times – rebuilding it per frame throws away the point of the GPU path. Free it before the renderer.
daegun_metal_renderertypedef struct daegun_metal_renderer daegun_metal_renderer;An opaque Metal renderer handle.
The Metal device daegun draws through. Created with
_renderer_new, which answersDAEGUN_UNSUPPORTEDwhere the platform is absent rather than failing to load. Free it last, after every target and geometry made from it.daegun_metal_targettypedef struct daegun_metal_target daegun_metal_target;An opaque Metal target handle.
A Metal render target: the pixels drawn into. Read them back with
_target_pixelsor_read_pixels, and free it before the renderer it came from.
Options
Filling an options struct with its defaults. Always call the _default function rather than zeroing the struct yourself: zero is a meaningful value for several fields, and the defaults are not all zero.
daegun_raster_optionstypedef struct { int32_t layout; /* DAEGUN_LAYOUT_* */ int32_t hinting; /* DAEGUN_HINT_* */ int32_t has_gamma; float gamma; /* coverage^(1/gamma), applied as coverage becomes a byte */ int32_t has_transform; float transform[6]; /* [a, b, c, d, dx, dy] in font units, before rasterizing */ int32_t has_stroke; float stroke_width; /* font units, so it scales with the size as the glyph does */ int32_t stroke_join; /* DAEGUN_JOIN_* */ float stroke_miter_limit; /* read only when stroke_join is DAEGUN_JOIN_MITER */ int32_t stroke_cap; /* DAEGUN_CAP_* */ int32_t has_embolden; float embolden; /* extra stem width in font units. THIS CHANGES THE ADVANCE. */ int32_t has_oblique; float oblique; /* tangent of the angle from vertical; positive leans right */ } daegun_raster_options;What you fill in and hand to anything that rasterizes. The has_ flags are how C says Option. Zeroing the struct gives the Rust default – grayscale, no gamma, transform, hinting, stroke or synthesis – so memset(&o, 0, sizeof o) is a correct start; daegun_raster_options_default() keeps working if a default ever stops being zero.
Outlines
Walking a glyph's outline through callbacks, and warming the outline cache ahead of time. Outline points are in font units, not on the 1000-unit em – divide by daegun_font_upm to get ems.
daegun_pentypedef struct { void (*move_to)(void *user, float x, float y); void (*line_to)(void *user, float x, float y); void (*quad_to)(void *user, float cx, float cy, float x, float y); void (*curve_to)(void *user, float c1x, float c1y, float c2x, float c2y, float x, float y); void (*close)(void *user); void *user; } daegun_pen;What you hand daegun to receive an outline. The first thing that crosses INTO the library.
useris passed back untouched to every callback; daegun never reads it. Any callback may be NULL, and that event is then skipped – so a caller wanting only the on-curve points supplies three of the five. Your callbacks MUST NOT unwind: a C++ exception or a longjmp through Rust frames is undefined behavior and nothing here can prevent it. You MAY call back into daegun from inside them, including on the same font – no lock is held while your callback runs.
Owned results
daegun returns lists and blobs behind opaque handles rather than as raw pointers, so that ownership is never in doubt. Each has a _data accessor that borrows – the pointer stays valid only until the handle is freed – and a _free that releases it. Copy the elements out if you need them to outlive the handle.
daegun_axistypedef struct { const char *tag; double value; } daegun_axis;One axis of a variable font, as you state it. The input six calls share.
tagis a NUL-terminated four-character tag such as "wght". A tag that is not valid UTF-8 is skipped rather than failing the call, because a location is a request and an axis the font does not have is ignored anyway.daegun_blobtypedef struct daegun_blob daegun_blob;a run of bytes: a font file, a bitmap
daegun_f64_listtypedef struct daegun_f64_list daegun_f64_list;An owned list of doubles on the 1000-unit em.
Returned by advance, caret and ligature-caret calls. Read the elements with
daegun_f64_list_data, which borrows – the pointer dies with the list – and free it withdaegun_f64_list_free.daegun_glyph_valuetypedef struct { uint16_t glyph; uint16_t value; } daegun_glyph_value;A glyph paired with what a table maps it to. One list of pairs rather than two parallel lists, which is the opposite of what the optional results below do. The difference: there the halves answer different questions and a caller reads one without the other, here neither half means anything alone.
daegun_glyph_value_listtypedef struct daegun_glyph_value_list daegun_glyph_value_list;An owned list of glyph and value pairs.
Returned by calls that read a per-glyph table. Read the elements with
daegun_glyph_value_list_data, which borrows – the pointer dies with the list – and free it withdaegun_glyph_value_list_free.daegun_i32_listtypedef struct daegun_i32_list daegun_i32_list;An owned list of signed 32-bit values.
Returned by calls reporting whole font units. Read the elements with
daegun_i32_list_data, which borrows – the pointer dies with the list – and free it withdaegun_i32_list_free.daegun_str_listtypedef struct daegun_str_list daegun_str_list;An owned list of strings.
Returned by the tag inventory and
STATcalls. Read the elements withdaegun_str_list_data, which borrows – the pointer dies with the list – and free it withdaegun_str_list_free.daegun_texttypedef struct daegun_text daegun_text;one owned string
daegun_u16_listtypedef struct daegun_u16_list daegun_u16_list;An owned list of 16-bit values, usually glyph ids.
Returned by glyph closure and justification calls. Read the elements with
daegun_u16_list_data, which borrows – the pointer dies with the list – and free it withdaegun_u16_list_free.daegun_usize_listtypedef struct daegun_usize_list daegun_usize_list;An owned list of sizes and offsets.
Returned by table parsing calls such as
daegun_parse_loca. Read the elements withdaegun_usize_list_data, which borrows – the pointer dies with the list – and free it withdaegun_usize_list_free.
Paths and stroking
Building a path by hand and stroking it. daegun_path * is an owned handle: create it, add verbs, use it, free it.
daegun_pathtypedef struct daegun_path daegun_path;A path: geometry as a value rather than a stream of pen calls. Built by driving it – daegun_path_move_to and friends are the same five calls a daegun_pen carries, because on the Rust side a path *is* a pen. There is no _finish: a path is readable and strokeable at any point, and may be extended afterwards.
daegun_scene_buildertypedef struct daegun_scene_builder daegun_scene_builder;A builder holds paths and the fills over them. Push each path once, keep the id it hands back, and fill it as many times as you like at different transforms – which is how one glyph outline serves every place it appears. Render turns the whole thing into a daegun_scene you read with daegun_scene_rgba above. The scene is authored y-up. Render applies
[s, 0, 0, -s, 0, 0]withs = px / upem, so that scale is yours to choose: px = 2, upem = 1 draws a layout expressed in CSS pixels at 2x.daegun_stroke_styletypedef struct { float width; int32_t cap; /* DAEGUN_CAP_* */ int32_t join; /* DAEGUN_JOIN_* */ float miter_limit; } daegun_stroke_style;How a path is stroked. The same fields daegun_raster_options carries, standalone so a path can be stroked without a rasterizer.
miter_limitis read only whenjoinis DAEGUN_JOIN_MITER.
Rasterizing
Turning a glyph into pixels. The result is coverage – one byte per pixel saying how much of it the glyph covers – which you tint yourself. It is a mask, not a color.
daegun_bitmaptypedef struct daegun_bitmap daegun_bitmap;A rasterized glyph: coverage pixels plus the metrics placing them.
Produced by the rasterizing calls. Free it with
daegun_bitmap_free. The pixels are a mask, not a color – one byte per pixel saying how much of it the glyph covers.daegun_metricstypedef struct { int32_t xmin; int32_t ymin; size_t width; size_t height; float advance_width; float advance_height; float bounds_xmin; float bounds_ymin; float bounds_width; float bounds_height; } daegun_metrics;width and height are the bitmap's, in pixels. xmin and ymin place its bottom-left corner relative to the pen. The bounds_ fields are the em-space box the pixels came from, which a caller compositing at sub-pixel offsets needs and cannot recover from the integers.
Raw tables and font building
The font's tables as bytes, and assembling a font file from tables of your own. For anything daegun does not model.
daegun_table_maptypedef struct daegun_table_map daegun_table_map;A tag-to-bytes map daegun owns: what instancing produces, and what building an sfnt takes. Writable, because the Rust API's build_font takes any map – so a caller can instance a font, drop a table, patch another, and build the result. A read-only view would translate the type and lose the point of it.
Reading a table by hand
Bounds-checked big-endian readers and writers. OpenType stores everything big-endian, and these do the byte order and the range check together, so a truncated table produces a refusal rather than a read past the end.
daegun_aat_entrytypedef struct { uint16_t new_state; uint16_t flags; /* The two type-specific words. Rearrangement uses neither, ligature only the first. */ uint16_t word1; uint16_t word2; } daegun_aat_entry;The two type-specific words. Rearrangement uses neither, ligature only the first.
daegun_aat_lookuptypedef struct daegun_aat_lookup daegun_aat_lookup;An AAT lookup. All six published formats sit behind one _value, so there is one handle.
daegun_aat_state_tabletypedef struct daegun_aat_state_table daegun_aat_state_table;A morx state machine. The 32-bit form, whose newState is a state index.
daegun_ankrtypedef struct daegun_ankr daegun_ankr;The ankr table: anchor points a morx machine attaches marks to.
Shaping
Turning a string into positioned glyphs using the font's own rules. The resulting daegun_run * holds glyphs, advances and offsets in parallel arrays of the same length, borrowed from the run until it is freed.
daegun_featuretypedef struct { const char *tag; uint32_t value; } daegun_feature;One OpenType feature you are turning on, off, or selecting an alternate of.
daegun_runtypedef struct daegun_run daegun_run;A shaped run: glyphs, advances, offsets and clusters, in parallel arrays.
Produced by the shaping calls. Free it with
daegun_run_free. Every array you read from it is borrowed and dies with the run, so copy anything you need to keep.daegun_shape_optionstypedef struct { int32_t cluster_level; /* DAEGUN_CLUSTER_* */ int32_t ignorables; /* DAEGUN_IGNORABLES_* */ const char *before; /* text preceding this run, for context. May be NULL. */ const char *after; /* text following it. May be NULL. */ bool beginning_of_text; bool has_point_size; double point_size; const daegun_feature *features; size_t features_len; const char *script; /* NULL to work it out */ const char *language; /* may be NULL */ bool report_unsafe_to_concat; bool report_tatweel_positions; bool suppress_dotted_circle; bool has_invisible_glyph; uint16_t invisible_glyph; } daegun_shape_options;Everything the shaper can be told. Zeroing it is the default, as with daegun_raster_options.
Subsetting
Cutting a font down to the glyphs a page actually uses. Subsetting by text is the call to reach for, because it shapes first and so keeps the glyphs that ligatures and joining actually produced.
daegun_math_constructiontypedef struct daegun_math_construction daegun_math_construction;How a symbol grows: larger variants, and a recipe for assembling one from repeating pieces.
Produced by
daegun_font_math_glyph_variants. Free it withdaegun_math_construction_free.daegun_stattypedef struct daegun_stat daegun_stat;An owned handle over the
STATtable, which describes how this font sits within its wider family.Produced by
daegun_font_stat_info. Free it withdaegun_stat_free.daegun_subsettypedef struct daegun_subset daegun_subset;A subset font: the cut-down file, and the map from old glyph ids to new.
Produced by
daegun_font_subsetanddaegun_font_subset_text. Free it withdaegun_subset_free. The TTF bytes are borrowed, so write them out before freeing.
The atlas packer, and rules
A shelf packer for building glyph atlases, plus small predicates over the enums this API uses.
daegun_axis_valuetypedef struct { uint16_t axis_index; double value; } daegun_axis_value;One (axis, value) pair of a COMBO.
daegun_recttypedef struct { size_t x; size_t y; size_t w; size_t h; } daegun_rect;Where a glyph landed in an atlas.
daegun_shelf_packertypedef struct daegun_shelf_packer daegun_shelf_packer;A shelf packer for an atlas of a given size: the same one daegun's own glyph cache uses. Rasterizing gives you pixels and a size; putting a thousand of them into one texture is a packing problem, and this is the solved version of it.
daegun_stat_valuetypedef struct { int32_t kind; /* DAEGUN_STAT_* */ uint16_t axis_index; /* meaningless for COMBO, which spans axes */ uint8_t elidable; uint8_t has_name; /* whether daegun_stat_value_name will answer */ double value; /* SINGLE's value, RANGE's nominal, LINKED's value; 0 for COMBO */ double min; /* RANGE only */ double max; /* RANGE only */ double linked_value; /* LINKED only */ uint32_t combo_start; /* COMBO only: where its pairs start in daegun_stat_combo_values */ uint32_t combo_count; } daegun_stat_value;One STAT axis value, with the four variants flattened into one shape – the same choice the COLR paint graph made, since C has no sum type and four parallel lists would have to be correlated by index.
Variation data
The machinery underneath variable fonts: item variation stores, delta set index maps, and feature variations. Reach for these only when implementing variation behavior yourself.
daegun_delta_set_index_maptypedef struct daegun_delta_set_index_map daegun_delta_set_index_map;A DeltaSetIndexMap: the indirection from an item to a store's (outer, inner) pair.
daegun_device_profiletypedef struct daegun_device_profile daegun_device_profile;What a device is, and what it calls itself. Every backend's _renderer_profile produces one, and daegun_device_profile_new builds one without a device at all – for a caller that opened its own, or that is deciding before opening any.
daegun_feature_variationstypedef struct daegun_feature_variations daegun_feature_variations;The FeatureVariations record a GSUB or GPOS table may point at: which features change at which points in the design space.
daegun_glyph_instancetypedef struct { float glyph_box[4]; float tint[4]; float offset[2]; float em_pixels[2]; float scale; uint32_t band_base; uint32_t bands_per_axis; uint32_t hull_base; float inv_scale; float _pad[3]; } daegun_glyph_instance;One glyph's instance data, uploaded straight to the GPU. Fields are public and this struct IS the wire format: the size assertion at the bottom of this header is what keeps the two in step.
daegun_ivstypedef struct daegun_ivs daegun_ivs;An item variation store, out of a GDEF, HVAR, MVAR or VVAR table. The one handle here that copies nothing: the Rust store is built rather than a view over the table, so this owns it outright.
daegun_region_axistypedef struct { double start; double peak; double end; } daegun_region_axis;One axis of one variation region: where it starts, peaks and ends.
daegun_requesttypedef struct { float ppem; int32_t hinted; int32_t stroked; int32_t gamma; int32_t emboldened; int32_t obliqued; } daegun_request;What a caller is asking for. The flags are int32_t rather than bool for the same reason every other flag in this header is.
daegun_subpixel_paramstypedef struct { float weights[DAEGUN_MAX_SUBPIXEL_WEIGHTS * 3]; uint32_t oversample[2]; uint32_t taps[2]; int32_t origin[2]; uint32_t channels; uint32_t supersample; } daegun_subpixel_params;The subpixel filter. Build it with daegun_subpixel_params_from_layout rather than by hand: most of it is a kernel the engine derives from the layout, and
tapspast DAEGUN_MAX_SUBPIXEL_TAPS indexes past the shader's own table.
Vulkan backend
Vulkan, available anywhere the loader finds a driver. The same 19 functions every backend has. Opened by name at run time, so it adds nothing to link.
daegun_vulkan_geometrytypedef struct daegun_vulkan_geometry daegun_vulkan_geometry;An opaque Vulkan geometry handle.
Glyph curves uploaded to the Vulkan device. Build a batch, create geometry from it once, then draw from that geometry many times – rebuilding it per frame throws away the point of the GPU path. Free it before the renderer.
daegun_vulkan_renderertypedef struct daegun_vulkan_renderer daegun_vulkan_renderer;An opaque Vulkan renderer handle.
The Vulkan device daegun draws through. Created with
_renderer_new, which answersDAEGUN_UNSUPPORTEDwhere the platform is absent rather than failing to load. Free it last, after every target and geometry made from it.daegun_vulkan_targettypedef struct daegun_vulkan_target daegun_vulkan_target;An opaque Vulkan target handle.
A Vulkan render target: the pixels drawn into. Read them back with
_target_pixelsor_read_pixels, and free it before the renderer it came from.
What it says
What the font claims about itself: its names, its style, its vertical metrics. Every measurement is on a 1000-unit em whatever the font's own units are, so a value in pixels is value * px / 1000.0.
daegun_line_metricstypedef struct { double ascent; double descent; double line_gap; } daegun_line_metrics;Ascent, descent and line gap for one writing direction, on the 1000-unit em.
descentis negative, being a coordinate below the baseline rather than a distance, so line height isascent - descent + line_gap. Filled bydaegun_font_line_metrics, which already resolves the font's disagreement between its typographic and Windows metrics./* the three fields, and why descent is subtracted rather than added */ daegun_line_metrics m; daegun_font_line_metrics(font, false, &m); printf("ascent %.0f, descent %.0f, gap %.0f\n", m.ascent, m.descent, m.line_gap); /* e.g. ascent 969, descent -242, gap 0 -> 1211 units of line height */daegun_os2_infotypedef struct { uint16_t version; uint16_t has_family_class; uint16_t family_class; uint16_t has_selection; uint16_t selection; uint16_t has_win_metrics; int32_t win_ascent; int32_t win_descent; uint16_t has_typo_metrics; int32_t typo_ascender; int32_t typo_descender; int32_t typo_line_gap; } daegun_os2_info;What OS/2 says. The has_ fields are Option again: a version below 4 carries no typographic metrics, and a face may state no family class at all.
daegun_typographic_metricstypedef struct { int32_t x_height; int32_t underline_position; int32_t underline_thickness; int32_t strikeout_size; int32_t strikeout_position; int32_t subscript_x_size; int32_t subscript_y_size; int32_t subscript_x_offset; int32_t subscript_y_offset; int32_t superscript_x_size; int32_t superscript_y_size; int32_t superscript_x_offset; int32_t superscript_y_offset; } daegun_typographic_metrics;x-height, underline, strikeout, and subscript and superscript placement, on the 1000-unit em.
Everything needed to decorate text the way the designer intended rather than by guessing. Drawing an underline at a fixed offset looks wrong across fonts; these are the font's own numbers. Filled by
daegun_font_typographic_metrics.