Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use wasm-bindgen instead of stdweb #6

Merged
merged 6 commits into from
Jan 7, 2019
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ members = [
"piet-cairo",
"piet-direct2d",
"piet-web",
"piet-web/examples/basic"
]
9 changes: 8 additions & 1 deletion piet-web/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,15 @@ edition = "2018"
keywords = ["graphics", "2d"]
categories = ["rendering::graphics-api", "wasm"]

[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]
kurbo = "0.1.2"
piet = { path = "../piet" }

stdweb = "0.4.12"
wasm-bindgen = "0.2.29"

[dependencies.web-sys]
version = "0.3.6"
features = ["CanvasRenderingContext2d", "CanvasWindingRule"]
8 changes: 4 additions & 4 deletions piet-web/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Running the examples

Generally follow the directions at [stdweb].
Ensure both cargo and [npm] are installed.

`$ cargo install -f cargo-web`
`$ cargo install -f wasm-bindgen`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get this:

$ cargo install -f wasm-bindgen
    Updating crates.io index
  Installing wasm-bindgen v0.2.30
error: specified package has no binaries

I can diagnose this, but I have on my "hapless dev" hat. This is on a Windows 10 box in a git bash shell, and node (10.15.0) and npm are installed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops! It's actually wasm-bindgen-cli. Once it's installed it's just called wasm-bindgen. I will update this.


`$ cargo web start --target=wasm32-unknown-unknown --example basic-web`
`$ cd examples/basic && ./build.sh`

Then navigate browser to local web server.

[stdweb]: https://github.com/koute/stdweb
[npm]: https://www.npmjs.com/get-npm
2 changes: 2 additions & 0 deletions piet-web/examples/basic/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
package-lock.json
18 changes: 18 additions & 0 deletions piet-web/examples/basic/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "piet-web-example"
version = "0.0.1"
authors = ["Ryan Levick <[email protected]>"]
edition = "2018"

[lib]
crate-type = ["cdylib"]

[dependencies]
piet = { path = "../../../piet" }
piet-web = { path = "../.." }
wasm-bindgen = "0.2.29"
kurbo = "0.1.2"

[dependencies.web-sys]
version = "0.3.6"
features = ["CanvasRenderingContext2d", "Window", "Document", "Element", "HtmlElement", "HtmlCanvasElement"]
2 changes: 2 additions & 0 deletions piet-web/examples/basic/basic-web-static/dist/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*
!.gitignore
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
</head>
<body>
<canvas id="canvas"></canvas>
<script src="basic-web.js"></script>
<script src="index.js"></script>
</body>
</html>
5 changes: 5 additions & 0 deletions piet-web/examples/basic/basic-web-static/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const rust = import('./dist/piet_web_example');

rust
.then(m => m.run())
.catch(console.error);
13 changes: 13 additions & 0 deletions piet-web/examples/basic/basic-web-static/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"scripts": {
"build": "webpack",
"serve": "webpack-dev-server"
},
"devDependencies": {
"text-encoding": "^0.7.0",
"html-webpack-plugin": "^3.2.0",
"webpack": "^4.11.1",
"webpack-cli": "^3.1.1",
"webpack-dev-server": "^3.1.0"
}
}
20 changes: 20 additions & 0 deletions piet-web/examples/basic/basic-web-static/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');

module.exports = {
entry: './index.js',
output: {
path: path.resolve(__dirname),
filename: 'index.js',
},
plugins: [
// Have this example work in Edge which doesn't ship `TextEncoder` or
// `TextDecoder` at this time.
new webpack.ProvidePlugin({
TextDecoder: ['text-encoding', 'TextDecoder'],
TextEncoder: ['text-encoding', 'TextEncoder']
})
],
mode: 'development'
};
15 changes: 15 additions & 0 deletions piet-web/examples/basic/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/sh

set -ex

# Build the `hello_world.wasm` file using Cargo/rustc
cargo build --target wasm32-unknown-unknown

# Run the `wasm-bindgen` CLI tool to postprocess the wasm file emitted by the
# Rust compiler to emit the JS support glue that's necessary
wasm-bindgen ../../../target/wasm32-unknown-unknown/debug/piet_web_example.wasm --out-dir basic-web-static/dist

# Finally, package everything up using Webpack and start a server so we can
# browse the result
npm install --prefix basic-web-static
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also has a paper-cut error: works fine if I cd to basic-web-static and do npm install and serve from there, but not from the dir as shown in the batch file. But then it works!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... the --prefix option should take care of that. I don't need to cd into that directory on my machine. Maybe different versions of npm are causing this?

I can change the script to cd into that directory instead. Do you think that will be a more robust solution? (ah... the joys of bash scripting ❤️)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The world of npm is foreign and strange to me, though I have played with it some. Looking at the docs, it looks like prefix sets the path where the artifacts get stored, but not where the package.json is read from. Did you try this from a fresh clone? (my inexperienced experience is that npm tends to litter a lot of files in your working directory)

I'm fine with it cd'ing into the directory. In general I would want to follow "best practices" but have no idea what those are. Not to be too nitpicky, but I think this is kinda important because a lot of people start projects by copying a hello example.

Copy link
Collaborator Author

@rylev rylev Jan 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries on being nitpicky. I 100% that this should be painless for people.

