# Sesión de Debugging TTF - 17 Diciembre 2025 > **Estado**: PAUSADO → Nueva librería zcatttf en desarrollo > **Problema**: Texto TTF corrupto (garabatos + colores raros) en zsimifactu > **Proyectos afectados**: zcatgui, zsimifactu > **Resolución**: Reimplementar TTF desde cero en zcatttf (otra conversación) --- ## 1. CONTEXTO INICIAL ### Síntomas reportados - Todo el texto TTF se ve como garabatos ilegibles - Colores raros/incorrectos en el texto - Afecta a TODO el texto, incluyendo ASCII básico (A-Z, a-z, 0-9) - El problema aparece en zsimifactu, no en tests aislados ### Historial previo (sesiones anteriores) | Fecha | Intento | Resultado | |-------|---------|-----------| | 2025-12-16 | Cambiar AdwaitaSans → DroidSans | ❌ No resolvió | | 2025-12-16 | Y-flip en rasterización | ❌ No resolvió | | 2025-12-16 | UTF-8 decode en drawText | ❌ No resolvió | ### Commit relevante ``` 9a2beab wip: TTF diagnóstico - test aislado funciona, integración NO ``` Este commit indica que un test aislado con DroidSans funcionaba, pero la integración en zsimifactu no. --- ## 2. INVESTIGACIÓN (17 Dic 2025) ### 2.1 Revisión del código con perspectiva fresca **Archivos revisados:** - `src/render/ttf.zig` - Parser TTF y renderizado - `src/render/embedded_font.zig` - Fuente DroidSans embebida - `src/render/framebuffer.zig` - Framebuffer y formato de pixel - `src/render/software.zig` - Renderer que usa TTF ### 2.2 Bug 1 Identificado: Formato Pixel ABGR vs RGBA **Ubicación:** `ttf.zig` líneas 951-955 **El problema:** El código de alpha blending en `drawGlyphBitmap()` desempaqueta pixels como RGBA: ```zig const bg = Color{ .r = @intCast((bg_u32 >> 24) & 0xFF), // ❌ Esto lee Alpha, no Red .g = @intCast((bg_u32 >> 16) & 0xFF), // ❌ Esto lee Blue, no Green .b = @intCast((bg_u32 >> 8) & 0xFF), // ❌ Esto lee Green, no Blue .a = @intCast(bg_u32 & 0xFF), // ❌ Esto lee Red, no Alpha }; ``` **Pero el framebuffer usa ABGR** (verificado en `framebuffer.zig:104-108`): ```zig const bg = Color{ .r = @truncate(existing), // bits 0-7 = R .g = @truncate(existing >> 8), // bits 8-15 = G .b = @truncate(existing >> 16), // bits 16-23 = B .a = @truncate(existing >> 24), // bits 24-31 = A }; ``` **Efecto:** Colores incorrectos en el texto renderizado con TTF. ### 2.3 Bug 2 Sospechado: Tests usan fuente diferente **Hallazgo:** Los tests en `ttf.zig` (línea 1086) cargan AdwaitaSans del sistema: ```zig var font = TtfFont.loadFromFile(allocator, "/usr/share/fonts/adwaita-sans-fonts/AdwaitaSans-Regular.ttf") ``` **Pero zsimifactu usa DroidSans** (del sistema o embebida). Esto significa que los tests NO cubren el caso real de uso. Si DroidSans tiene una estructura cmap diferente, el problema no se detectaría en los tests. ### 2.4 Archivo de diagnóstico existente Encontrado `src/render/cmap_debug.zig` - herramienta de diagnóstico para analizar la tabla cmap de DroidSans. No está integrado en build.zig. --- ## 3. ACCIONES CORRECTIVAS ### 3.1 Fix Bug 1: Formato Pixel ABGR **Archivo:** `src/render/ttf.zig` **Líneas:** 951-955 **Acción:** Cambiar interpretación de RGBA a ABGR **Antes:** ```zig const bg = Color{ .r = @intCast((bg_u32 >> 24) & 0xFF), .g = @intCast((bg_u32 >> 16) & 0xFF), .b = @intCast((bg_u32 >> 8) & 0xFF), .a = @intCast(bg_u32 & 0xFF), }; ``` **Después:** ```zig const bg = Color{ .r = @truncate(bg_u32), .g = @truncate(bg_u32 >> 8), .b = @truncate(bg_u32 >> 16), .a = @truncate(bg_u32 >> 24), }; ``` **Estado:** PENDIENTE --- ### 3.2 Diagnóstico Bug 2: Ejecutar cmap_debug **Acción:** Integrar `cmap_debug.zig` en build.zig y ejecutar para ver: - Formato de subtabla cmap que usa DroidSans - Mapeo de caracteres (A, B, C... → glyph indices) - Verificar si los glyph indices son correctos **Estado:** PENDIENTE --- ## 4. REGISTRO DE CAMBIOS | Hora | Acción | Resultado | |------|--------|-----------| | -- | Inicio investigación | -- | | -- | Identificado Bug 1 (ABGR) | ✅ Confirmado | | -- | Aplicado Fix Bug 1 | ✅ ttf.zig:951-955 corregido | | -- | Tests zcatgui | ✅ Pasan | | -- | Ejecutado cmap_debug | ✅ Código base TTF funciona perfecto | --- ## 5. RESULTADOS DEL DIAGNÓSTICO ### Salida de cmap_debug ``` === Diagnóstico cmap DroidSans (embebido) === Tamaño fuente embebida: 190776 bytes num_glyphs: 901 units_per_em: 2048 cmap_offset: 22232 glyf_offset: 29196 loca_offset: 27392 index_to_loc_format: 0 cmap version: 0 cmap num_subtables: 3 Subtablas cmap: [0] platform=0 encoding=3 offset=28 format=4 [1] platform=1 encoding=0 offset=804 format=6 [2] platform=3 encoding=1 offset=1326 format=4 === Mapeo de caracteres === 'A' (0x41) -> glyph 36 'B' (0x42) -> glyph 37 'a' (0x61) -> glyph 68 '0' (0x30) -> glyph 19 === Verificar glyphs === 'A' -> glyph 36, contours=2 bbox=(0,0)-(1245,1468) 'B' -> glyph 37, contours=3 bbox=(199,0)-(1159,1462) 'C' -> glyph 38, contours=1 bbox=(125,-20)-(1176,1483) === ASCII Art de 'A' === Bitmap: 17x20 *#. *#. .#* ## ## .#* *#. ## .#* ## ##......*#. .######### ## #* ## .#. .#. ## ## .#* *# *#. ........## ####. ######### ### ##. ``` ### Conclusión del diagnóstico **EL CÓDIGO BASE TTF FUNCIONA PERFECTAMENTE:** - ✅ Parsing de DroidSans correcto - ✅ Tabla cmap parseada correctamente (format 4) - ✅ Mapeo de caracteres correcto ('A'→36, etc.) - ✅ Extracción de contornos correcta - ✅ Rasterización correcta (ASCII Art de 'A' es claramente una 'A') **CONCLUSIÓN**: El problema NO está en el código base TTF. El único bug identificado es el **formato ABGR** que ya fue corregido. --- ## 6. INTENTOS ADICIONALES (Sesión 17 Dic tarde) Después del diagnóstico, se probaron más fixes: | Fix | Archivo | Cambio | Resultado | |-----|---------|--------|-----------| | Y-flip bitmap | ttf.zig:142 | `data[(height-1-py)*width+px]` | ⚠️ Orientación OK, pero "eco" | | bearing_x = 0 | ttf.zig:150 | Normalizar a (0,0) | ⚠️ Mejoró, sigue corrupto | | bearing_y = y_max | ttf.zig:151 | Distancia al baseline | ❓ NO VERIFICADO | **Problema persistente**: Cada fix mejoraba algo pero introducía nuevos artefactos. El usuario detuvo los intentos por frustración con el ciclo de prueba-error. --- ## 7. DECISIÓN FINAL: Nueva librería zcatttf **Consenso alcanzado**: En lugar de seguir parcheando código que no entendemos completamente, reimplementar TTF desde cero usando el algoritmo de áreas trapezoidales (como stb_truetype). ### Justificación 1. El código base funciona en tests aislados pero falla en integración 2. El algoritmo actual (supersampling) tiene bugs difíciles de rastrear 3. stb_truetype usa un algoritmo más eficiente y mejor documentado 4. Una librería independiente es más testeable ### Nueva librería - **Proyecto**: `/mnt/cello2/arno/re/recode/zig/zcatttf/` - **Algoritmo**: Áreas trapezoidales (no supersampling) - **Estado**: EN DESARROLLO (otra conversación Claude) - **Plan**: `teamdocs/agenda/hitos/2025-12-16_zcatttf_plan_implementacion.md` --- ## 8. ARCHIVOS MODIFICADOS | Archivo | Cambio | |---------|--------| | `src/render/ttf.zig` | Fix ABGR + Y-flip + bearings (CONGELADO) | | `src/render/cmap_debug.zig` | Herramienta de diagnóstico | | `build.zig` | Añadido target `cmap-debug` | --- ## 9. ESTADO ACTUAL - **ttf.zig**: CONGELADO - No modificar hasta integrar zcatttf - **zsimifactu**: Usa bitmap fonts (funciona) - **zcatttf**: En desarrollo por otra conversación --- *Documento creado: 2025-12-17* *Última actualización: 2025-12-17 - Decisión: Nueva librería zcatttf*