Skip to content

Commit

Permalink
fix or refined for radial gradient rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
mhfan committed May 9, 2024
1 parent 241d7ee commit 41171e4
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 28 deletions.
16 changes: 11 additions & 5 deletions src/nanovg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* Copyright (c) 2023 M.H.Fan, All rights reserved. *
****************************************************************/

#![cfg_attr(coverage_nightly, feature(coverage_attribute))]

use std::{collections::VecDeque, time::Instant, error::Error};
use femtovg::{renderer::OpenGl, Canvas, Path, Paint, Color};

Expand Down Expand Up @@ -98,6 +100,7 @@ fn get_renderer() -> Result<OpenGl, Box<dyn Error>> {

use winit::{window::Window, event_loop::EventLoop};

#[cfg_attr(coverage_nightly, coverage(off))] //#[cfg(not(tarpaulin_include))]
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"));
Expand All @@ -107,12 +110,12 @@ fn main() -> Result<(), Box<dyn Error>> {
let mut prevt = Instant::now();
let path = std::env::args().nth(1).unwrap_or("data/tiger.svg".to_owned());
let mut fontdb = usvg::fontdb::Database::new(); fontdb.load_system_fonts();
let tree = usvg::Tree::from_data(&std::fs::read(&path)?,
let tree = usvg::Tree::from_data(&std::fs::read(path)?,
&usvg::Options::default(), &fontdb)?;

let mut coll = Vec::with_capacity(tree.root().children().len());
convert_nodes(&mut coll, tree.root(), &usvg::Transform::default());
println!("Load/Parse/Convert {path} in {:.2}s, {} paths, used {}kB memory",
println!("Load/Parse/Convert in {:.2}s, {} paths used {}kB memory",
(Instant::now() - prevt).as_secs_f32(), coll.len(), coll.iter().fold(0,
|sum, elem| sum + elem.0.size() + std::mem::size_of_val(elem)) / 1000);
// XXX: seems no way to get size of stops in PaintFlavor
Expand Down Expand Up @@ -397,9 +400,12 @@ fn convert_paint(paint: &usvg::Paint,
usvg::Paint::LinearGradient(grad) =>
Paint::linear_gradient_stops(grad.x1(), grad.y1(), grad.x2(), grad.y2(),
convert_stops(grad.stops(), opacity)),
usvg::Paint::RadialGradient(grad) =>
Paint::radial_gradient_stops(grad.cx(), grad.cy(), 1., grad.r().get(),
convert_stops(grad.stops(), opacity)), // grad.fx(), grad.fy(),
usvg::Paint::RadialGradient(grad) => {
let (dx, dy) = (grad.cx() - grad.fx(), grad.cy() - grad.fy());
let radius = (dx * dx + dy * dy).sqrt(); // XXX: 1.
Paint::radial_gradient_stops(grad.fx(), grad.fy(), radius, grad.r().get(),
convert_stops(grad.stops(), opacity))
}
}))
}

11 changes: 5 additions & 6 deletions src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,9 @@ fn style_to_paint<'a, R: io::Read, W: io::Write>(img: &TinyVG<R, W>,
}
Style::RadialGradient { points, cindex } => {
let (dx, dy) = (points.1.x - points.0.x, points.1.y - points.0.y);
let radius = if dx.abs() < f32::EPSILON { dy.abs() }
else if dy.abs() < f32::EPSILON { dx.abs() }
else { (dx * dx + dy * dy).sqrt() };

paint.shader = skia::RadialGradient::new(points.0.into(), points.1.into(), radius,
paint.shader = skia::RadialGradient::new(points.0.into(), points.0.into(),
(dx * dx + dy * dy).sqrt(),
vec![ skia::GradientStop::new(0.0, img.lookup_color(cindex.0).into()),
skia::GradientStop::new(1.0, img.lookup_color(cindex.1).into()),
], skia::SpreadMode::Pad, trfm)
Expand All @@ -206,14 +204,15 @@ fn style_to_paint<'a, R: io::Read, W: io::Write>(img: &TinyVG<R, W>,
trait PathBuilderExt {
fn arc_to(&mut self, radius: &(f32, f32), rotation: f32,
large: bool, sweep: bool, target: &Point);
}
} // https://github.com/RazrFalcon/resvg/blob/master/crates/usvg/src/parser/shapes.rs#L287

// SVG arc to Canvas arc: https://github.com/nical/lyon/blob/main/crates/geom/src/arc.rs
impl PathBuilderExt for skia::PathBuilder {
fn arc_to(&mut self, radius: &(f32, f32), rotation: f32,
large: bool, sweep: bool, target: &Point) {
let prev = self.last_point().unwrap();

let svg_arc = kurbo::SvgArc { // lyon_geom: https://github.com/nical/lyon
let svg_arc = kurbo::SvgArc {
from: kurbo::Point::new(prev.x as _, prev.y as _),
to: kurbo::Point::new(target.x as _, target.y as _),
radii: kurbo::Vec2 ::new(radius.0 as _, radius.1 as _),
Expand Down
7 changes: 2 additions & 5 deletions src/render_b2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,9 @@ fn convert_style<R: io::Read, W: io::Write>(img: &TinyVG<R, W>,
}
Style::RadialGradient { points, cindex } => {
let (dx, dy) = (points.1.x - points.0.x, points.1.y - points.0.y);
let radius = if dx.abs() < f32::EPSILON { dy.abs() }
else if dy.abs() < f32::EPSILON { dx.abs() }
else { (dx * dx + dy * dy).sqrt() };

let mut radial = BLGradient::new(
&BLRadialGradientValues::new(&points.0.into(), &points.1.into(), radius));
let mut radial = BLGradient::new(&BLRadialGradientValues::new(
&points.0.into(), &points.0.into(), (dx * dx + dy * dy).sqrt()));
radial.addStop(0.0, img.lookup_color(cindex.0).into());
radial.addStop(1.0, img.lookup_color(cindex.1).into());
Box::new(radial) //radial.scale(scale, scale);
Expand Down
9 changes: 5 additions & 4 deletions src/render_evg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,13 +176,14 @@ fn style_to_stencil<R: io::Read, W: io::Write>(img: &TinyVG<R, W>, style: &Style
sten //sten.set_matrix(trfm);
}
Style::RadialGradient { points, cindex } => {
let (dx, dy) = (points.1.x - points.0.x, points.1.y - points.0.y);
let radius = (dx * dx + dy * dy).sqrt();
let radius = GF_Point2D { x: radius.into(), y: radius.into() };

let sten = Stencil::new(GF_STENCIL_RADIAL_GRADIENT);
let radius = GF_Point2D {
x: (points.1.x - points.0.x).abs().into(),
y: (points.1.y - points.0.y).abs().into() };
sten.push_interpolation(0.into(), img.lookup_color(cindex.0).into());
sten.push_interpolation(1.into(), img.lookup_color(cindex.1).into());
sten.set_radial(points.0.into(), points.1.into(), radius);
sten.set_radial(points.0.into(), points.0.into(), radius);
sten //sten.set_matrix(trfm);
}
}
Expand Down
16 changes: 8 additions & 8 deletions wcnvs/src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,11 @@ fn convert_paint(ctx2d: &Contex2d, paint: &usvg::Paint,
}); linear.into()
}
usvg::Paint::RadialGradient(grad) => {
let radial = ctx2d.create_radial_gradient(
grad.cx() as _, grad.cy() as _, 1., // XXX:
grad.fx() as _, grad.fy() as _, grad.r().get() as _).unwrap();
let (dx, dy) = (grad.cx() - grad.fx(), grad.cy() - grad.fy());
let radius = (dx * dx + dy * dy).sqrt();
let radial = ctx2d.create_radial_gradient(
grad.fx() as _, grad.fy() as _, radius as _, // XXX: 1.,
grad.cx() as _, grad.cy() as _, grad.r().get() as _).unwrap();

grad.stops().iter().for_each(|stop| { let _ = radial.add_color_stop(0.0,
&to_css_color(stop.color(), stop.opacity() * opacity));
Expand Down Expand Up @@ -274,7 +276,7 @@ fn process_segcmd(path: &Path2d, cmd: &SegInstr, last_point: &mut Point) {

fn wcns_arc_to(path: &Path2d, start: &Point, radius: &(f32, f32),
rotation: f32, large: bool, sweep: bool, end: &Point) {
let svg_arc = kurbo::SvgArc { // lyon_geom: https://github.com/nical/lyon
let svg_arc = kurbo::SvgArc {
to: kurbo::Point::new(end.x as _, end.y as _),
from: kurbo::Point::new(start.x as _, start.y as _),
radii: kurbo::Vec2 ::new(radius.0 as _, radius.1 as _),
Expand Down Expand Up @@ -305,13 +307,11 @@ fn convert_style<R: io::Read, W: io::Write>(img: &TinyVG<R, W>,
} // don't need to scale, since created in context
Style::RadialGradient { points, cindex } => {
let (dx, dy) = (points.1.x - points.0.x, points.1.y - points.0.y);
let radius = if dx.abs() < f32::EPSILON { dy.abs() }
else if dy.abs() < f32::EPSILON { dx.abs() }
else { (dx * dx + dy * dy).sqrt() };
let radius = (dx * dx + dy * dy).sqrt();

let radial = ctx2d.create_radial_gradient(
points.0.x as _, points.0.y as _, 1., // XXX:
points.1.x as _, points.1.y as _, radius as _).unwrap();
points.0.x as _, points.0.y as _, radius as _).unwrap();
let _ = radial.add_color_stop(0.0, &to_css_color(img, cindex.0));
let _ = radial.add_color_stop(1.0, &to_css_color(img, cindex.1)); radial.into()
}
Expand Down

0 comments on commit 41171e4

Please sign in to comment.