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
  2. Modelo mental
  3. Orden de parseo
  4. Diseños de bytes

↑ 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.


↑ Contenido

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:

  1. Una tabla de offsets de 12 bytes (el encabezado sfnt): qué tipo de font es y cuántas tablas contiene.
  2. 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.”
  3. 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.


↑ Contenido

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:

  1. Tabla de offsets — Leer los primeros 12 bytes; capturar numTables.
  2. Directorio de tablas — Leer numTables × 16 bytes en un mapa tag → (offset, length). Después de esto, cambiar de lectura lineal a búsqueda por offset.
  3. head — Entrega unitsPerEm, indexToLocFormat, el bounding box del font.
  4. maxp — Entrega numGlyphs.
  5. hhea — Entrega numberOfHMetrics.
  6. hmtx — Necesita numberOfHMetrics (hhea) y numGlyphs (maxp).
  7. loca — Necesita indexToLocFormat (head) y numGlyphs (maxp).
  8. glyf — Necesita loca para delimitar cada glifo.
  9. cmap — Independiente; el mapa de carácter → glifo.
  10. 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.


↑ Contenido

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.