Merge branch 'master' of https://github.com/servo/pathfinder into PR-pdf

This commit is contained in:
Sebastian K 2020-07-07 22:13:57 +03:00
commit dec6fa05f0
10 changed files with 506 additions and 101 deletions

168
Cargo.lock generated
View File

@ -2,9 +2,9 @@
# It is not intended for manual editing.
[[package]]
name = "addr2line"
version = "0.12.2"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "602d785912f476e480434627e8732e6766b760c045bbf897d9dfaa9f4fbd399c"
checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072"
dependencies = [
"gimli",
]
@ -135,14 +135,14 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
[[package]]
name = "backtrace"
version = "0.3.49"
version = "0.3.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05100821de9e028f12ae3d189176b41ee198341eb8f369956407fea2f5cc666c"
checksum = "46254cf2fdcdf1badb5934448c1bcbe046a56537b3987d96c51a7afc5d03f293"
dependencies = [
"addr2line",
"cfg-if",
"libc 0.2.71",
"miniz_oxide 0.3.7",
"miniz_oxide 0.4.0",
"object",
"rustc-demangle",
]
@ -233,24 +233,6 @@ dependencies = [
"nix",
]
[[package]]
name = "canvas-webgl-minimal"
version = "0.1.0"
dependencies = [
"pathfinder_canvas",
"pathfinder_color",
"pathfinder_content",
"pathfinder_geometry",
"pathfinder_gl",
"pathfinder_gpu",
"pathfinder_renderer",
"pathfinder_resources",
"pathfinder_webgl",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
]
[[package]]
name = "canvas_glutin_minimal"
version = "0.1.0"
@ -366,6 +348,24 @@ dependencies = [
"sdl2-sys",
]
[[package]]
name = "canvas_webgl_minimal"
version = "0.1.0"
dependencies = [
"pathfinder_canvas",
"pathfinder_color",
"pathfinder_content",
"pathfinder_geometry",
"pathfinder_gl",
"pathfinder_gpu",
"pathfinder_renderer",
"pathfinder_resources",
"pathfinder_webgl",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
]
[[package]]
name = "cbindgen"
version = "0.13.2"
@ -418,9 +418,9 @@ dependencies = [
[[package]]
name = "chrono"
version = "0.4.12"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0fee792e164f78f5fe0c296cc2eb3688a2ca2b70cdff33040922d298203f0c4"
checksum = "c74d84029116787153e02106bf53e66828452a4b325cc8652b788b5967c0a0b6"
dependencies = [
"num-integer",
"num-traits 0.2.12",
@ -701,7 +701,7 @@ dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"lazy_static",
"lazy_static 1.4.0",
"maybe-uninit",
"memoffset",
"scopeguard",
@ -726,7 +726,16 @@ checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
dependencies = [
"autocfg",
"cfg-if",
"lazy_static",
"lazy_static 1.4.0",
]
[[package]]
name = "css-color-parser"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ccb6ce7ef97e6dc6e575e51b596c9889a5cc88a307b5ef177d215c61fd7581d"
dependencies = [
"lazy_static 0.1.16",
]
[[package]]
@ -751,9 +760,9 @@ dependencies = [
[[package]]
name = "deflate"
version = "0.8.4"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7e5d2a2273fed52a7f947ee55b092c4057025d7a3e04e5ecdbd25d6c3fb1bd7"
checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
dependencies = [
"adler32",
"byteorder",
@ -769,7 +778,7 @@ dependencies = [
"gl",
"io-surface",
"jemallocator",
"lazy_static",
"lazy_static 1.4.0",
"metal 0.18.0",
"nfd",
"objc",
@ -851,7 +860,7 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcdf488e3a52a7aa30a05732a3e58420e22acb4b2b75635a561fc6ffbcab59ef"
dependencies = [
"lazy_static",
"lazy_static 1.4.0",
"libc 0.2.71",
"winapi 0.3.9",
"wio",
@ -878,7 +887,7 @@ name = "encoding"
version = "0.1.0"
source = "git+https://github.com/pdf-rs/encoding/#44cafed01e9c40af58bd569a002c379e09da85bf"
dependencies = [
"lazy_static",
"lazy_static 1.4.0",
]
[[package]]
@ -950,7 +959,7 @@ checksum = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e"
[[package]]
name = "font"
version = "0.1.0"
source = "git+https://github.com/pdf-rs/font/#17d3c1d19d937440c760c79be373798326f02bcb"
source = "git+https://github.com/pdf-rs/font/#4c32bbab70d077cbf2322f500bb8c1a8f611fb75"
dependencies = [
"brotli-decompressor",
"decorum",
@ -985,7 +994,7 @@ dependencies = [
"dwrote",
"float-ord",
"freetype",
"lazy_static",
"lazy_static 1.4.0",
"libc 0.2.71",
"log",
"pathfinder_geometry",
@ -1090,9 +1099,9 @@ dependencies = [
[[package]]
name = "gimli"
version = "0.21.0"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc8e0c9bce37868955864dbecd2b1ab2bdf967e6f28066d65aaac620444b65c"
checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724"
[[package]]
name = "gl"
@ -1156,7 +1165,7 @@ dependencies = [
"glutin_gles2_sys",
"glutin_glx_sys",
"glutin_wgl_sys",
"lazy_static",
"lazy_static 1.4.0",
"libloading 0.5.2",
"log",
"objc",
@ -1264,9 +1273,9 @@ dependencies = [
[[package]]
name = "hermit-abi"
version = "0.1.14"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909"
checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9"
dependencies = [
"libc 0.2.71",
]
@ -1324,9 +1333,9 @@ dependencies = [
[[package]]
name = "instant"
version = "0.1.5"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69da7ce1490173c2bf4d26bc8be429aaeeaf4cce6c4b970b7949651fa17655fe"
checksum = "5b141fdc7836c525d4d594027d318c84161ca17aaf8113ab1f81ab93ae897485"
dependencies = [
"js-sys",
"wasm-bindgen",
@ -1431,9 +1440,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "jpeg-decoder"
version = "0.1.19"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b47b4c4e017b01abdc5bcc126d2d1002e5a75bbe3ce73f9f4f311a916363704"
checksum = "cc797adac5f083b8ff0ca6f6294a999393d76e197c36488e2ef732c4715f6fa3"
dependencies = [
"byteorder",
"rayon",
@ -1482,6 +1491,12 @@ dependencies = [
"arrayvec",
]
[[package]]
name = "lazy_static"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf186d1a8aa5f5bee5fd662bc9c1b949e0259e1bcc379d1f006847b0080c7417"
[[package]]
name = "lazy_static"
version = "1.4.0"
@ -1992,7 +2007,7 @@ dependencies = [
"cloudabi",
"libc 0.2.71",
"redox_syscall",
"smallvec 1.4.0",
"smallvec 1.4.1",
"winapi 0.3.9",
]
@ -2003,7 +2018,7 @@ dependencies = [
"egl",
"gl",
"jni",
"lazy_static",
"lazy_static 1.4.0",
"pathfinder_demo",
"pathfinder_geometry",
"pathfinder_gl",
@ -2068,7 +2083,7 @@ dependencies = [
"pathfinder_geometry",
"pathfinder_simd",
"quickcheck",
"smallvec 1.4.0",
"smallvec 1.4.1",
]
[[package]]
@ -2175,7 +2190,7 @@ dependencies = [
"pathfinder_svg",
"pathfinder_ui",
"rayon",
"smallvec 1.4.0",
"smallvec 1.4.1",
"usvg",
]
@ -2225,7 +2240,7 @@ dependencies = [
"rayon",
"serde",
"serde_json",
"smallvec 1.4.0",
"smallvec 1.4.1",
"vec_map",
]
@ -2294,6 +2309,25 @@ dependencies = [
"serde_json",
]
[[package]]
name = "pathfinder_web_canvas"
version = "0.1.0"
dependencies = [
"css-color-parser",
"pathfinder_canvas",
"pathfinder_color",
"pathfinder_content",
"pathfinder_geometry",
"pathfinder_gl",
"pathfinder_gpu",
"pathfinder_renderer",
"pathfinder_resources",
"pathfinder_webgl",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
]
[[package]]
name = "pathfinder_webgl"
version = "0.1.0"
@ -2313,7 +2347,7 @@ dependencies = [
[[package]]
name = "pdf"
version = "0.7.0"
source = "git+https://github.com/pdf-rs/pdf#2beb20e6396722a1a6771d0caabc4fe6e05b671c"
source = "git+https://github.com/pdf-rs/pdf#249b9b0ac7d508344c2cdffd48c9e031763d0405"
dependencies = [
"byteorder",
"chrono",
@ -2335,7 +2369,7 @@ dependencies = [
[[package]]
name = "pdf_derive"
version = "0.1.19"
source = "git+https://github.com/pdf-rs/pdf#2beb20e6396722a1a6771d0caabc4fe6e05b671c"
source = "git+https://github.com/pdf-rs/pdf#249b9b0ac7d508344c2cdffd48c9e031763d0405"
dependencies = [
"quote 1.0.7",
"syn 1.0.33",
@ -2344,7 +2378,7 @@ dependencies = [
[[package]]
name = "pdf_render"
version = "0.1.0"
source = "git+https://github.com/pdf-rs/pdf#2beb20e6396722a1a6771d0caabc4fe6e05b671c"
source = "git+https://github.com/pdf-rs/pdf#249b9b0ac7d508344c2cdffd48c9e031763d0405"
dependencies = [
"encoding",
"font",
@ -2522,7 +2556,7 @@ dependencies = [
"crossbeam-deque",
"crossbeam-queue",
"crossbeam-utils",
"lazy_static",
"lazy_static 1.4.0",
"num_cpus",
]
@ -2672,7 +2706,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f74124048ea86b5cd50236b2443f6f57cf4625a8e8818009b4e50dbb8729a43"
dependencies = [
"bitflags",
"lazy_static",
"lazy_static 1.4.0",
"libc 0.2.71",
"sdl2-sys",
]
@ -2770,7 +2804,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11"
dependencies = [
"lazy_static",
"lazy_static 1.4.0",
"libc 0.2.71",
]
@ -2826,9 +2860,9 @@ dependencies = [
[[package]]
name = "smallvec"
version = "1.4.0"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4"
checksum = "3757cb9d89161a2f24e1cf78efa0c1fcff485d18e3f55e0aa3480824ddaa0f3f"
[[package]]
name = "smithay-client-toolkit"
@ -2839,7 +2873,7 @@ dependencies = [
"andrew",
"bitflags",
"dlib",
"lazy_static",
"lazy_static 1.4.0",
"memmap",
"nix",
"wayland-client 0.21.13",
@ -2856,7 +2890,7 @@ dependencies = [
"andrew",
"bitflags",
"dlib",
"lazy_static",
"lazy_static 1.4.0",
"memmap",
"nix",
"wayland-client 0.23.6",
@ -2921,7 +2955,7 @@ dependencies = [
"euclid",
"gl_generator 0.13.1",
"io-surface",
"lazy_static",
"lazy_static 1.4.0",
"libc 0.2.71",
"log",
"mach",
@ -3064,7 +3098,7 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
dependencies = [
"lazy_static",
"lazy_static 1.4.0",
]
[[package]]
@ -3258,7 +3292,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e53963b583d18a5aa3aaae4b4c1cb535218246131ba22a71f05b518098571df"
dependencies = [
"bumpalo",
"lazy_static",
"lazy_static 1.4.0",
"log",
"proc-macro2 1.0.18",
"quote 1.0.7",
@ -3437,7 +3471,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "520ab0fd578017a0ee2206623ba9ef4afe5e8f23ca7b42f6acfba2f4e66b1628"
dependencies = [
"dlib",
"lazy_static",
"lazy_static 1.4.0",
]
[[package]]
@ -3447,7 +3481,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d94e89a86e6d6d7c7c9b19ebf48a03afaac4af6bc22ae570e9a24124b75358f4"
dependencies = [
"dlib",
"lazy_static",
"lazy_static 1.4.0",
]
[[package]]
@ -3457,7 +3491,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "537500923d50be11d95a63c4cb538145e4c82edf61296b7debc1f94a1a6514ed"
dependencies = [
"dlib",
"lazy_static",
"lazy_static 1.4.0",
]
[[package]]
@ -3525,7 +3559,7 @@ dependencies = [
"cocoa 0.18.5",
"core-foundation 0.6.4",
"core-graphics 0.17.3",
"lazy_static",
"lazy_static 1.4.0",
"libc 0.2.71",
"log",
"objc",
@ -3551,7 +3585,7 @@ dependencies = [
"core-video-sys",
"dispatch",
"instant",
"lazy_static",
"lazy_static 1.4.0",
"libc 0.2.71",
"log",
"mio",
@ -3601,7 +3635,7 @@ version = "2.18.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bf981e3a5b3301209754218f962052d4d9ee97e478f4d26d4a6eced34c1fef8"
dependencies = [
"lazy_static",
"lazy_static 1.4.0",
"libc 0.2.71",
"maybe-uninit",
"pkg-config",

View File

@ -34,6 +34,7 @@ members = [
"utils/gamma-lut",
"utils/svg-to-skia",
"utils/convert",
"web_canvas",
"webgl",
]

View File

@ -89,6 +89,22 @@ impl Canvas {
Canvas { scene }
}
/// Returns the inner scene.
#[inline]
pub fn scene(&self) -> &Scene {
&self.scene
}
/// Returns the inner scene, replacing it with a blank scene.
#[inline]
pub fn take_scene(&mut self) -> Scene {
let view_box = self.scene.view_box();
let mut new_scene = Scene::new();
new_scene.set_view_box(view_box);
mem::replace(&mut self.scene, new_scene)
}
/// Destroys this canvas and returns the inner scene.
#[inline]
pub fn into_scene(self) -> Scene {
self.scene
@ -113,6 +129,12 @@ impl Canvas {
pub fn size(&self) -> Vector2I {
self.scene.view_box().size().ceil().to_i32()
}
pub fn set_size(&mut self, new_size: Vector2I) {
let new_view_box = RectI::new(Vector2I::default(), new_size).to_f32();
self.scene.set_bounds(new_view_box);
self.scene.set_view_box(new_view_box);
}
}
pub struct CanvasRenderingContext2D {
@ -131,11 +153,23 @@ impl CanvasRenderingContext2D {
&self.canvas
}
#[inline]
pub fn canvas_mut(&mut self) -> &mut Canvas {
&mut self.canvas
}
#[inline]
pub fn into_canvas(self) -> Canvas {
self.canvas
}
// Extensions
/// Clears the current canvas.
pub fn clear(&mut self) {
drop(self.canvas.take_scene())
}
// Drawing rectangles
#[inline]
@ -170,26 +204,51 @@ impl CanvasRenderingContext2D {
// Line styles
#[inline]
pub fn line_width(&self) -> f32 {
self.current_state.line_width
}
#[inline]
pub fn set_line_width(&mut self, new_line_width: f32) {
self.current_state.line_width = new_line_width
}
#[inline]
pub fn line_cap(&self) -> LineCap {
self.current_state.line_cap
}
#[inline]
pub fn set_line_cap(&mut self, new_line_cap: LineCap) {
self.current_state.line_cap = new_line_cap
}
#[inline]
pub fn line_join(&self) -> LineJoin {
self.current_state.line_join
}
#[inline]
pub fn set_line_join(&mut self, new_line_join: LineJoin) {
self.current_state.line_join = new_line_join
}
#[inline]
pub fn miter_limit(&self) -> f32 {
self.current_state.miter_limit
}
#[inline]
pub fn set_miter_limit(&mut self, new_miter_limit: f32) {
self.current_state.miter_limit = new_miter_limit
}
#[inline]
pub fn line_dash(&mut self) -> &[f32] {
&self.current_state.line_dash
}
#[inline]
pub fn set_line_dash(&mut self, mut new_line_dash: Vec<f32>) {
// Duplicate and concatenate if an odd number of dashes are present.
@ -202,6 +261,11 @@ impl CanvasRenderingContext2D {
self.current_state.line_dash = new_line_dash
}
#[inline]
pub fn line_dash_offset(&self) -> f32 {
self.current_state.line_dash_offset
}
#[inline]
pub fn set_line_dash_offset(&mut self, new_line_dash_offset: f32) {
self.current_state.line_dash_offset = new_line_dash_offset
@ -657,7 +721,6 @@ impl Path2D {
#[inline]
pub fn move_to(&mut self, to: Vector2F) {
// TODO(pcwalton): Cull degenerate contours.
self.flush_current_contour();
self.current_contour.push_endpoint(to);
}

View File

@ -446,29 +446,6 @@ impl IntoFontCollection for Vec<FontFamily> {
}
}
/*
impl IntoFontCollection for Handle {
#[inline]
fn into_font_collection(self, context: &CanvasFontContext) -> Arc<FontCollection> {
self.load().expect("Failed to load the font!").into_font_collection(context)
}
}
impl<'a> IntoFontCollection for &'a [Handle] {
#[inline]
fn into_font_collection(self, context: &CanvasFontContext) -> Arc<FontCollection> {
let mut font_collection = FontCollection::new();
for handle in self {
let postscript_name = handle.postscript_name();
let font = handle.load().expect("Failed to load the font!");
font_collection.add_family(FontFamily::new_from_font(font));
}
Arc::new(font_collection)
}
}
*/
impl IntoFontCollection for Font {
#[inline]
fn into_font_collection(self, context: &CanvasFontContext) -> Arc<FontCollection> {

View File

@ -301,7 +301,9 @@ impl<W> DemoApp<W> where W: Window {
let viewport = self.window.viewport(self.ui_model.mode.view(0));
self.scene_proxy.set_view_box(RectF::new(Vector2F::zero(),
viewport.size().to_f32()));
self.renderer.set_main_framebuffer_size(self.window_size.device_size());
self.renderer.options_mut().dest =
DestFramebuffer::full_window(self.window_size.device_size());
self.renderer.dest_framebuffer_size_changed();
self.dirty = true;
}
Event::MouseDown(new_position) => {

View File

@ -1,5 +1,5 @@
[package]
name = "canvas-webgl-minimal"
name = "canvas_webgl_minimal"
version = "0.1.0"
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
edition = "2018"
@ -11,7 +11,7 @@ crate-type = ["cdylib", "rlib"]
default = []
[dependencies]
wasm-bindgen = "0.2.63"
wasm-bindgen = "0.2"
[dependencies.pathfinder_canvas]
path = "../../canvas"
@ -45,7 +45,7 @@ version = "0.3"
features = ["Window"]
[dev-dependencies]
wasm-bindgen-test = "0.3.13"
wasm-bindgen-test = "0.3"
[profile.release]
# Tell `rustc` to optimize for small code size.

View File

@ -24,11 +24,6 @@ use web_sys::{self, HtmlCanvasElement, WebGl2RenderingContext};
mod utils;
#[wasm_bindgen]
extern {
fn alert(s: &str);
}
#[wasm_bindgen]
pub fn rust_main() {
utils::set_panic_hook();

View File

@ -290,6 +290,10 @@ impl<D> Renderer<D> where D: Device {
}
}
pub fn destroy(self) -> D {
self.core.device
}
pub fn begin_scene(&mut self) {
self.core.framebuffer_flags = FramebufferFlags::empty();
@ -485,7 +489,8 @@ impl<D> Renderer<D> where D: Device {
}
#[inline]
pub fn set_main_framebuffer_size(&mut self, new_framebuffer_size: Vector2I) {
pub fn dest_framebuffer_size_changed(&mut self) {
let new_framebuffer_size = self.core.main_viewport().size();
if let Some(ref mut debug_ui_presenter) = self.debug_ui_presenter {
debug_ui_presenter.ui_presenter.set_framebuffer_size(new_framebuffer_size);
}

60
web_canvas/Cargo.toml Normal file
View File

@ -0,0 +1,60 @@
[package]
name = "pathfinder_web_canvas"
version = "0.1.0"
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
edition = "2018"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
css-color-parser = "0.1"
wasm-bindgen = "0.2"
[dependencies.pathfinder_canvas]
path = "../canvas"
[dependencies.pathfinder_color]
path = "../color"
[dependencies.pathfinder_content]
path = "../content"
[dependencies.pathfinder_geometry]
path = "../geometry"
[dependencies.pathfinder_gl]
path = "../gl"
[dependencies.pathfinder_gpu]
path = "../gpu"
[dependencies.pathfinder_renderer]
path = "../renderer"
[dependencies.pathfinder_resources]
path = "../resources"
[dependencies.pathfinder_webgl]
path = "../webgl"
[dependencies.web-sys]
version = "0.3"
features = ["Window", "console"]
[dev-dependencies]
wasm-bindgen-test = "0.3"
[profile.release]
# Tell `rustc` to optimize for small code size.
# opt-level = "s"
debug = 1
[package.metadata.wasm-pack.profile.profiling]
wasm-opt = false
dwarf-debug-info = true
[package.metadata.wasm-pack.profile.profiling.wasm-bindgen]
debug-js-glue = false
demangle-name-section = true
dwarf-debug-info = true

268
web_canvas/src/lib.rs Normal file
View File

@ -0,0 +1,268 @@
// pathfinder/web_canvas/src/lib.rs
//
// Copyright © 2020 The Pathfinder Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use css_color_parser::Color;
use pathfinder_canvas::{Canvas, CanvasFontContext, CanvasRenderingContext2D, FillRule, FillStyle};
use pathfinder_canvas::{LineCap, Path2D};
use pathfinder_color::ColorU;
use pathfinder_geometry::rect::RectF;
use pathfinder_geometry::transform2d::Transform2F;
use pathfinder_geometry::vector::{vec2f, vec2i};
use pathfinder_renderer::concurrent::executor::SequentialExecutor;
use pathfinder_renderer::gpu::options::{DestFramebuffer, RendererMode, RendererOptions};
use pathfinder_renderer::gpu::renderer::Renderer;
use pathfinder_renderer::options::BuildOptions;
use pathfinder_resources::embedded::EmbeddedResourceLoader;
use pathfinder_webgl::WebGlDevice;
use std::str::FromStr;
use std::sync::Arc;
use wasm_bindgen::JsCast;
use wasm_bindgen::prelude::*;
use web_sys::{self, HtmlCanvasElement, WebGl2RenderingContext};
#[wasm_bindgen]
pub struct PFCanvasRenderingContext2D {
html_canvas: HtmlCanvasElement,
context: CanvasRenderingContext2D,
renderer: Renderer<WebGlDevice>,
default_path: Path2D,
current_state: WebCanvasState,
saved_states: Vec<WebCanvasState>,
}
#[derive(Clone)]
struct WebCanvasState {
fill_style_string: Arc<String>,
stroke_style_string: Arc<String>,
}
#[wasm_bindgen(js_name = "createContext")]
pub fn create_context(html_canvas: HtmlCanvasElement) -> PFCanvasRenderingContext2D {
let context = html_canvas.get_context("webgl2")
.unwrap()
.unwrap()
.dyn_into::<WebGl2RenderingContext>()
.unwrap();
// Get the real size of the window, taking HiDPI into account.
let framebuffer_size = vec2i(html_canvas.width() as i32, html_canvas.height() as i32);
// Create a Pathfinder GL device.
let pathfinder_device = WebGlDevice::new(context);
// Create a Pathfinder renderer.
let mode = RendererMode::default_for_device(&pathfinder_device);
let options = RendererOptions {
dest: DestFramebuffer::full_window(framebuffer_size),
background_color: None,
..RendererOptions::default()
};
let resource_loader = EmbeddedResourceLoader::new();
let renderer = Renderer::new(pathfinder_device, &resource_loader, mode, options);
// Make a canvas.
let font_context = CanvasFontContext::from_system_source();
let context = Canvas::new(framebuffer_size.to_f32()).get_context_2d(font_context);
PFCanvasRenderingContext2D {
html_canvas,
context,
renderer,
default_path: Path2D::new(),
current_state: WebCanvasState {
fill_style_string: Arc::new("black".to_owned()),
stroke_style_string: Arc::new("black".to_owned()),
},
saved_states: vec![],
}
}
#[wasm_bindgen]
impl PFCanvasRenderingContext2D {
#[wasm_bindgen(js_name = "pfFlush")]
pub fn pf_flush(&mut self) {
// Update framebuffer size.
let framebuffer_size = vec2i(self.html_canvas.width() as i32,
self.html_canvas.height() as i32);
self.renderer.options_mut().dest = DestFramebuffer::full_window(framebuffer_size);
self.renderer.options_mut().background_color = None;
self.renderer.dest_framebuffer_size_changed();
// TODO(pcwalton): This is inefficient!
let mut scene = (*self.context.canvas_mut().scene()).clone();
scene.build_and_render(&mut self.renderer, BuildOptions::default(), SequentialExecutor);
self.context.canvas_mut().set_size(framebuffer_size);
}
#[wasm_bindgen(js_name = "pfClear")]
pub fn pf_clear(&mut self) {
self.context.clear();
}
#[wasm_bindgen(getter)]
pub fn canvas(&self) -> HtmlCanvasElement {
self.html_canvas.clone()
}
// Drawing rectangles
#[wasm_bindgen(js_name = "clearRect")]
pub fn clear_rect(&mut self, x: f32, y: f32, width: f32, height: f32) {
self.context.clear_rect(RectF::new(vec2f(x, y), vec2f(width, height)));
}
#[wasm_bindgen(js_name = "fillRect")]
pub fn fill_rect(&mut self, x: f32, y: f32, width: f32, height: f32) {
self.context.fill_rect(RectF::new(vec2f(x, y), vec2f(width, height)));
}
#[wasm_bindgen(js_name = "strokeRect")]
pub fn stroke_rect(&mut self, x: f32, y: f32, width: f32, height: f32) {
self.context.stroke_rect(RectF::new(vec2f(x, y), vec2f(width, height)));
}
// TODO(pcwalton): Drawing text
// Line styles
#[wasm_bindgen(js_name = "lineWidth")]
#[wasm_bindgen(getter)]
pub fn line_width(&self) -> f32 {
self.context.line_width()
}
#[wasm_bindgen(js_name = "lineWidth")]
#[wasm_bindgen(setter)]
pub fn set_line_width(&mut self, new_line_width: f32) {
self.context.set_line_width(new_line_width);
}
#[wasm_bindgen(js_name = "lineCap")]
#[wasm_bindgen(getter)]
pub fn line_cap(&self) -> String {
match self.context.line_cap() {
LineCap::Butt => "butt".to_owned(),
LineCap::Round => "round".to_owned(),
LineCap::Square => "square".to_owned(),
}
}
#[wasm_bindgen(js_name = "lineCap")]
#[wasm_bindgen(setter)]
pub fn set_line_cap(&mut self, new_line_cap: &str) {
if new_line_cap == "butt" {
self.context.set_line_cap(LineCap::Butt)
} else if new_line_cap == "round" {
self.context.set_line_cap(LineCap::Round)
} else if new_line_cap == "square" {
self.context.set_line_cap(LineCap::Square)
}
}
#[wasm_bindgen(js_name = "fillStyle")]
#[wasm_bindgen(setter)]
pub fn set_fill_style(&mut self, new_style_string: &str) {
if let Some(new_style) = parse_fill_or_stroke_style(new_style_string) {
self.context.set_fill_style(new_style);
self.current_state.fill_style_string = Arc::new(new_style_string.to_owned());
}
}
#[wasm_bindgen(js_name = "strokeStyle")]
#[wasm_bindgen(setter)]
pub fn set_stroke_style(&mut self, new_style_string: &str) {
if let Some(new_style) = parse_fill_or_stroke_style(new_style_string) {
self.context.set_stroke_style(new_style);
self.current_state.stroke_style_string = Arc::new(new_style_string.to_owned());
}
}
pub fn transform(&mut self, a: f32, b: f32, c: f32, d: f32, e: f32, f: f32) {
let new_transform = self.context.transform() * Transform2F::row_major(a, c, e, b, d, f);
self.context.set_transform(&new_transform)
}
pub fn translate(&mut self, x: f32, y: f32) {
self.context.translate(vec2f(x, y))
}
pub fn scale(&mut self, x: f32, y: f32) {
self.context.scale(vec2f(x, y))
}
pub fn rotate(&mut self, angle: f32) {
self.context.rotate(angle)
}
#[wasm_bindgen(js_name = "beginPath")]
pub fn begin_path(&mut self) {
self.default_path = Path2D::new();
}
#[wasm_bindgen(js_name = "moveTo")]
pub fn move_to(&mut self, x: f32, y: f32) {
self.default_path.move_to(vec2f(x, y))
}
#[wasm_bindgen(js_name = "lineTo")]
pub fn line_to(&mut self, x: f32, y: f32) {
self.default_path.line_to(vec2f(x, y))
}
#[wasm_bindgen(js_name = "bezierCurveTo")]
pub fn bezier_curve_to(&mut self, cp1x: f32, cp1y: f32, cp2x: f32, cp2y: f32, x: f32, y: f32) {
self.default_path.bezier_curve_to(vec2f(cp1x, cp1y), vec2f(cp2x, cp2y), vec2f(x, y))
}
#[wasm_bindgen(js_name = "quadraticCurveTo")]
pub fn quadratic_curve_to(&mut self, cpx: f32, cpy: f32, x: f32, y: f32) {
self.default_path.quadratic_curve_to(vec2f(cpx, cpy), vec2f(x, y))
}
#[wasm_bindgen(js_name = "closePath")]
pub fn close_path(&mut self) {
self.default_path.close_path();
}
pub fn fill(&mut self) {
let path = self.default_path.clone();
self.context.fill_path(path, FillRule::Winding);
}
pub fn stroke(&mut self) {
let path = self.default_path.clone();
self.context.stroke_path(path);
}
pub fn save(&mut self) {
self.context.save();
self.saved_states.push(self.current_state.clone());
}
pub fn restore(&mut self) {
if let Some(saved_state) = self.saved_states.pop() {
self.current_state = saved_state;
}
self.context.restore();
}
}
fn parse_fill_or_stroke_style(string: &str) -> Option<FillStyle> {
let css_color = match Color::from_str(string) {
Err(_) => return None,
Ok(css_color) => css_color,
};
let color = ColorU::new(css_color.r,
css_color.g,
css_color.b,
(css_color.a * 255.0).round() as u8);
Some(FillStyle::Color(color))
}