[package] name = "llimphi-compositor" version.workspace = true edition.workspace = true license.workspace = true authors.workspace = true publish.workspace = true description = "llimphi-compositor — el núcleo declarativo de Llimphi sin winit: el árbol `View`, el mount sobre taffy, el paint a `vello::Scene` y el hit-test. No depende de llimphi-hal ni de una surface concreta, así que la misma composición sirve sobre winit (llimphi-ui) o, a futuro, sobre el framebuffer del kernel wawa. `wgpu` entra sólo por la firma de `GpuPaintFn` (tipos, no windowing)." repository.workspace = true [dependencies] # El modelo de ENTRADA, como dato puro y sin vecinos. Estaba adentro de este # crate (módulo `input`) hasta el 24-ago-2026; se mudó porque el cable de la # jaula lo necesita serializable y no puede depender de un crate que exige elegir # backend de pintura. Se re-exporta desde `crate::input`, así que nadie cambia. llimphi-entrada = { path = "../llimphi-entrada", version = "0.1.0" } llimphi-layout = { path = "../llimphi-layout", version = "0.1.0" } # El mapa sin sistema operativo — el mismo que `std::collections::HashMap` usa # por dentro, así que en Linux no cambia nada. hashbrown = { version = "0.17", default-features = false, features = ["default-hasher", "inline-more"] } # El hasher de las memoizaciones. `std::collections::hash_map::DefaultHasher` # no existe sin std, y el default de hashbrown va sembrado al azar por proceso. # `FixedState` es DETERMINISTA, que es lo que estos hashes necesitan: comparan # el mismo subárbol entre fotogramas. foldhash = { version = "0.2", default-features = false } # `ceil`/`sqrt` sobre f32/f64 no existen sin `std`: son métodos que aporta la # stdlib, no el lenguaje. Se piden a libm en el perfil bare-metal. libm = { version = "0.2", optional = true } # Sin `default-features`: su default enciende el backend vello, y acá el backend # lo elige la feature de ESTE crate. Se reenvía abajo. llimphi-text = { path = "../llimphi-text", version = "0.1.0", default-features = false } # Reloj monotónico portable de las animaciones (ver `crate::Instant`). En # targets nativos es un re-export literal de `std::time::Instant`: mismo tipo, # coste cero. En wasm32 es `performance.now()`, donde el de std panica. web-time = { version = "1", optional = true } # vello declarado DIRECTO (no `{ workspace = true }`) y sin `default-features`. # # Es la mitad que faltaba para sacar wgpu de verdad: hacer opcional la dep # DIRECTA no alcanzaba, porque wgpu volvía a entrar por la puerta de atrás — # `vello` lo trae en su `default` (features `wgpu` + `wgpu_default`). Y como # apagar `default-features` desde un miembro no hace nada si el workspace no lo # declaró, había que declararlo acá. # # Lo que el compositor usa de vello es `Scene`, `kurbo` y `peniko`, y NINGUNO # está detrás de la feature `wgpu` (`vello/src/lib.rs:146`). O sea: el árbol de # escena de vello nunca necesitó una GPU, sólo venía en el mismo paquete. # # OPCIONAL desde W3.b: el compositor ya no nombra a `vello::Scene` sino al # alias `Lienzo`, que en wawa es `llimphi_cpu::Escena`. vello entra sólo con la # feature del backend homónimo. # 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 } # Sólo para los tipos de la firma de GpuPaintFn (Device/Queue/Encoder/View). # wgpu NO depende de winit — el compositor sigue libre de windowing. # # OPCIONAL desde W1 (PLAN-LLIMPHI.md): en wawa no hay wgpu que valga, y era la # única dependencia del compositor atada a una GPU concreta. Con `default` la # feature está encendida, así que para todo consumidor de hoy no cambia nada. wgpu = { workspace = true, optional = true } [features] # El default reproduce lo de siempre: backend vello, fuentes del sistema y el # hook de GPU directa. Ningún consumidor de hoy nota W3.b. default = ["std", "vello", "system", "gpu"] # --- El backend de pintura. Excluyentes; `llimphi-text` lo vigila con un # `compile_error!` si se encienden los dos. --- # Linux: se pinta en una `vello::Scene`. # `std` da el reloj (`web-time`) y la stdlib. Sin él, el compositor usa su # propio `Instant` de microsegundos (ver `crate::reloj`). std = ["dep:web-time", "llimphi-text/std"] vello = ["dep:vello", "llimphi-text/vello", "std"] # wawa: se pinta en una `llimphi_cpu::Escena`, sin GPU y sin std. cpu = ["llimphi-text/cpu"] # App enjaulada (W4): no se pinta — se GRABA en una `EscenaWire` que cruza la # frontera WASM, y el texto viaja sin shapear. `render.rs` no distingue: la # costura está en `llimphi-text::wire`, que le da otro `Typesetter` con las # mismas firmas. # cargo check -p llimphi-compositor --no-default-features --features wire,std wire = ["llimphi-text/wire"] # Fuentes del sistema (fontique). Sólo tiene sentido con std. system = ["llimphi-text/system"] # Matemática por libm — el perfil bare-metal. libm = ["llimphi-text/libm", "dep:libm"] # El hook de pintura GPU directa (`View::gpu_paint_with`). Encendido por # defecto: apagarlo es la excepción (el camino CPU de wawa), no la norma. # Implica el backend vello: sin `vello::Scene` no hay pasada sobre la que # encimar el render de wgpu. gpu = ["vello", "dep:wgpu", "vello/wgpu_default"] [dev-dependencies] # Volcado headless del paint a PNG (llvmpipe) para VER sombra/gradiente/borde # sin levantar ventana. Sólo capas inferiores — no llimphi-ui (sin ciclo). llimphi-hal = { path = "../llimphi-hal", version = "0.1.0" } llimphi-raster = { path = "../llimphi-raster", version = "0.1.0" } llimphi-theme = { path = "../llimphi-theme", version = "0.1.0" } png = { workspace = true } pollster = { workspace = true } # Widgets REALES para el showreel: el `View` que devuelven es el mismo # tipo (`llimphi_compositor::View`, re-exportado por llimphi-ui), así que # montan con el mount/paint/measure de este mismo crate. Dev-only → sin ciclo # en el grafo normal (llimphi-ui depende de este crate, no al revés). llimphi-widget-switch = { path = "../widgets/switch", version = "0.1.0" } llimphi-widget-slider = { path = "../widgets/slider", version = "0.1.0" } llimphi-widget-progress = { path = "../widgets/progress", version = "0.1.0" } llimphi-widget-button = { path = "../widgets/button", version = "0.1.0" } llimphi-widget-segmented = { path = "../widgets/segmented", version = "0.1.0" }