Motivación
Programar un rasterizer de TTF es posiblemente una de las cosas mas inútiles que hay, debido a que existen
varias soluciones listas para integrar en un engine.
Por otro lado, desde un punto de vista educativo, el aprendizaje obtenido es bastante sorprendente.
Documentación
El formato TrueType (posteriormente llamado OpenType) se puede encontrar en la página de
Apple y de forma mas escueta en la de
Microsoft.
Es realmente triste que estos documentos estén tan pobremente detallados, mas de una vez tuve que ver
código de otros rasterizers para comprobar si estaba entendiendo bien la especificación.
Recuerdo que el mayor inconveniente que tuve es que el archivo esta en formato
big-endian, y este
detalle solo estaba mencionado en el documento de Microsoft.
La información en un archivo TTF esta dividida en tablas y sin ninguna duda la mas importante es la que contiene los
glyphs, la representación visual de un carácter.
Otra tabla, por ejemplo, une el código de un carácter (Unicode) con su correspondiente
glyph
Cada
glyph es un conjunto de puntos ordenados, que al ser unidos forman el contorno de un símbolo.
Estos puntos pueden estar
en la curva o
fuera de la curva, estos últimos especifican puntos de control de una curva bezier. Uno esperaría entonces que siempre que haya un punto de control, que se encuentre en el medio de 2 puntos
en curva, marcando el inicio y fin de la misma.
 |
| Bezier |
Pero no siempre es así y a veces hay mas de un punto
fuera de la curva, entonces uno se pregunta, ¿de dónde cuernos saca los puntos de inicio y fin?
Como estos puntos se pueden calcular, no necesitan estar explicitados en el
glyph. Este otro "pequeño" detalle también es difícil de entender leyendo solo la documentación.
 |
| Las curvas de la e y la o son mas angostas de lo que deberían. |
Pasitos de bebé
Lo primero que intenté hacer fue poder visualizar algo de la información del archivo TTF que quería parsear; ver que los valores obtenidos tuvieran algo de sentido y después poder dibujar algo que se pareciera a un carácter.
La imagen de abajo muestra un contorno usando los puntos de control como si fueran rectas y en la parte de arriba ya con las curvas bezier.
Finalmente, una vez que tuve el contorno de un carácter pude rasterizar ese
glyph
 |
| Contorno y rasterizer. |
De ninguna manera esta biblioteca esta completa, ni desde un punto de capacidades, velocidad ni robustez. Por lo pronto le falta
Ademas, hay una fina linea entre las capacidades que debería brindar un elemento de texto y no el rasterizer, entre otras:
- Parsear códigos de control, como espacios, saltos de linea y tabulación
- justificación de texto
- Negrita e itálica
API
Desde el punto de vista del programador que va a dibujar texto solo hay que usar 2 funciones, una para cargar la TTF y otra para dibujar el texto en una posición con un tamaño y un color.
ttf_font *TtfFont = CreateTtf(game, "freesans.ttf");
...
DrawText(game, TtfTont, "Hola", Size, Pos, Black);
Como mencioné en mi
post anterior, estoy alejándome de objetos, herencia y polimorfismo y es por eso que el API son solo funciones. Esto me abre la puerta a poder hacer mi propia
IMGUI, que seguramente este escribiendo en en futuro cercano :)