Skip to content

Commit

Permalink
bump dioxus version to v0.6 and refined
Browse files Browse the repository at this point in the history
  • Loading branch information
mhfan committed Dec 15, 2024
1 parent 2b43b16 commit 3645bd2
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 104 deletions.
7 changes: 5 additions & 2 deletions .github/workflows/rust-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,14 @@ jobs:
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

#- uses: taiki-e/install-action@nextest
- uses: cargo-bins/cargo-binstall@main
- name: Run tests
# uses: taiki-e/install-action@nextest
run: cargo t -F "evg,b2d,ftg,ovg,ugl" -- --nocapture #cargo nextest r
env: # DYLD_FALLBACK_LIBRARY_PATH (macOS), PATH (Windows) # XXX:
LD_LIBRARY_PATH: ${{github.workspace}}/3rdparty/amanithvg/lib/linux/x86_64/sre/standalone
run: |
cargo t -F "evg,b2d,ftg,ovg,ugl" -- --nocapture #cargo nextest r
cargo binstall dioxus-cli && cd wcnvs && dx build
- name: Benchmark
run: |
Expand Down
9 changes: 7 additions & 2 deletions wcnvs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
dioxus = { version = "0.5", features = [ "web" ] } # "web", "fullstack", "router"
#dioxus-logger = "0.5"
dioxus = { version = "0.6" } #, features = [ "fullstack", "router" ]
#tracing = "0.1"

js-sys = "0.3"
Expand All @@ -24,5 +23,11 @@ intvg = { path = "..", default-features = false } # git = "https://github.com/mh
kurbo = "0.11" # Bezier curves utils
usvg = "0.44"

[features]
default = ["web"]
desktop = ["dioxus/desktop"]
mobile = ["dioxus/mobile"]
web = ["dioxus/web"]

#[workspace]

37 changes: 18 additions & 19 deletions wcnvs/Dioxus.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@

# cargo install dioxus-cli # --git https://github.com/Dioxuslabs/cli
# cargo binstall dioxus-cli # dx new foo

[application]
name = "wcnvs" # App (Project) Name
out_dir = "dist" # `build` & `serve` dist path
asset_dir = "assets" # resource (assets) file folder
name = "wcnvs" # App (Project) Name

# Dioxus App Default Platform: web, desktop, fullstack, mobile, ssr
default_platform = "web"
# you can also use `dx serve/build --platform XXX` to use other platform
default_platform = "web" # value: web | desktop | mobile

#asset_dir = "assets" # resource (static) file folder
#out_dir = "dist" # Web `build` & `serve` dist path
#hot_reload = true # hot reload by default

[web.wasm_opt]
level = "4" # The level wasm-opt should target. z is the smallest. 4 is the fastest.

[web.app]
title = "Dioxus | WebCanvas" # HTML title tag content
Expand All @@ -16,22 +21,16 @@ title = "Dioxus | WebCanvas" # HTML title tag content

[web.watcher]
reload_html = true # when watcher trigger, regenerate the `index.html`
watch_path = [ "src", "assets" ] # which files or dirs will be watcher monitoring

[web.resource] # include `assets` in web platform
style = ["tailwind.css"] # CSS style file
script = [] # Javascript code file
# which files or dirs will be watcher monitoring
watch_path = [ "src", "assets", "index.html", "tailwind_base.css", "tailwind.config.js" ]

#[web.resource] # include `assets` in web platform
#style = [ "assets/tailwind.css" ] # Additional CSS style files
#script = [] # Additional JavaScript files

[web.resource.dev]
script = [] # Javascript code file, serve: [dev-server] only
script = [] # Javascript code file, serve: [dev-server] only
#script = ["https://cdn.tailwindcss.com"]

[application.tools]
# use binaryen.wasm-opt for output Wasm file
# binaryen just will trigger in `web` platform
#binaryen = { wasm_opt = true }

