use super::drawable::Drawable;
use super::color::Color;
use super::image::Image;
use wasm_bindgen::{JsCast, JsValue};
pub struct Canvas {
pub(crate) context: web_sys::CanvasRenderingContext2d,
pub(crate) element: web_sys::HtmlCanvasElement
}
impl Canvas {
pub fn new() -> Canvas {
let document = web_sys::window().unwrap().document().unwrap();
let element = document
.create_element("canvas")
.unwrap()
.dyn_into::<web_sys::HtmlCanvasElement>()
.unwrap();
let context = element
.get_context("2d")
.unwrap()
.unwrap()
.dyn_into::<web_sys::CanvasRenderingContext2d>()
.unwrap();
Canvas {
context,
element
}
}
pub fn clear_rect(&mut self, (x, y): (f64, f64), (w, h): (f64, f64)) {
self.context.clear_rect(x, y, w, h);
}
pub fn clear(&mut self) {
self.clear_rect(
(0.0, 0.0),
(
f64::from(self.element.width()),
f64::from(self.element.height()),
),
)
}
pub fn clear_with_black(&mut self) {
self.fill_rect(
(0.0, 0.0),
(
f64::from(self.element.width()),
f64::from(self.element.height()),
),
Color::black()
);
}
pub fn clear_with_color(&mut self, color: Color) {
self.fill_rect(
(0.0, 0.0),
(
f64::from(self.element.width()),
f64::from(self.element.height()),
),
color
);
}
pub fn draw(&mut self, object: &impl Drawable) {
object.draw_on_canvas(self);
}
pub fn draw_image(&mut self, (x, y): (f64, f64), image: &Image) {
self.context
.draw_image_with_html_image_element(
image.get_html_element(),
x,
y,
)
.unwrap();
}
pub fn draw_canvas(&mut self, (x, y): (f64, f64), canvas: &Canvas) {
self.context
.draw_image_with_html_canvas_element(
&canvas.element,
x,
y,
)
.unwrap();
}
pub fn get_2d_canvas_rendering_context(&mut self) -> &mut web_sys::CanvasRenderingContext2d {
&mut self.context
}
pub fn fill_rect(&mut self, (x, y): (f64, f64), (w, h): (f64, f64), color: Color) {
self.context.set_fill_style(&JsValue::from_str(&color.to_string()));
self.context.fill_rect(x, y, w, h);
}
pub fn fill_text(&mut self, (x, y): (usize, usize), text: &str, max_width: Option<usize>) {
if let Some(max_width) = max_width {
self.context.fill_text_with_max_width(text, x as f64, y as f64, max_width as f64).unwrap();
} else {
self.context.fill_text(text, x as f64, y as f64).unwrap();
}
}
pub fn set_width(&mut self, width: u32) {
self.element.set_width(width);
}
pub fn set_height(&mut self, height: u32) {
self.element.set_height(height);
}
pub fn get_width(&self) -> u32 {
self.element.width()
}
pub fn get_height(&self) -> u32 {
self.element.height()
}
pub fn get_size(&self) -> (u32, u32) {
(self.element.width(), self.element.height())
}
}
pub enum LineCap {
Butt,
Round,
Square
}
impl ToString for LineCap {
fn to_string(&self) -> String {
match self {
LineCap::Butt => String::from("butt"),
LineCap::Round => String::from("round"),
LineCap::Square => String::from("square"),
}
}
}
pub enum LineJoin {
Round,
Bevel,
Miter,
}
impl ToString for LineJoin {
fn to_string(&self) -> String {
match self {
LineJoin::Miter => String::from("miter"),
LineJoin::Round => String::from("round"),
LineJoin::Bevel => String::from("bevel"),
}
}
}
pub struct LineStyle {
pub color: Color,
pub size: f64,
pub cap: LineCap,
pub join: LineJoin
}
impl LineStyle {
pub fn apply_on_canvas(&self, canvas: &mut Canvas) {
canvas.context.set_line_width(self.size);
canvas.context.set_stroke_style(&JsValue::from_str(&self.color.to_string()));
canvas.context.set_line_cap(&self.cap.to_string());
canvas.context.set_line_join(&self.join.to_string());
}
}
impl Default for LineStyle {
fn default() -> LineStyle {
LineStyle {
color: Color::black(),
size: 3.0,
cap: LineCap::Butt,
join: LineJoin::Miter
}
}
}