Cambios: - ttf.zig: Fix formato pixel ABGR (era RGBA invertido) - cmap_debug.zig: Herramienta diagnóstico tabla cmap - build.zig: Target cmap-debug para ejecutar diagnóstico - docs/research/TTF_DEBUG_SESSION: Documentación sesión debug Nota: El código base TTF funciona (cmap_debug lo confirma). El bug de rendering sigue sin resolver en integración. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
6.2 KiB
Sesión de Debugging TTF - 17 Diciembre 2025
Estado: EN PROGRESO Problema: Texto TTF corrupto (garabatos + colores raros) en zsimifactu Proyectos afectados: zcatgui, zsimifactu
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 renderizadosrc/render/embedded_font.zig- Fuente DroidSans embebidasrc/render/framebuffer.zig- Framebuffer y formato de pixelsrc/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:
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):
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:
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:
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:
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. PRÓXIMOS PASOS
- Aplicar fix Bug 1 (formato ABGR) - HECHO
- Ejecutar tests zcatgui - PASAN
- Ejecutar diagnóstico cmap - CÓDIGO BASE OK
- PROBAR zsimifactu con el fix aplicado
- Si sigue fallando, investigar diferencias en la integración
7. ARCHIVOS MODIFICADOS
| Archivo | Cambio |
|---|---|
src/render/ttf.zig |
Fix formato ABGR en líneas 951-955 |
src/render/cmap_debug.zig |
Herramienta de diagnóstico actualizada |
build.zig |
Añadido target cmap-debug |
Documento creado: 2025-12-17 Última actualización: 2025-12-17 - Fix ABGR aplicado, diagnóstico completo