# default value: input = "public/tailwind.css", config = "src/tailwind.config.js"
#tailwindcss = { input = "tailwind_base.css", config = "tailwind.config.js" }
#tailwindcss = { input = "main.css", config = "tailwind.config.js" }

2 changes: 2 additions & 0 deletions wcnvs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
3. Run the following command in the root of the project to start the tailwind CSS compiler:

```bash
npm install tailwindcss -D #-g

npx tailwindcss -i tailwind_base.css -o assets/tailwind.css --watch
```

Expand Down
9 changes: 0 additions & 9 deletions wcnvs/src/lib.rs

This file was deleted.

40 changes: 19 additions & 21 deletions wcnvs/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@
//#![allow(non_snake_case)]
use dioxus::{prelude::*, web::WebEventExt};

fn main() {
//dioxus_logger::init(tracing::Level::INFO).expect("failed to init logger");
//tracing::info!("starting app of web canvas");
launch(app);
}

// https://github.com/nathan-barry/rust-site/blob/main/src/projects/game_of_life.rs
use web_sys::{HtmlCanvasElement, CanvasRenderingContext2d, Path2d};
use wasm_bindgen::{JsCast/*, prelude::*, closure::Closure*/};

fn main() { launch(app); }
mod render;

fn app() -> Element {
fn draw_canvas(ctx2d: &CanvasRenderingContext2d, data: &[u8], file: &str, cw: u32, ch: u32) {
use {intvg::tinyvg::TVGBuf, instant::Instant};
Expand All @@ -22,7 +19,7 @@ fn app() -> Element {
let tree = usvg::Tree::from_data(data, &usvg_opts).unwrap();

let now = Instant::now();
wcnvs::render::render_svg(&tree, ctx2d, cw, ch);
render::render_svg(&tree, ctx2d, cw, ch);
draw_perf(ctx2d, 1. / now.elapsed().as_secs_f32());

return //intvg::convert::Convert::from_usvg(&data).unwrap()
Expand All @@ -31,27 +28,27 @@ fn app() -> Element {
// file, data.len(), tvg.header); // evt.value()

let now = Instant::now();
wcnvs::render::render_tvg(&tvg, ctx2d, cw, ch);
render::render_tvg(&tvg, ctx2d, cw, ch);
draw_perf(ctx2d, 1. / now.elapsed().as_secs_f32());
}

fn draw_perf(ctx2d: &CanvasRenderingContext2d, fps: f32) {
ctx2d.save(); let _ = ctx2d.reset_transform();
let _ = ctx2d.translate(3., 3.);
ctx2d.set_fill_style(&"#00000080".into());
ctx2d.set_fill_style_str("#00000080");
ctx2d.fill_rect(0., 0., 100., 20.);

ctx2d.set_text_align("right");
ctx2d.set_text_baseline("top");
ctx2d.set_font("14px sans-serif");
ctx2d.set_fill_style(&"#f0f0f0f0".into());
ctx2d.set_fill_style_str("#f0f0f0f0");
let _ = ctx2d.fill_text(&format!("{:.2} FPS", fps), 100. - 10., 2.);
ctx2d.restore();
}

fn draw_smile(ctx2d: &CanvasRenderingContext2d) {
ctx2d.set_fill_style (&"#00ff00ff".into());
ctx2d.set_stroke_style(&"#0000ffff".into());
ctx2d.set_fill_style_str ("#00ff00ff");
ctx2d.set_stroke_style_str("#0000ffff");
use std::f64::consts::{PI, TAU};

if true { ctx2d.begin_path();
Expand Down Expand Up @@ -85,7 +82,7 @@ fn app() -> Element {

let mut file_data: Signal<Option<(Vec<u8>, String)>> = use_signal(|| None);
let init_canvas = move |evt: Event<MountedData>| {
let canvas: HtmlCanvasElement = evt.web_event().clone().dyn_into().unwrap();
let canvas: HtmlCanvasElement = evt.as_web_event().clone().dyn_into().unwrap();
//let canvas: HtmlCanvasElement = web_sys::window().unwrap().document().unwrap()
// .get_element_by_id("canvas").unwrap().dyn_into().unwrap();

Expand Down Expand Up @@ -121,15 +118,16 @@ fn app() -> Element {
.unchecked_ref()).unwrap().observe(&canvas);
};

rsx! { style { dangerous_inner_html: format_args!("{}", // XXX:
//"html { background-color: #15191D; color: #DCDCDC; }
// body { font-family: Courier, Monospace; text-align: center; height: 100vh; }"
" body { display: flex; justify-content: center; align-items: center; height: 96vh; }
#main { display: flex; flex-direction: column;
justify-content: space-evenly; width: 60%; height: 100%; }
#canvas { width: 100%; height: 90%; }"
) }
//html { background-color: #15191D; color: #DCDCDC; }
//body { font-family: Courier, Monospace; text-align: center; height: 100vh; }
let head_style = r"
body { display: flex; justify-content: center; align-items: center; height: 96vh; }
#main { display: flex; flex-direction: column;
justify-content: space-evenly; width: 60%; height: 100%; }
#canvas { width: 100%; height: 90%; }";

//tracing::info!("starting app of web canvas");
rsx! { style { {head_style} }
canvas { id: "canvas", onmounted: init_canvas }
input { r#type: "file", accept: ".tvg, .svg", id: "picker",
onchange: move |evt| async move { if let Some(feng) = &evt.files() {
Expand Down
52 changes: 27 additions & 25 deletions wcnvs/src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ fn render_nodes(ctx2d: &Contex2d, parent: &usvg::Group, trfm: &usvg::Transform)

let fill = path.fill().map(|fill| {
if let Some(style) = convert_paint(ctx2d, fill.paint(),
fill.opacity(), trfm) { ctx2d.set_fill_style(&style); }
fill.opacity(), trfm) { ctx2d.set_fill_style_str(&style); }
match fill.rule() {
usvg::FillRule::NonZero => web_sys::CanvasWindingRule::Nonzero,
usvg::FillRule::EvenOdd => web_sys::CanvasWindingRule::Evenodd,
Expand All @@ -56,7 +56,7 @@ fn render_nodes(ctx2d: &Contex2d, parent: &usvg::Group, trfm: &usvg::Transform)

let stroke = path.stroke().map(|stroke| {
if let Some(style) = convert_paint(ctx2d, stroke.paint(),
stroke.opacity(), trfm) { ctx2d.set_stroke_style(&style); }
stroke.opacity(), trfm) { ctx2d.set_stroke_style_str(&style); }

ctx2d.set_line_width (stroke.width().get() as _);
ctx2d.set_miter_limit(stroke.miterlimit().get() as _);
Expand Down Expand Up @@ -103,27 +103,27 @@ fn render_nodes(ctx2d: &Contex2d, parent: &usvg::Group, trfm: &usvg::Transform)
}

fn convert_paint(ctx2d: &Contex2d, paint: &usvg::Paint,
opacity: usvg::Opacity, _trfm: &usvg::Transform) -> Option<wasm_bindgen::JsValue> {
opacity: usvg::Opacity, _trfm: &usvg::Transform) -> Option<String> {
fn to_css_color(color: usvg::Color, opacity: usvg::Opacity) -> String {
let mut str = format!("#{:0<2x}{:0<2x}{:0<2x}",
color.red, color.green, color.blue);
if opacity != 1.0 { str.push_str(&format!("{:0<2x}",
(opacity.get() * 255.) as u8)); } str
}

Some(match paint { usvg::Paint::Pattern(_) => { // trfm should be applied here
match paint { usvg::Paint::Pattern(_) => { // trfm should be applied here
// TODO: https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas
// refer to render_pattern_pixmap@resvg/crates/resvg/src/path.rs
eprintln!("Not support pattern painting"); return None }
usvg::Paint::Color(color) => to_css_color(*color, opacity).into(),
eprintln!("Not support pattern painting"); None }
usvg::Paint::Color(color) => Some(to_css_color(*color, opacity)),

usvg::Paint::LinearGradient(grad) => {
let linear = ctx2d.create_linear_gradient(
grad.x1() as _, grad.y1() as _, grad.x2() as _, grad.y2() as _);

grad.stops().iter().for_each(|stop| { let _ = linear.add_color_stop(0.0,
&to_css_color(stop.color(), stop.opacity() * opacity));
}); linear.into()
}); linear.as_string()
}
usvg::Paint::RadialGradient(grad) => {
let radial = ctx2d.create_radial_gradient(
Expand All @@ -133,9 +133,9 @@ fn convert_paint(ctx2d: &Contex2d, paint: &usvg::Paint,

grad.stops().iter().for_each(|stop| { let _ = radial.add_color_stop(0.0,
&to_css_color(stop.color(), stop.opacity() * opacity));
}); radial.into()
}); radial.as_string()
}
})
}
}

pub fn render_tvg<R: io::Read, W: io::Write>(tvg: &TinyVG<R, W>,
Expand All @@ -156,23 +156,23 @@ pub fn render_tvg<R: io::Read, W: io::Write>(tvg: &TinyVG<R, W>,
let mut iter = coll.iter();
if let Some(pt) = iter.next() { path.move_to(pt.x as _, pt.y as _) }
iter.for_each(|pt| path.line_to(pt.x as _, pt.y as _));
ctx2d.set_fill_style(&convert_style(tvg, ctx2d, fill)); path.close_path();
ctx2d.set_fill_style_str(&convert_style(tvg, ctx2d, fill)); path.close_path();
ctx2d.fill_with_path_2d(&path);
}
Command::FillRects(FillCMD { fill, coll }) => {
ctx2d.set_fill_style(&convert_style(tvg, ctx2d, fill));
ctx2d.set_fill_style_str(&convert_style(tvg, ctx2d, fill));
coll.iter().for_each(|rect| {
path.rect(rect.x as _, rect.y as _, rect.w as _, rect.h as _);
}); ctx2d.fill_with_path_2d(&path);
}
Command::FillPath (FillCMD { fill, coll }) => {
ctx2d.set_fill_style(&convert_style(tvg, ctx2d, fill));
ctx2d.set_fill_style_str(&convert_style(tvg, ctx2d, fill));
for seg in coll { let _ = segment_to_path(seg, &path);
//if res { return Err("Got line width in fill path segment") }
} ctx2d.fill_with_path_2d(&path);
}
Command::DrawLines(DrawCMD { line, lwidth, coll }) => {
ctx2d.set_stroke_style(&convert_style(tvg, ctx2d, line));
ctx2d.set_stroke_style_str(&convert_style(tvg, ctx2d, line));
ctx2d.set_line_width(*lwidth as _);
coll.iter().for_each(|line| {
path.move_to(line.start.x as _, line.start.y as _);
Expand All @@ -185,13 +185,13 @@ pub fn render_tvg<R: io::Read, W: io::Write>(tvg: &TinyVG<R, W>,
iter.for_each(|pt| path.line_to(pt.x as _, pt.y as _));

ctx2d.set_line_width(*lwidth as _); if !*strip { path.close_path(); }
ctx2d.set_stroke_style(&convert_style(tvg, ctx2d, line));
ctx2d.set_stroke_style_str(&convert_style(tvg, ctx2d, line));
ctx2d.stroke_with_path(&path);
}
Command::DrawPath (DrawCMD {
line, lwidth, coll }) => {
ctx2d.set_line_width(*lwidth as _);
ctx2d.set_stroke_style(&convert_style(tvg, ctx2d, line));
ctx2d.set_stroke_style_str(&convert_style(tvg, ctx2d, line));
for seg in coll { stroke_segment_path(seg, ctx2d); }
}
Command::OutlinePolyg(fill, DrawCMD {
Expand All @@ -201,14 +201,14 @@ pub fn render_tvg<R: io::Read, W: io::Write>(tvg: &TinyVG<R, W>,
iter.for_each(|pt| path.line_to(pt.x as _, pt.y as _));

ctx2d.set_line_width(*lwidth as _); path.close_path();
ctx2d.set_fill_style (&convert_style(tvg, ctx2d, fill));
ctx2d.set_stroke_style(&convert_style(tvg, ctx2d, line));
ctx2d.set_fill_style_str (&convert_style(tvg, ctx2d, fill));
ctx2d.set_stroke_style_str(&convert_style(tvg, ctx2d, line));
ctx2d.fill_with_path_2d(&path); ctx2d.stroke_with_path (&path);
}
Command::OutlineRects(fill, DrawCMD {
line, lwidth, coll }) => {
ctx2d.set_fill_style (&convert_style(tvg, ctx2d, fill));
ctx2d.set_stroke_style(&convert_style(tvg, ctx2d, line));
ctx2d.set_fill_style_str (&convert_style(tvg, ctx2d, fill));
ctx2d.set_stroke_style_str(&convert_style(tvg, ctx2d, line));
ctx2d.set_line_width(*lwidth as _);

coll.iter().for_each(|rect| {
Expand All @@ -218,8 +218,8 @@ pub fn render_tvg<R: io::Read, W: io::Write>(tvg: &TinyVG<R, W>,
}
Command::OutlinePath (fill, DrawCMD {
line, lwidth, coll }) => {
ctx2d.set_fill_style (&convert_style(tvg, ctx2d, fill));
ctx2d.set_stroke_style(&convert_style(tvg, ctx2d, line));
ctx2d.set_fill_style_str (&convert_style(tvg, ctx2d, fill));
ctx2d.set_stroke_style_str(&convert_style(tvg, ctx2d, line));
ctx2d.set_line_width(*lwidth as _);

for seg in coll { let res = segment_to_path(seg, &path);
Expand Down Expand Up @@ -313,27 +313,29 @@ fn wcns_arc_to(path: &Path2d, start: &Point, radius: &(f32, f32),
}

fn convert_style<R: io::Read, W: io::Write>(img: &TinyVG<R, W>,
ctx2d: &Contex2d, style: &Style) -> wasm_bindgen::JsValue {
ctx2d: &Contex2d, style: &Style) -> String {
fn to_css_color<R: io::Read, W: io::Write>(img: &TinyVG<R, W>, idx: u32) -> String {
let color = img.lookup_color(idx);
let mut str = format!("#{:0<2x}{:0<2x}{:0<2x}", color.r, color.g, color.b);
if color.a != 255 { str.push_str(&format!("{:0<2x}", color.a)); } str
}

match style { Style::FlatColor(idx) => to_css_color(img, *idx).into(),
match style { Style::FlatColor(idx) => to_css_color(img, *idx),

Style::LinearGradient { points, cindex } => {
let linear = ctx2d.create_linear_gradient(
points.0.x as _, points.0.y as _, points.1.x as _, points.1.y as _);
let _ = linear.add_color_stop(0.0, &to_css_color(img, cindex.0));
let _ = linear.add_color_stop(1.0, &to_css_color(img, cindex.1)); linear.into()
let _ = linear.add_color_stop(1.0, &to_css_color(img, cindex.1));
linear.as_string().unwrap_or("".to_owned())
} // don't need to scale, since created in context
Style::RadialGradient { points, cindex } => {
let radial = ctx2d.create_radial_gradient( // XXX: 0.
points.0.x as _, points.0.y as _, 1., points.0.x as _, points.0.y as _,
(points.1.x - points.0.x).hypot(points.1.y - points.0.y) 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()
let _ = radial.add_color_stop(1.0, &to_css_color(img, cindex.1));
radial.as_string().unwrap_or("".to_owned())
}
}
}
Expand Down
Loading

0 comments on commit 3645bd2

Please sign in to comment.