Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ wasm-bindgen = "0.2.78"

[target.'cfg(target_arch = "wasm32")'.dependencies.web-sys]
version = "0.3.55"
features = ["CanvasRenderingContext2d", "Document", "Element", "HtmlCanvasElement", "ImageData", "Window"]
features = ["CanvasRenderingContext2d", "Document", "Element", "HtmlCanvasElement", "ImageData", "OffscreenCanvas", "Window"]

[target.'cfg(target_os = "redox")'.dependencies]
redox_syscall = "0.3"
Expand Down
22 changes: 22 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,28 @@ impl Surface {
})
}

/// Creates a new instance of this struct, using the provided [`HtmlCanvasElement`](web_sys::HtmlCanvasElement).
#[cfg(target_arch = "wasm32")]
pub fn from_canvas(canvas: web_sys::HtmlCanvasElement) -> Result<Self, SoftBufferError> {
let imple = SurfaceDispatch::Web(web::WebImpl::from_canvas(canvas)?);

Ok(Self {
surface_impl: Box::new(imple),
})
}
Comment on lines +238 to +246
Copy link
Member

Choose a reason for hiding this comment

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

The general pattern in winit is to make this an extension trait on the existing type. Could we do that here?


/// Creates a new instance of this struct, using the provided [`HtmlCanvasElement`](web_sys::OffscreenCanvas).
#[cfg(target_arch = "wasm32")]
pub fn from_offscreen_canvas(
offscreen_canvas: web_sys::OffscreenCanvas,
Copy link
Member

Choose a reason for hiding this comment

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

I'd rather avoid exposing a public dependency on web-sys if at all possible (in case we decide to move to stdweb or something). Is there a way of representing these types without web-sys?

Copy link
Member

Choose a reason for hiding this comment

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

I don't know of a way to avoid that. Even Winit does it.

As far as I know stdweb is dead, but if you know of an alternative to the wasm-bindgen ecosystem I would be very interested!

Copy link
Member

Choose a reason for hiding this comment

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

I forgot to mention, it is actually possible to represent these types without web-sys: using JsValue.
But this would still require wasm-bindgen as a public dependency, which doesn't really help if we want to change to an alternative later.

) -> Result<Self, SoftBufferError> {
let imple = SurfaceDispatch::Web(web::WebImpl::from_offscreen_canvas(offscreen_canvas)?);

Ok(Self {
surface_impl: Box::new(imple),
})
}

/// Shows the given buffer with the given width and height on the window corresponding to this
/// graphics context. Panics if buffer.len() ≠ width*height. If the size of the buffer does
/// not match the size of the window, the buffer is drawn in the upper-left corner of the window.
Expand Down
42 changes: 37 additions & 5 deletions src/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use wasm_bindgen::JsCast;
use web_sys::CanvasRenderingContext2d;
use web_sys::HtmlCanvasElement;
use web_sys::ImageData;
use web_sys::OffscreenCanvas;

use crate::SoftBufferError;

Expand Down Expand Up @@ -35,8 +36,13 @@ impl WebDisplayImpl {
}
}

enum Canvas {
HtmlCanvasElement(HtmlCanvasElement),
OffscreenCanvas(OffscreenCanvas),
}

pub struct WebImpl {
canvas: HtmlCanvasElement,
canvas: Canvas,
ctx: CanvasRenderingContext2d,
}

Expand All @@ -56,8 +62,26 @@ impl WebImpl {
// We already made sure this was a canvas in `querySelector`.
.unchecked_into();

let ctx = canvas
.get_context("2d")
Self::new_internal(Canvas::HtmlCanvasElement(canvas))
}

pub(crate) fn from_canvas(canvas: HtmlCanvasElement) -> Result<Self, SoftBufferError> {
Self::new_internal(Canvas::HtmlCanvasElement(canvas))
}

pub(crate) fn from_offscreen_canvas(
offscreen_canvas: OffscreenCanvas,
) -> Result<Self, SoftBufferError> {
Self::new_internal(Canvas::OffscreenCanvas(offscreen_canvas))
}

fn new_internal(canvas: Canvas) -> Result<Self, SoftBufferError> {
let ctx = match &canvas {
Canvas::HtmlCanvasElement(canvas) => canvas.get_context("2d"),
Canvas::OffscreenCanvas(canvas) => canvas.get_context("2d"),
};

let ctx = ctx
.map_err(|_| {
SoftBufferError::PlatformError(
Some("Canvas already controlled using `OffscreenCanvas`".into()),
Expand All @@ -77,8 +101,16 @@ impl WebImpl {
}

pub(crate) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
self.canvas.set_width(width.into());
self.canvas.set_height(height.into());
match &self.canvas {
Canvas::HtmlCanvasElement(canvas) => {
canvas.set_width(width.into());
canvas.set_height(height.into());
}
Canvas::OffscreenCanvas(canvas) => {
canvas.set_width(width.into());
canvas.set_height(height.into());
}
}

let bitmap: Vec<_> = buffer
.iter()
Expand Down