From 04ede06c9c05e4094a97369880e663e01fae6d28 Mon Sep 17 00:00:00 2001 From: darkfi Date: Sat, 6 Jul 2024 10:44:44 +0200 Subject: [PATCH] wallet: editbox clip the rendered text properly --- bin/darkwallet/src/app.rs | 24 +++++++++++-------- bin/darkwallet/src/gfx2.rs | 7 ++++++ bin/darkwallet/src/mesh.rs | 41 ++++++++++++++++++++++++-------- bin/darkwallet/src/ui/editbox.rs | 21 ++++++++++------ 4 files changed, 66 insertions(+), 27 deletions(-) diff --git a/bin/darkwallet/src/app.rs b/bin/darkwallet/src/app.rs index ce7abbdab..b28869e7e 100644 --- a/bin/darkwallet/src/app.rs +++ b/bin/darkwallet/src/app.rs @@ -324,19 +324,22 @@ impl App { node.set_property_bool("is_active", true).unwrap(); let prop = node.get_property("rect").unwrap(); prop.set_f32(0, 150.).unwrap(); - let code = vec![Op::Sub(( - Box::new(Op::LoadVar("h".to_string())), - Box::new(Op::ConstFloat32(60.)), - ))]; - prop.set_expr(1, code).unwrap(); - let code = vec![Op::Sub(( - Box::new(Op::LoadVar("w".to_string())), - Box::new(Op::ConstFloat32(120.)), - ))]; - prop.set_expr(2, code).unwrap(); + prop.set_f32(1, 150.).unwrap(); + prop.set_f32(2, 380.).unwrap(); + //let code = vec![Op::Sub(( + // Box::new(Op::LoadVar("h".to_string())), + // Box::new(Op::ConstFloat32(60.)), + //))]; + //prop.set_expr(1, code).unwrap(); + //let code = vec![Op::Sub(( + // Box::new(Op::LoadVar("w".to_string())), + // Box::new(Op::ConstFloat32(120.)), + //))]; + //prop.set_expr(2, code).unwrap(); prop.set_f32(3, 60.).unwrap(); node.set_property_f32("baseline", 40.).unwrap(); node.set_property_f32("font_size", 20.).unwrap(); + node.set_property_f32("font_size", 40.).unwrap(); node.set_property_str("text", "hello king!๐Ÿ˜๐Ÿ†jelly ๐Ÿ†1234").unwrap(); let prop = node.get_property("text_color").unwrap(); prop.set_f32(0, 1.).unwrap(); @@ -357,6 +360,7 @@ impl App { prop.set_null(0).unwrap(); prop.set_null(1).unwrap(); node.set_property_u32("z_index", 1).unwrap(); + node.set_property_bool("debug", true).unwrap(); drop(sg); let pimpl = EditBox::new( diff --git a/bin/darkwallet/src/gfx2.rs b/bin/darkwallet/src/gfx2.rs index 33d1aa064..035c6507b 100644 --- a/bin/darkwallet/src/gfx2.rs +++ b/bin/darkwallet/src/gfx2.rs @@ -139,6 +139,13 @@ impl Rectangle { point.y <= self.y + self.h } + pub fn rhs(&self) -> f32 { + self.x + self.w + } + pub fn bhs(&self) -> f32 { + self.y + self.h + } + pub fn top_left(&self) -> Point { Point { x: self.x, y: self.y } } diff --git a/bin/darkwallet/src/mesh.rs b/bin/darkwallet/src/mesh.rs index b5d6a608f..1e8992c47 100644 --- a/bin/darkwallet/src/mesh.rs +++ b/bin/darkwallet/src/mesh.rs @@ -34,26 +34,47 @@ impl MeshBuilder { } pub fn append(&mut self, mut verts: Vec, indices: Vec) { - if let Some(clipper) = &self.clipper { - for vert in &mut verts { - let mut vpos = vert.pos(); - clipper.clip_point(&mut vpos); - vert.set_pos(&vpos); - } - } - let mut indices = indices.into_iter().map(|i| i + self.verts.len() as u16).collect(); self.verts.append(&mut verts); self.indices.append(&mut indices); } pub fn draw_box(&mut self, obj: &Rectangle, color: Color, uv: &Rectangle) { - let (x1, y1) = obj.top_left().unpack(); - let (x2, y2) = obj.bottom_right().unpack(); + let clipped = match &self.clipper { + Some(clipper) => { + let Some(clipped) = clipper.clip(&obj) else { + return; + }; + clipped + } + None => obj.clone(), + }; + + let (x1, y1) = clipped.top_left().unpack(); + let (x2, y2) = clipped.bottom_right().unpack(); let (u1, v1) = uv.top_left().unpack(); let (u2, v2) = uv.bottom_right().unpack(); + // Interpolate UV coords + assert!(obj.w >= clipped.w); + assert!(obj.h >= clipped.h); + + let i = (clipped.x - obj.x) / obj.w; + let clip_u1 = u1 + i*(u2 - u1); + + let i = (clipped.rhs() - obj.x) / obj.w; + let clip_u2 = u1 + i*(u2 - u1); + + let i = (clipped.y - obj.y) / obj.h; + let clip_v1 = v1 + i*(v2 - v1); + + let i = (clipped.bhs() - obj.y) / obj.h; + let clip_v2 = v1 + i*(v2 - v1); + + let (u1, u2) = (clip_u1, clip_u2); + let (v1, v2) = (clip_v1, clip_v2); + let verts = vec![ // top left Vertex { pos: [x1, y1], color, uv: [u1, v1] }, diff --git a/bin/darkwallet/src/ui/editbox.rs b/bin/darkwallet/src/ui/editbox.rs index 79db95ddc..3a0267b85 100644 --- a/bin/darkwallet/src/ui/editbox.rs +++ b/bin/darkwallet/src/ui/editbox.rs @@ -246,18 +246,21 @@ impl EditBox { /// Called whenever the text or any text property changes. /// Not related to cursor, text highlighting or bounding (clip) rects. - async fn regen_mesh(&self, clip: &Rectangle) -> TextRenderInfo { + async fn regen_mesh(&self, mut clip: Rectangle) -> TextRenderInfo { + clip.x = 0.; + clip.y = 0.; + let text = self.text.get(); let font_size = self.font_size.get(); let text_color = self.text_color.get(); let baseline = self.baseline.get(); let debug = self.debug.get(); - debug!(target: "ui::editbox", "Rendering text '{}'", text); + debug!(target: "ui::editbox", "Rendering text '{}' clip={:?}", text, clip); let glyphs = self.glyphs.lock().unwrap().clone(); let atlas = text2::make_texture_atlas(&self.render_api, font_size, &glyphs).await.unwrap(); - let mut mesh = MeshBuilder::new(); + let mut mesh = MeshBuilder::with_clip(clip.clone()); let mut glyph_pos_iter = GlyphPositionIter::new(font_size, &glyphs, baseline); for ((uv_rect, glyph_rect), glyph) in atlas.uv_rects.into_iter().zip(glyph_pos_iter).zip(glyphs.iter()) @@ -270,6 +273,10 @@ impl EditBox { mesh.draw_box(&glyph_rect, color, &uv_rect); } + if debug { + mesh.draw_outline(&clip, COLOR_BLUE, 1.); + } + let mesh = mesh.alloc(&self.render_api).await.unwrap(); TextRenderInfo { mesh, texture_id: atlas.texture_id } @@ -438,11 +445,14 @@ impl EditBox { panic!("Node {:?} bad rect property", node); }; + rect.x += parent_rect.x; + rect.y += parent_rect.y; + let render_info = self.render_info.lock().unwrap().clone(); let render_info = match render_info { Some(render_info) => render_info, None => { - let render_info = self.regen_mesh(&rect).await; + let render_info = self.regen_mesh(rect.clone()).await; *self.render_info.lock().unwrap() = Some(render_info.clone()); render_info } @@ -455,9 +465,6 @@ impl EditBox { num_elements: render_info.mesh.num_elements, }; - rect.x += parent_rect.x; - rect.y += parent_rect.x; - let off_x = rect.x / parent_rect.w; let off_y = rect.y / parent_rect.h; let scale_x = 1. / parent_rect.w;