jueves, 5 de mayo de 2016

TTF Rasterizer

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 :)

No hay comentarios.:

Publicar un comentario