[package] name = "llimphi-text" version.workspace = true edition.workspace = true license.workspace = true authors.workspace = true publish.workspace = true # vello directo (no llimphi-raster): el motor de texto sólo necesita # Scene/peniko/kurbo para construir y pintar layouts — nada del Renderer ni # de llimphi-hal. Eso mantiene llimphi-text (y quien lo use: el compositor) # libre de winit, condición para correr sobre el framebuffer de wawa. description = "Text shaping for llimphi over parley (Inter default, DejaVu Sans symbol fallback)." repository.workspace = true [dependencies] # Sin `default-features`: de vello acá se usan `Scene`, `Glyph`, `kurbo` y # `peniko`, y ninguno vive detrás de su feature `wgpu`. Con el default puesto, # este crate arrastraba wgpu entero al árbol y anulaba —por unificación de # features— el trabajo de sacarlo de `llimphi-compositor` (W1 de # PLAN-LLIMPHI.md). Declarado directo porque apagar `default-features` desde un # miembro no surte efecto si el workspace no lo declaró así. # # OPCIONAL desde W2: `vello` es std-only (no tiene perfil no_std), y el kernel de # wawa no lo puede enlazar. Sólo lo necesitan las SIETE funciones de dibujo # (`draw_layout*`, `draw_block`, `paint_decoration`); todo el shaping — # `Typesetter`, `layout`, `measurement`— está limpio de vello. Esa es la # frontera, y resultó estar ya dibujada sola. # Versión desde el workspace, NO pinneada acá. Tenerla suelta fue lo que # metió DOS vello en el grafo al migrar a 0.9 (2026-07-28) y produjo el # error más desorientador de la tanda: «expected Scene, found # llimphi_raster::vello::Scene» — el mismo tipo, de dos crates distintos. vello = { workspace = true, default-features = false, optional = true } # El IR de escena (W4): el tercer backend. Igual que `vello` y `llimphi-cpu`, es # opcional — sólo lo enlaza quien compila el camino de la app enjaulada. llimphi-wire-escena = { path = "../llimphi-wire-escena", version = "0.1.0", default-features = false, optional = true } # parley DIRECTO y sin defaults: su `default = ["system"]` arrastra # fontconfig/objc2/windows por fontique. Se recupera con la feature `system` de # acá, que el default enciende — en Linux el fallback CJK/emoji del sistema NO # se resigna. parley = { version = "0.6", default-features = false, optional = true } # peniko directo. Antes llegaba VÍA vello (`use vello::peniko`), y eso ataba los # tipos de color al crate que justamente hay que poder apagar. peniko = { version = "0.6", default-features = false } # El caché de shaping. `std::collections::HashMap` ES hashbrown por dentro, así # que esto no cambia el comportamiento en Linux: sólo lo vuelve expresable sin # sistema operativo. hashbrown = { version = "0.17", default-features = false, features = ["default-hasher", "inline-more"] } # El backend CPU (W3). Opcional y apagado por default: en Linux el camino normal # sigue siendo vello. Se enciende en wawa, que es donde `vello::Scene` no existe. llimphi-cpu = { path = "../llimphi-cpu", version = "0.1.0", default-features = false, optional = true } [features] # El default reproduce EXACTAMENTE lo de antes: dibujo con vello, fuentes del # sistema, std. Ningún consumidor nota W2. default = ["std", "vello", "system"] # ¿Este build SHAPEA? Es el gate honesto: `parley` (con fontique y swash detrás) # sólo hace falta si alguien va a resolver ligaduras y line-break de este lado. # Los backends que pintan lo necesitan; el backend `wire` NO — su typesetter # pregunta en vez de shapear, y arrastrar el shaper igual sería meter en la jaula # justo lo que W4 sacó de ella. shaping = ["dep:parley"] std = ["parley?/std", "peniko/std", "llimphi-cpu?/std", "llimphi-wire-escena?/std"] # Pintar el texto shapeado en una `llimphi_cpu::Escena` en vez de en una # `vello::Scene`. Es el camino de wawa: mismo layout de parley, otro pincel. cpu = ["dep:llimphi-cpu", "shaping"] # Emitir hacia el IR de escena en vez de rasterizar: el camino de una app `.wasm` # que compone dentro de la jaula y manda el resultado. Excluyente con los otros # dos backends. NO shapea — ver el módulo `wire`. # cargo check -p llimphi-text --no-default-features --features wire,std wire = ["dep:llimphi-wire-escena"] # Las fuentes del sistema (fontique/system → fontconfig · objc2 · windows). Es # lo que da el fallback CJK/emoji más allá de las tres fuentes embebidas. system = ["std", "shaping", "parley?/system"] # Las siete funciones que pintan en `vello::Scene`. vello = ["dep:vello", "std", "shaping"] # Bare-metal (wawa): matemática por libm, sin sistema de fuentes — sólo los # blobs que el crate ya embebe y registra a mano. # cargo check -p llimphi-text --target x86_64-wawa \ # --no-default-features --features libm -Z build-std=core,alloc libm = ["parley?/libm", "peniko/libm", "llimphi-cpu?/libm", "llimphi-wire-escena?/libm"] [dev-dependencies] llimphi-raster = { path = "../llimphi-raster", version = "0.1.0" } llimphi-hal = { path = "../llimphi-hal", version = "0.1.0" } pollster = { workspace = true } [[example]] name = "hello_text" path = "examples/hello_text.rs" # Pinta con `draw_block`, que sólo existe con la feature `vello` (W2). required-features = ["vello"] # W4.1 de 03_ukupacha/wawa/PLAN-LLIMPHI.md — el costo del shaping del lado app, # el único número que le faltaba a la decisión de ABI de W4. [[example]] name = "medir_shaping" path = "examples/medir_shaping.rs" # Mide el costo del shaping: pide `parley`, o sea la feature `shaping`. Faltaba # declararlo, así que bajo `wire` el ejemplo existía y no compilaba — la misma # clase de cosa que una feature declarada y nunca construida. required-features = ["shaping"] # Mide el caché de shaping (`cache_stats`), que sólo existe donde se shapea. No # estaba declarado —cargo lo descubría solo— y por eso nadie había notado que no # compila sin `shaping`. [[example]] name = "bench_cache" path = "examples/bench_cache.rs" required-features = ["shaping"] # Mide con `measure`, que sólo existe donde se shapea. Mismo caso que los # ejemplos: no estaba declarado, así que nadie había notado que no compila bajo # el backend `wire`. [[test]] name = "mono_ancho_fijo" path = "tests/mono_ancho_fijo.rs" required-features = ["shaping"]