/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::cell::RefCell; use canvas_traits::canvas::Path; use dom_struct::dom_struct; use js::rust::HandleObject; use script_bindings::str::DOMString; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::Path2DMethods; use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::reflector::{Reflector, reflect_dom_object_with_proto}; use crate::dom::bindings::root::DomRoot; use crate::dom::globalscope::GlobalScope; use crate::script_runtime::CanGc; #[dom_struct] pub(crate) struct Path2D { reflector_: Reflector, #[ignore_malloc_size_of = "Defined in kurbo."] #[no_trace] path: RefCell, } impl Path2D { pub(crate) fn new() -> Path2D { Self { reflector_: Reflector::new(), path: RefCell::new(Path::new()), } } pub(crate) fn new_with_path(other: &Path2D) -> Path2D { Self { reflector_: Reflector::new(), path: other.path.clone(), } } pub(crate) fn new_with_str(path: &str) -> Path2D { Self { reflector_: Reflector::new(), path: RefCell::new(Path::from_svg(path)), } } pub(crate) fn segments(&self) -> Path { self.path.borrow().clone() } } impl Path2DMethods for Path2D { /// fn AddPath(&self, other: &Path2D) { let other = other.segments(); // Step 7. Add all the subpaths in c to a. self.path.borrow_mut().0.extend(other.0); } /// fn ClosePath(&self) { self.path.borrow_mut().close_path(); } /// fn MoveTo(&self, x: f64, y: f64) { self.path.borrow_mut().move_to(x, y); } /// fn LineTo(&self, x: f64, y: f64) { self.path.borrow_mut().line_to(x, y); } /// fn QuadraticCurveTo(&self, cpx: f64, cpy: f64, x: f64, y: f64) { self.path.borrow_mut().quadratic_curve_to(cpx, cpy, x, y); } /// fn BezierCurveTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) { self.path .borrow_mut() .bezier_curve_to(cp1x, cp1y, cp2x, cp2y, x, y); } /// fn ArcTo(&self, x1: f64, y1: f64, x2: f64, y2: f64, radius: f64) -> Fallible<()> { self.path .borrow_mut() .arc_to(x1, y1, x2, y2, radius) .map_err(|_| Error::IndexSize) } /// fn Rect(&self, x: f64, y: f64, w: f64, h: f64) { self.path.borrow_mut().rect(x, y, w, h); } /// fn Arc( &self, x: f64, y: f64, radius: f64, start_angle: f64, end_angle: f64, counterclockwise: bool, ) -> Fallible<()> { self.path .borrow_mut() .arc(x, y, radius, start_angle, end_angle, counterclockwise) .map_err(|_| Error::IndexSize) } /// fn Ellipse( &self, x: f64, y: f64, radius_x: f64, radius_y: f64, rotation_angle: f64, start_angle: f64, end_angle: f64, counterclockwise: bool, ) -> Fallible<()> { self.path .borrow_mut() .ellipse( x, y, radius_x, radius_y, rotation_angle, start_angle, end_angle, counterclockwise, ) .map_err(|_| Error::IndexSize) } /// fn Constructor( global: &GlobalScope, proto: Option, can_gc: CanGc, ) -> DomRoot { reflect_dom_object_with_proto(Box::new(Self::new()), global, proto, can_gc) } /// fn Constructor_( global: &GlobalScope, proto: Option, can_gc: CanGc, other: &Path2D, ) -> DomRoot { reflect_dom_object_with_proto(Box::new(Self::new_with_path(other)), global, proto, can_gc) } /// fn Constructor__( global: &GlobalScope, proto: Option, can_gc: CanGc, path_string: DOMString, ) -> DomRoot { reflect_dom_object_with_proto( Box::new(Self::new_with_str(path_string.str())), global, proto, can_gc, ) } }