Parsear un Font
Parsear Archivos de Fuente TrueType (TTF)
Una guía práctica e independiente de implementación para leer el formato binario TTF. Esta página cubre el modelo mental y el orden de parseo; los diseños de bytes campo por campo de cada tabla viven en la referencia compacta — Referencia Compacta de Bytes en TTF.
Contenido
1. Introducción
El objetivo es tomar un archivo .ttf como un arreglo plano de bytes y
convertirlo en datos estructurados — el encabezado del font, los contornos de
glifos, las métricas, el mapa de caracteres. Este documento cubre cómo
hacerlo: la forma del archivo, el orden de lectura, y cómo mover el cursor de
lectura a través de los bytes.
2. Modelo mental
Un archivo TTF no es un documento que se lee de principio a fin. Es un pequeño archivo comprimido (el formato se llama “sfnt” — scalable font). Sus bytes se organizan como:
- Una tabla de offsets de 12 bytes (el encabezado sfnt): qué tipo de font es y cuántas tablas contiene.
- Un directorio de tablas: un registro de tamaño fijo por tabla, cada uno indicando “la tabla con esta etiqueta vive en este offset de byte y tiene esta longitud.”
- Los datos de la tabla, ubicados sólo por los offsets en el directorio.
Núnca asumes dónde está algo. Este tipo de archivos no sigue ninguna convención de orden. Lees el offset y la longitud de una tabla desde el directorio, luego saltas allí.
Ayuda saber para qué sirven las tablas antes de parsearlas. Así es como un carácter se convierte en un glifo dibujado:
código de carácter ──(cmap)──► índice de glifo ──(loca)──► glyf (el contorno)
└─(hmtx)──► ancho de avance (el espaciado)
head y maxp son la configuración que hace que loca sea interpretable.
Esta cadena también explica por qué el orden de parseo en la sección 3 es el
que es.
3. Orden de parseo
Dónde se ubica una tabla (físicamente) es independiente de cuándo la decodificas (lógicamente). El orden de decodificación está forzado por las dependencias de datos:
- Tabla de offsets — Leer los primeros 12 bytes; capturar
numTables. - Directorio de tablas — Leer
numTables × 16bytes en un mapatag → (offset, length). Después de esto, cambiar de lectura lineal a búsqueda por offset. head— EntregaunitsPerEm,indexToLocFormat, el bounding box del font.maxp— EntreganumGlyphs.hhea— EntreganumberOfHMetrics.hmtx— NecesitanumberOfHMetrics(hhea) ynumGlyphs(maxp).loca— NecesitaindexToLocFormat(head) ynumGlyphs(maxp).glyf— Necesitalocapara delimitar cada glifo.cmap— Independiente; el mapa de carácter → glifo.name,post,OS/2,kern— Independiente / opcional; parsear según sea necesario.
Validar mientras avanzas. sfntVersion es un valor conocido; head.magicNumber == 0x5F0F3CF5; cada offset + length permanece dentro del archivo; la última entrada de loca equivale a la longitud de la tabla glyf.
4. Diseños de bytes
Para diseños de bytes offset por offset de cada tabla — big-endian, todos los tipos de campo, cada tabla — consulta la Referencia Compacta de Bytes en TTF. Está organizada como tablas de referencia rápida para cada tabla en el font.