diff options
| author | eunhhu <[email protected]> | 2026-09-27 08:44:42 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-09-27 08:44:42 +0100 |
| commit | 523b810d6a9c60342c7f5d74f36fe66f3f2057e9 (patch) | |
| tree | c716fb00013264fdbfe7a95dc3f4a43c50b01ecc /src/symbols.h | |
| parent | 65a208f7a88e0aeea0d9db4666fd171f59b2a1d2 (diff) | |
| download | vega-523b810d6a9c60342c7f5d74f36fe66f3f2057e9.tar.gz vega-523b810d6a9c60342c7f5d74f36fe66f3f2057e9.zip | |
Draw glyphs and icons from one symbol format, by exact pixel area
Symbol files (VEGASYM1) hold glyphs and icons as quadratic curves, verified
once per symbol and then read in place. vega-symbols builds them from fonts
(through FreeType, losslessly: twice the font's units keeps TrueType's
implied points whole) and from solid SVG paths (arcs included), refusing by
name what an icon asks for that symbols cannot hold.
The reference rasterizer computes each pixel's covered area exactly: every
curve's integral of clamp(1 - x) dy inside the pixel, split where it crosses
the pixel's sides. The Slug-style two-ray average first tried missed FreeType
by 15.4 levels on average at 12 px; exact area is within 1.2-3.5 at 8-16 px,
and where it differs most it matches 64x64 supersampling, not FreeType.
Reaching an outline costs 4.6-29x less than through FreeType, but the files
are 2.1-6.6x larger than glyf or CFF: design 002 has the numbers and the next
question (points shared along contours, lines without control points).
Diffstat (limited to 'src/symbols.h')
| -rw-r--r-- | src/symbols.h | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/src/symbols.h b/src/symbols.h new file mode 100644 index 0000000..da33e34 --- /dev/null +++ b/src/symbols.h @@ -0,0 +1,38 @@ +#ifndef VEGA_SYMBOLS_H +#define VEGA_SYMBOLS_H +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +/* Symbols: glyphs and icons as quadratic curves in one file, verified once + * and then read where it lies (docs/design/002-symbol-format.md). */ +enum { VEGA_SYMBOLS_HEADER = 28, VEGA_SYMBOL_BYTES = 24, VEGA_CURVE_BYTES = 12 }; +typedef struct { int16_t x0, y0, x1, y1, x2, y2; } VegaCurve; +typedef struct { + uint32_t code, first, count; /* its curves: [first, first + count) */ + int16_t left, bottom, right, top; /* bounds, in units, y up */ + int16_t advance; +} VegaSymbol; +typedef struct { + const unsigned char *bytes; + size_t size; + uint16_t units; /* per em */ + uint32_t symbols, curves; +} VegaSymbols; + +/* Verify bytes as a symbol file (kept, not copied); false with why. What + * reading needs is checked, per symbol: after this no read leaves the file. + * The curves themselves are not: one outside its symbol's bounds draws wrong. */ +bool vega_symbols_open(VegaSymbols *, const unsigned char *bytes, size_t size, char *error, size_t error_size); +/* The symbol of code (a binary search), or false. */ +bool vega_symbol(const VegaSymbols *, uint32_t code, VegaSymbol *out); +VegaSymbol vega_symbol_at(const VegaSymbols *, uint32_t index); +VegaCurve vega_curve(const VegaSymbols *, uint32_t index); +/* The coverage (0 to 1) of the pixel whose center is (x, y) in units, at + * scale pixels per unit: as a GPU would compute it per pixel. */ +double vega_symbol_coverage(const VegaSymbols *, const VegaSymbol *, double scale, double x, double y); +/* width x height 8-bit coverage, rows top first; pixel (i, j) has its center + * at (left + (i + 0.5) / scale, top - (j + 0.5) / scale) in units. */ +void vega_symbol_raster(const VegaSymbols *, const VegaSymbol *, double scale, double left, double top, int width, + int height, unsigned char *out); +#endif |