What you said about --prefix is true for global items (installed with -g) but for local cli commands this tells npm in which directory to run. From the docs: "If set on the command line, then it forces non-global commands to run in the specified folder."

I tried from a fresh clone and it worked fine for me.

If you run npm install --prefix basic-web-static from that directory (the $PROJECT_ROOT/piet-web/examples/basic directory), it warns that you don't have a package.json?

I try to avoid using cd in my bash scripts because I've ran into weird issues before, but if that's what's needed to get it working, we can do it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

raphl@DESKTOP-6JFLCBE MINGW64 ~/github/piet/piet-web/examples/basic (rylev-wasm-bindgen)
$ npm -v
6.4.1
$ npm install --prefix basic-web-static
npm ERR! code ENOLOCAL
npm ERR! Could not install from "" as it does not contain a package.json file.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\raphl\AppData\Roaming\npm-cache\_logs\2019-01-07T17_39_10_724Z-debug.log

I'm not sure what's going on here, and totally understand wanting to minimize cd'ing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a bug in the windows version of npm: https://npm.community/t/npm-prefix-flag-does-not-work-as-expected-on-windows/3147

I think moving to just using cd is the best choice.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good - I was just about to try it on my Mac, but seems like you've isolated it. That bug is scary, being auto-closed even though it seems valid and with the potential to affect lots of people.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's unfortunately how the web world works. It's pretty fast and loose. The latest commit should fix it (though I just ran into another way things could break that the readme now references).

npm run serve --prefix basic-web-static
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@

use kurbo::{BezPath, Line};

use stdweb::traits::*;
use stdweb::unstable::TryInto;
use stdweb::web::{document, CanvasRenderingContext2d};

use stdweb::web::html_element::CanvasElement;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::{window, HtmlCanvasElement};

use piet::{FillRule, RenderContext};
use piet_web::WebRenderContext;
Expand All @@ -29,22 +27,26 @@ fn draw_pretty_picture<R: RenderContext>(rc: &mut R) {
rc.fill(&path, &brush, FillRule::NonZero);
}

fn main() {
stdweb::initialize();

let canvas: CanvasElement = document()
.query_selector("#canvas")
#[wasm_bindgen]
pub fn run() {
let canvas = window()
.unwrap()
.document()
.unwrap()
.try_into()
.get_element_by_id("canvas")
.unwrap()
.dyn_into::<HtmlCanvasElement>()
.unwrap();
let mut context = canvas
.get_context("2d")
.unwrap()
.unwrap()
.dyn_into::<web_sys::CanvasRenderingContext2d>()
.unwrap();
let mut context: CanvasRenderingContext2d = canvas.get_context().unwrap();

canvas.set_width(canvas.offset_width() as u32);
canvas.set_height(canvas.offset_height() as u32);

let mut piet_context = WebRenderContext::new(&mut context);
draw_pretty_picture(&mut piet_context);

stdweb::event_loop();
}
25 changes: 11 additions & 14 deletions piet-web/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! The Web Canvas backend for the Piet 2D graphics abstraction.

use stdweb::web::{CanvasRenderingContext2d, FillRule};
use wasm_bindgen::JsValue;
use web_sys::{CanvasRenderingContext2d, CanvasWindingRule};

use kurbo::{PathEl, Shape, Vec2};

Expand All @@ -25,15 +26,15 @@ pub enum StrokeStyle {
Default,
}

fn convert_fill_rule(fill_rule: piet::FillRule) -> FillRule {
fn convert_fill_rule(fill_rule: piet::FillRule) -> CanvasWindingRule {
match fill_rule {
piet::FillRule::NonZero => FillRule::NonZero,
piet::FillRule::EvenOdd => FillRule::EvenOdd,
piet::FillRule::NonZero => CanvasWindingRule::Nonzero,
piet::FillRule::EvenOdd => CanvasWindingRule::Evenodd,
}
}

impl<'a> RenderContext for WebRenderContext<'a> {
/// stdweb doesn't have a native Point type, so use kurbo's.
/// wasm-bindgen doesn't have a native Point type, so use kurbo's.
type Point = Vec2;
type Coord = f64;
type Brush = Brush;
Expand All @@ -47,15 +48,11 @@ impl<'a> RenderContext for WebRenderContext<'a> {
Brush::Solid(rgba)
}

fn fill(
&mut self,
shape: &impl Shape,
brush: &Self::Brush,
fill_rule: piet::FillRule,
) {
fn fill(&mut self, shape: &impl Shape, brush: &Self::Brush, fill_rule: piet::FillRule) {
self.set_path(shape);
self.set_brush(brush, true);
self.ctx.fill(convert_fill_rule(fill_rule));
self.ctx
.fill_with_canvas_winding_rule(convert_fill_rule(fill_rule));
}

fn stroke(
Expand Down Expand Up @@ -94,9 +91,9 @@ impl<'a> WebRenderContext<'a> {
)
};
if is_fill {
self.ctx.set_fill_style_color(&color_str);
self.ctx.set_fill_style(&JsValue::from_str(&color_str));
} else {
self.ctx.set_stroke_style_color(&color_str);
self.ctx.set_stroke_style(&JsValue::from_str(&color_str));
}
}
}
Expand Down