From 269369988194c3039f38fa8efffadc4df09791f7 Mon Sep 17 00:00:00 2001 From: MeiHui FAN Date: Tue, 21 May 2024 10:28:48 +0800 Subject: [PATCH] code refined and slightly improved --- src/nanovg.rs | 141 +++++++++++++++++++++++++++++--------------- src/tinyvg.rs | 46 +++++++-------- wcnvs/src/main.rs | 4 +- wcnvs/src/render.rs | 3 + 4 files changed, 122 insertions(+), 72 deletions(-) diff --git a/src/nanovg.rs b/src/nanovg.rs index 4eb7c63..68caaca 100644 --- a/src/nanovg.rs +++ b/src/nanovg.rs @@ -104,12 +104,7 @@ fn main() -> Result<(), Box> { eprintln!(r"{} v{}-g{}, {}, {} 🦀", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"), env!("BUILD_GIT_HASH"), env!("BUILD_TIMESTAMP"), env!("CARGO_PKG_AUTHORS")); //build_time::build_time_local!("%H:%M:%S%:z %Y-%m-%d"), //option_env!("ENV_VAR_NAME"); - println!("Usage: {} []", std::env::args().next().unwrap()); - - let mut fontdb = usvg::fontdb::Database::new(); fontdb.load_system_fonts(); - let path = std::env::args().nth(1).unwrap_or("data/tiger.svg".to_owned()); - let mut tree = usvg::Tree::from_data(&std::fs::read(path)?, - &usvg::Options::default(), &fontdb)?; + println!("Usage: {} []", std::env::args().next().unwrap()); let event_loop = EventLoop::new()?; let screen_size = event_loop.primary_monitor().unwrap().size(); @@ -136,17 +131,30 @@ fn main() -> Result<(), Box> { (window, canvas) }; + /* let mut viewport = rive_rs::Viewport::default(); + let mut scene = None; use inlottie::rive::NanoVG; */ + + let mut fontdb = usvg::fontdb::Database::new(); fontdb.load_system_fonts(); + let path = std::env::args().nth(1).unwrap_or("data/tiger.svg".to_owned()); + let file = std::fs::read(&path)?; let mut tree = None; + + match path.rfind('.').map_or("", |i| &path[1 + i..]) { + "svg" => tree = usvg::Tree::from_data(&file, &usvg::Options::default(), &fontdb).ok(), + //"riv" => scene = NanoVG::new_scene(&file), + _ => eprintln!("File format is not supported: {path}"), + } + let (mut dragging, mut focused, mut mouse) = (false, true, (0., 0.)); let (mut perf, mut prevt) = (PerfGraph::new(), Instant::now()); event_loop.run(|event, target| { let mut resize_canvas = - |size: PhysicalSize, svg_size: usvg::Size| { + |size: PhysicalSize, orig: usvg::Size| { canvas.reset(); mouse = (0., 0.); - let scale = (size.width as f32 / svg_size.width()) - .min(size.height as f32 / svg_size.height()) * 0.95; - canvas.translate((size.width as f32 - scale * svg_size.width()) / 2., - (size.height as f32 - scale * svg_size.height()) / 2.); + let scale = (size.width as f32 / orig.width()) + .min(size.height as f32 / orig.height()) * 0.95; + canvas.translate((size.width as f32 - scale * orig.width()) / 2., + (size.height as f32 - scale * orig.height()) / 2.); canvas.set_size (size.width, size.height, window.scale_factor() as _); canvas.scale(scale, scale); }; @@ -159,13 +167,28 @@ fn main() -> Result<(), Box> { WindowEvent::Resized(size) => { surface.resize(&glctx, size.width .try_into().unwrap(), size.height.try_into().unwrap()); - resize_canvas(size, tree.size()); + if let Some(tree) = &tree { resize_canvas(size, tree.size()); } + + /* if scene.is_some() { + //viewport.resize(scene.width(), scene.height()); + //resize_canvas(size, (scene.width(), scene.height())); + viewport.resize(size.width, size.height); mouse = (0., 0.); + canvas.set_size(size.width, size.height, window.scale_factor() as _); + } */ } WindowEvent::MouseInput { button: MouseButton::Left, state, .. } => match state { - ElementState::Pressed => dragging = true, - ElementState::Released => dragging = false, + ElementState::Pressed => { dragging = true; + /* if let Some(scene) = &mut scene { + scene.pointer_down(mouse.0, mouse.1, &viewport); + } */ + } + ElementState::Released => { dragging = false; + /* if let Some(scene) = &mut scene { + scene.pointer_up (mouse.0, mouse.1, &viewport); + } */ + } }, WindowEvent::Focused(bl) => focused = bl, @@ -187,30 +210,51 @@ fn main() -> Result<(), Box> { .transform_point(position.x as _, position.y as _); canvas.translate(p1.0 - p0.0, p1.1 - p0.1); } mouse = (position.x as _, position.y as _); + + /* if let Some(scene) = &mut scene { + scene.pointer_move(mouse.0, mouse.1, &viewport); + } */ } WindowEvent::DroppedFile(path) => { - tree = usvg::Tree::from_data(&std::fs::read(path).unwrap(), - &usvg::Options::default(), &fontdb).unwrap(); + tree = None; //scene = None; + let file = std::fs::read(&path).unwrap_or(vec![]); + match path.extension().and_then(|ext| ext.to_str()) { + Some("svg") => tree = usvg::Tree::from_data(&file, + &usvg::Options::default(), &fontdb).ok().map(|tree| { + resize_canvas(window.inner_size(), tree.size()); tree }), + + //Some("riv") => scene = NanoVG::new_scene(&file), + _ => eprintln!("File format is not supported: {}", path.display()), + } + //let mut size = window.inner_size(); size.width += 1; size.height += 1; //let _ = window.request_inner_size(size); - resize_canvas(window.inner_size(), tree.size()); window.request_redraw(); } WindowEvent::RedrawRequested => { - let now = Instant::now(); - perf.update((now - prevt).as_secs_f32()); prevt = now; + //let elapsed = prevt.elapsed(); + prevt = Instant::now(); - canvas.clear_rect(0, 0, canvas.width(), - canvas.height(), Color::rgbf(0.3, 0.3, 0.32)); - render_nodes(&mut canvas, &mouse, tree.root(), &usvg::Transform::default()); + /* if let Some(scene) = &mut scene { + if !scene.advance_and_maybe_draw(&mut NanoVG::new(&mut canvas), + elapsed, &mut viewport) { return; } + } */ - perf.render(&mut canvas, 3., 3.); - canvas.flush(); // Tell renderer to execute all drawing commands - #[cfg(not(target_arch = "wasm32"))] + if let Some(tree) = &tree { canvas.clear_rect(0, 0, + canvas.width(), canvas.height(), Color::rgbf(0.3, 0.3, 0.32)); + render_nodes(&mut canvas, &mouse, tree.root(), &usvg::Transform::default()); + } + + perf.render(&mut canvas, 3., 3.); canvas.flush(); + // Tell renderer to execute all drawing commands + + #[cfg(not(target_arch = "wasm32"))] // Display what just rendered surface.swap_buffers(&glctx).expect("Could not swap buffers"); - } // Display what just rendered + + perf.update(prevt.elapsed().as_secs_f32()); + } _ => () }, @@ -275,42 +319,47 @@ fn create_window(event_loop: &EventLoop<()>, title: &str, width: u32, height: u3 let mut canvas = Canvas::new(unsafe { OpenGl::new_from_function_cstr(|s| gl_display.get_proc_address(s) as *const _) }?)?; + #[cfg(target_os = "macos")] let _ = canvas.add_font_dir("/Library/fonts"); canvas.add_font_dir("data/fonts").expect("Cannot add font dir/files"); Ok((window, surface, glctx, canvas)) } -pub struct PerfGraph(VecDeque, /*max: */f32, /*sum: */f32/*, Instant*/); -impl PerfGraph { #[allow(clippy::new_without_default)] - pub fn new() -> Self { Self(VecDeque::with_capacity(100), 0., 0./*, Instant::now()*/) } +pub struct PerfGraph { que: VecDeque, max: f32, sum: f32/*, time: Instant*/ } + +impl PerfGraph { + #[allow(clippy::new_without_default)] pub fn new() -> Self { + Self { que: VecDeque::with_capacity(100), max: 0., sum: 0./*, time: Instant::now()*/ } + } - pub fn update(&mut self, ft: f32) { //let now = Instant::now(); - //let ft = (now - self.1).as_secs_f32(); self.1 = now; - let fps = 1. / ft; if self.1 < fps { self.1 = fps } // (ft + f32::EPSILON) - if self.0.len() == 100 { self.2 -= self.0.pop_front().unwrap_or(0.); } - self.0.push_back(fps); self.2 += fps; + pub fn update(&mut self, ft: f32) { //debug_assert!(f32::EPSILON < ft); + //let ft = self.time.elapsed().as_secs_f32(); self.time = Instant::now(); + let fps = 1. / ft; if self.max < fps { self.max = fps } // (ft + f32::EPSILON) + if self.que.len() == 100 { self.sum -= self.que.pop_front().unwrap_or(0.); } + self.que.push_back(fps); self.sum += fps; } pub fn render(&self, canvas: &mut Canvas, x: f32, y: f32) { let (rw, rh, mut path) = (100., 20., Path::new()); + let mut paint = Paint::color(Color::rgba(0, 0, 0, 128)); path.rect(0., 0., rw, rh); - let mut paint = Paint::color(Color::rgba(240, 240, 240, 255)); - paint.set_text_baseline(femtovg::Baseline::Top); - paint.set_text_align(femtovg::Align::Right); - paint.set_font_size(14.0); - canvas.save(); canvas.reset_transform(); canvas.translate(x, y); - canvas.fill_path(&path, &Paint::color(Color::rgba(0, 0, 0, 128))); + canvas.fill_path(&path, &paint); path = Path::new(); path.move_to(0., rh); - for i in 0..self.0.len() { // self.0[i].min(100.) / 100. - path.line_to(rw * i as f32 / self.0.len() as f32, rh - rh * self.0[i] / self.1); - } path.line_to(rw, rh); - canvas.fill_path(&path, &Paint::color(Color::rgba(255, 192, 0, 128))); + for i in 0..self.que.len() { // self.que[i].min(100.) / 100. + path.line_to(rw * i as f32 / self.que.len() as f32, rh - rh * self.que[i] / self.max); + } path.line_to(rw, rh); paint.set_color(Color::rgba(255, 192, 0, 128)); + canvas.fill_path(&path, &paint); + + paint.set_color(Color::rgba(240, 240, 240, 255)); + paint.set_text_baseline(femtovg::Baseline::Top); + paint.set_text_align(femtovg::Align::Right); + paint.set_font_size(14.0); // some fixed values can be moved into the structure - let _ = canvas.fill_text(rw - 10., 0., // self.0.iter().sum::() - &format!("{:.2} FPS", self.2 / self.0.len() as f32), &paint); + let _ = canvas.fill_text(rw - 10., 0., // self.que.iter().sum::() + &format!("{:.2} FPS", self.sum / self.que.len() as f32), &paint); canvas.restore(); } } diff --git a/src/tinyvg.rs b/src/tinyvg.rs index a5f0366..aa7409e 100644 --- a/src/tinyvg.rs +++ b/src/tinyvg.rs @@ -133,7 +133,7 @@ impl TinyVG { #[allow(clippy::new_without_defau tvgd.header.width = (tvgd.read_range)(reader)? as _; tvgd.header.height = (tvgd.read_range)(reader)? as _; - let color_count = reader.read_var_uint()?; + let color_count = reader.read_varuint()?; tvgd.color_table.reserve_exact(color_count as _); tvgd.header.color_fmt = ColorEncoding::RGBA8888; @@ -176,7 +176,7 @@ impl TinyVG { #[allow(clippy::new_without_defau 1 => Command::FillPolyg(self.read_fillcmd(skind, reader, Self::read_point)?), 2 => Command::FillRects(self.read_fillcmd(skind, reader, Self::read_rect)?), - 3 => { let count = reader.read_var_uint()? + 1; + 3 => { let count = reader.read_varuint()? + 1; let fill= self.read_style(skind, reader)?; let coll = self.read_path(count as _, reader)?; Command::FillPath(FillCMD { fill, coll }) @@ -185,7 +185,7 @@ impl TinyVG { #[allow(clippy::new_without_defau 5 => Command::DrawLoop (self.read_drawcmd(skind, reader, Self::read_point)?, false), 6 => Command::DrawLoop (self.read_drawcmd(skind, reader, Self::read_point)?, true), - 7 => { let count = reader.read_var_uint()? + 1; + 7 => { let count = reader.read_varuint()? + 1; let line= self.read_style(skind, reader)?; let lwidth = self.read_unit(reader)?; let coll = self.read_path(count as _, reader)?; @@ -212,7 +212,7 @@ impl TinyVG { #[allow(clippy::new_without_defau fn read_fillcmd(&self, fill_kind: u8, reader: &mut R, read_fn: impl Fn(&Self, &mut R) -> Result) -> Result> { - let count = reader.read_var_uint()? + 1; + let count = reader.read_varuint()? + 1; let fill = self.read_style(fill_kind, reader)?; let mut coll = Vec::with_capacity(count as _); for _ in 0..count { coll.push(read_fn(self, reader)?); } @@ -221,7 +221,7 @@ impl TinyVG { #[allow(clippy::new_without_defau fn read_drawcmd(&self, line_kind: u8, reader: &mut R, read_fn: impl Fn(&Self, &mut R) -> Result) -> Result> { - let count = reader.read_var_uint()? + 1; + let count = reader.read_varuint()? + 1; let line = self.read_style(line_kind, reader)?; let lwidth = self.read_unit(reader)?; let mut coll = Vec::with_capacity(count as _); @@ -242,7 +242,7 @@ impl TinyVG { #[allow(clippy::new_without_defau fn read_path(&self, count: usize, reader: &mut R) -> Result> { let mut vlen = Vec::with_capacity(count); let mut coll = Vec::with_capacity(count); - for _ in 0..count { vlen.push(reader.read_var_uint()? + 1); } + for _ in 0..count { vlen.push(reader.read_varuint()? + 1); } for len in vlen { coll.push(self.read_segment(len, reader)?); } Ok(coll) } @@ -282,14 +282,14 @@ impl TinyVG { #[allow(clippy::new_without_defau fn read_style(&self, kind: u8, reader: &mut R) -> Result