// ============================================================================= // emitir_fixture :: la escena que el kernel va a reproducir // ----------------------------------------------------------------------------- // El encoder (esta jaula) y el reproductor (`llimphi-wawa`) NO pueden vivir en // el mismo binario: `wire` y `cpu` son backends excluyentes de `llimphi-text`, // y encender los dos dispara un `compile_error!` puesto a propósito. Eso no es // un obstáculo del diseño, es el diseño — son dos procesos en dos lados de una // frontera, y forzarlos a convivir para testearlos sería probar otra cosa. // // Así que la costura del test es la misma que la de producción: **bytes**. Este // ejemplo compone una vista con el compositor de verdad, la serializa, y deja // el resultado donde el test del otro lado lo levanta con `include_bytes!`. // // cargo run --example emitir_fixture --no-default-features --features std // // Si alguna vez el fixture y el reproductor dejan de entenderse, el test de // `llimphi-wawa` lo dice — que es exactamente lo que uno quiere que pase si // alguien cambia el formato del cable de un solo lado. // ============================================================================= use std::io::Write; use llimphi_jaula::taffy::prelude::*; use llimphi_jaula::{Color, Jaula, Style, View}; use llimphi_text::wire::{Medida, Peticion}; /// El destino, relativo a este crate. const DESTINO: &str = "../llimphi-wawa/pruebas/fixture_jaula.postcard"; #[derive(Clone, Debug, PartialEq)] enum Msg { Toque, } /// El medidor de la jaula. /// /// **Acá está la única pieza de W4 que todavía es un muñón**, y conviene que se /// vea: en wawa esto tiene que ser un `sys_medir_texto` que cruza a parley del /// lado nativo. Mientras no exista, el fixture se layoutea con una fórmula. La /// consecuencia práctica: el texto del fixture se pinta bien —el kernel lo /// shapea de verdad— pero ubicado según una medida aproximada. fn medidor(p: &Peticion<'_>) -> Medida { let chars = p.cadena.chars().count() as f32; let ancho = chars * p.estilo.tamano_px * 0.52; Medida { width: ancho, full_width: ancho, height: p.estilo.tamano_px * p.estilo.alto_linea, } } fn vista() -> View { let raiz = Style { size: Size { width: length(320.0), height: length(72.0), }, flex_direction: FlexDirection::Column, justify_content: Some(JustifyContent::CENTER), padding: Rect { left: length(14.0), right: length(14.0), top: length(10.0), bottom: length(10.0), }, ..Default::default() }; View::new(raiz) .fill(Color::from_rgba8(22, 26, 38, 255)) .radius(8.0) .children(vec![ View::new(Style::default()).text( "escena emitida por la jaula", 15.0, Color::from_rgba8(230, 232, 240, 255), ), View::new(Style::default()) .text( "shapeada del otro lado", 12.0, Color::from_rgba8(140, 200, 175, 255), ) .on_click(Msg::Toque), ]) } fn main() { let mut jaula = Jaula::new(320.0, 72.0, medidor); let _montado = jaula.fotograma(vista()); let escena = jaula.escena(); let bytes = postcard::to_allocvec(escena).expect("serializar"); println!("órdenes : {}", escena.len()); println!("textos : {}", escena.textos()); println!("estilos : {}", escena.estilos().len()); println!("estimadas : {}", jaula.medidas_estimadas()); println!("bytes : {}", bytes.len()); let destino = std::path::Path::new(DESTINO); if let Some(dir) = destino.parent() { std::fs::create_dir_all(dir).expect("crear directorio"); } let mut f = std::fs::File::create(destino).expect("crear fixture"); f.write_all(&bytes).expect("escribir fixture"); println!("escrito en : {}", destino.display()); emitir_peticion_de_prueba(); } /// Emite además los bytes de una `PeticionMedida` lista para embeber en una app /// `.wasm` sin asignador. /// /// `hello_wasm` es `no_std` y **sin alloc**: no puede construir un `String` para /// armar la petición en tiempo de ejecución. Pero tampoco lo necesita — lo único /// que el syscall pide son bytes, y los bytes se pueden calcular acá y embeber /// como constante. Así la app de prueba ejercita el cruce de verdad sin arrastrar /// un asignador que no le hace falta para nada más. fn emitir_peticion_de_prueba() { use llimphi_jaula::wire::{EstiloTextoWire, PeticionMedida}; let peticion = PeticionMedida { cadena: "wawa mide texto".into(), estilo: EstiloTextoWire { tamano_px: 16.0, ..Default::default() }, ancho_max: None, }; let bytes = postcard::to_allocvec(&peticion).expect("serializar peticion"); println!("\n// --- pegar en 03_ukupacha/wawa/apps/hello_wasm/src/lib.rs ---"); println!( "/// `PeticionMedida {{ cadena: {:?}, tamano_px: {} }}` en postcard.", peticion.cadena, peticion.estilo.tamano_px ); print!("const PETICION_MEDIDA: [u8; {}] = [", bytes.len()); for (i, b) in bytes.iter().enumerate() { if i % 12 == 0 { print!("\n "); } print!("0x{b:02x}, "); } println!("\n];"); }