Skip to content

Commit

Permalink
code refined and slightly improved
Browse files Browse the repository at this point in the history
  • Loading branch information
mhfan committed May 21, 2024
1 parent 6c21206 commit 2693699
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 72 deletions.
141 changes: 95 additions & 46 deletions src/nanovg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,7 @@ fn main() -> Result<(), Box<dyn Error>> {
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: {} [<path-to-svg>]", 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: {} [<path-to-file>]", std::env::args().next().unwrap());

let event_loop = EventLoop::new()?;
let screen_size = event_loop.primary_monitor().unwrap().size();
Expand All @@ -136,17 +131,30 @@ fn main() -> Result<(), Box<dyn Error>> {
(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<u32>, svg_size: usvg::Size| {
|size: PhysicalSize<u32>, 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);
};
Expand All @@ -159,13 +167,28 @@ fn main() -> Result<(), Box<dyn Error>> {
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,
Expand All @@ -187,30 +210,51 @@ fn main() -> Result<(), Box<dyn Error>> {
.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());
}

_ => ()
},
Expand Down Expand Up @@ -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<f32>, /*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<f32>, 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<T: femtovg::Renderer>(&self, canvas: &mut Canvas<T>, 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::<f32>()
&format!("{:.2} FPS", self.2 / self.0.len() as f32), &paint);
let _ = canvas.fill_text(rw - 10., 0., // self.que.iter().sum::<f32>()
&format!("{:.2} FPS", self.sum / self.que.len() as f32), &paint);
canvas.restore();
}
}
Expand Down
Loading

0 comments on commit 2693699

Please sign in to comment.