Freestanding C module resolving a Unicode codepoint (cmap format 4) to a glyph index and its outline header (contour count, bounding box), verified against an independent from-scratch Python reference reader via tools/ttftest.c. Not yet wired into the boot path or capsule system. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
132 lines
4.1 KiB
C
132 lines
4.1 KiB
C
/*
|
||
StarForth — Steady-State Virtual Machine Runtime
|
||
|
||
Copyright (c) 2023–2025 Robert A. James
|
||
All rights reserved.
|
||
|
||
This file is part of the StarForth project.
|
||
|
||
Licensed under the StarForth License, Version 1.0 (the "License");
|
||
you may not use this file except in compliance with the License.
|
||
|
||
You may obtain a copy of the License at:
|
||
https://github.com/star.4th@proton.me/StarForth/LICENSE.txt
|
||
|
||
This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
express or implied, including but not limited to the warranties of
|
||
merchantability, fitness for a particular purpose, and noninfringement.
|
||
|
||
See the License for the specific language governing permissions and
|
||
limitations under the License.
|
||
*/
|
||
|
||
/**
|
||
* ttf.h - TrueType font parser core (Freestanding)
|
||
*
|
||
* FABRIC.md item 4.3.7. Reads a TTF's sfnt directory plus head/maxp/loca/
|
||
* glyf/cmap tables, resolving a Unicode codepoint to a glyph index and its
|
||
* outline header (contour count, bounding box). Does NOT extract outline
|
||
* points or rasterize — that is 4.3.7a/4.3.7c. No floating point; all
|
||
* fields read here are raw integers straight from the font's own
|
||
* big-endian on-disk format (see FABRIC.md §27.7 decision #2 for why the
|
||
* Q48.16-vs-float call was made, and why it doesn't bind this file, which
|
||
* never scales anything).
|
||
*
|
||
* cmap: only format 4 (Windows/Unicode BMP) subtables are resolved. This
|
||
* covers ASCII and all of the BMP, which is what the v1 glyph repertoire
|
||
* (§27.6.4) needs. Format 12 (supplementary planes) is deferred — no
|
||
* v1 glyph requires it.
|
||
*/
|
||
|
||
#ifndef STARKERNEL_TTF_H
|
||
#define STARKERNEL_TTF_H
|
||
|
||
#include <stdint.h>
|
||
#include <stddef.h>
|
||
#include "q48_16.h"
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
#define TTF_OK 0
|
||
#define TTF_ERR_BAD_SFNT -1
|
||
#define TTF_ERR_TABLE_MISSING -2
|
||
#define TTF_ERR_BAD_TABLE -3
|
||
#define TTF_ERR_BAD_GLYPH_INDEX -4
|
||
#define TTF_ERR_OUT_OF_BOUNDS -5
|
||
|
||
/** Glyph index returned for "no mapping" by ttf_codepoint_to_glyph(). */
|
||
#define TTF_GLYPH_MISSING 0
|
||
|
||
/**
|
||
* Parsed font handle. Borrows the caller's buffer (does not copy or own
|
||
* it) — the buffer must outlive the ttf_font_t.
|
||
*/
|
||
typedef struct {
|
||
const uint8_t *data;
|
||
uint32_t size;
|
||
|
||
uint32_t head_off;
|
||
uint32_t maxp_off;
|
||
uint32_t loca_off;
|
||
uint32_t loca_len;
|
||
uint32_t glyf_off;
|
||
uint32_t glyf_len;
|
||
|
||
uint16_t units_per_em;
|
||
int16_t index_to_loc_format; /* 0 = Offset16 (x2), 1 = Offset32 */
|
||
uint16_t num_glyphs;
|
||
|
||
/* Selected cmap subtable (format 4 only, see file header comment). */
|
||
uint32_t cmap_subtable_off;
|
||
int has_cmap;
|
||
} ttf_font_t;
|
||
|
||
/** Raw glyf record header, per §27.6/4.3.7's "done when" clause. */
|
||
typedef struct {
|
||
int16_t num_contours; /* >= 0 simple glyph, < 0 composite glyph */
|
||
int16_t x_min;
|
||
int16_t y_min;
|
||
int16_t x_max;
|
||
int16_t y_max;
|
||
uint32_t glyf_offset; /* absolute file offset of this glyph's record */
|
||
uint32_t glyf_length; /* bytes; 0 for an empty glyph (e.g. space) */
|
||
} ttf_glyph_header_t;
|
||
|
||
/**
|
||
* ttf_parse - Locate and validate the sfnt directory and the head/maxp/
|
||
* loca/glyf tables (cmap is optional; ttf_codepoint_to_glyph() fails
|
||
* cleanly if absent). Does not copy `data` — `out` borrows it.
|
||
*
|
||
* @param data Whole .ttf file contents
|
||
* @param size Length of data in bytes
|
||
* @param out Parsed handle to populate
|
||
* @return TTF_OK, or a TTF_ERR_* code
|
||
*/
|
||
int ttf_parse(const uint8_t *data, uint32_t size, ttf_font_t *out);
|
||
|
||
/**
|
||
* ttf_codepoint_to_glyph - Resolve a Unicode codepoint via the font's
|
||
* format-4 cmap subtable.
|
||
*
|
||
* @return glyph index, or TTF_GLYPH_MISSING if unmapped or no cmap
|
||
*/
|
||
uint32_t ttf_codepoint_to_glyph(const ttf_font_t *font, uint32_t codepoint);
|
||
|
||
/**
|
||
* ttf_glyph_header - Read a glyph's outline header (contour count,
|
||
* bounding box) via loca + glyf. Does not extract contour points.
|
||
*
|
||
* @param glyph_index As returned by ttf_codepoint_to_glyph()
|
||
* @param out Header to populate
|
||
* @return TTF_OK, or a TTF_ERR_* code
|
||
*/
|
||
int ttf_glyph_header(const ttf_font_t *font, uint32_t glyph_index,
|
||
ttf_glyph_header_t *out);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* STARKERNEL_TTF_H */ |