From 49820a6797fab5d376c06ff7c7f23b0aa18f5525 Mon Sep 17 00:00:00 2001 From: n0max Date: Sat, 29 Apr 2017 18:06:54 +0200 Subject: Remove IndexSizeError in CanvasRenderingContext2D::drawImage --- components/script/dom/canvasrenderingcontext2d.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 432dbe800aa..a5ec8d233b6 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -350,7 +350,7 @@ impl CanvasRenderingContext2D { dh); if !is_rect_valid(source_rect) || !is_rect_valid(dest_rect) { - return Err(Error::IndexSize); + return Ok(()); } let smoothing_enabled = self.state.borrow().image_smoothing_enabled; @@ -407,7 +407,7 @@ impl CanvasRenderingContext2D { dh); if !is_rect_valid(source_rect) || !is_rect_valid(dest_rect) { - return Err(Error::IndexSize); + return Ok(()); } let smoothing_enabled = self.state.borrow().image_smoothing_enabled; -- cgit v1.2.3 From 5acee23f5d46b40c35491de22592a58a9ef5a45b Mon Sep 17 00:00:00 2001 From: SendilKumar N Date: Thu, 9 Mar 2017 20:30:01 +0800 Subject: Use the origin of the actual image response when determining if a canvas is origin clean. --- components/script/dom/canvasrenderingcontext2d.rs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index a5ec8d233b6..348ec08aced 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -32,7 +32,7 @@ use dom::htmlcanvaselement::HTMLCanvasElement; use dom::htmlcanvaselement::utils as canvas_utils; use dom::htmlimageelement::HTMLImageElement; use dom::imagedata::ImageData; -use dom::node::{Node, NodeDamage, window_from_node}; +use dom::node::{document_from_node, Node, NodeDamage, window_from_node}; use dom_struct::dom_struct; use euclid::matrix2d::Matrix2D; use euclid::point::Point2D; @@ -228,16 +228,11 @@ impl CanvasRenderingContext2D { } HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::CanvasRenderingContext2D(image) => image.origin_is_clean(), - HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::HTMLImageElement(image) => - match image.get_url() { - None => true, - Some(url) => { - // TODO(zbarsky): we should check the origin of the image against - // the entry settings object, but for now check it against the canvas' doc. - let node: &Node = &*self.canvas.upcast(); - url.origin() == node.owner_doc().url().origin() - } - } + HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::HTMLImageElement(image) => { + let image_origin = image.get_origin().expect("Image's origin is missing"); + let document = document_from_node(&*self.canvas); + document.url().clone().origin() == image_origin + } } } @@ -429,8 +424,8 @@ impl CanvasRenderingContext2D { }; let img = match self.request_image_from_cache(url) { - ImageResponse::Loaded(img) => img, - ImageResponse::PlaceholderLoaded(_) | + ImageResponse::Loaded(img, _) => img, + ImageResponse::PlaceholderLoaded(_, _) | ImageResponse::None | ImageResponse::MetadataLoaded(_) => { return None; -- cgit v1.2.3 From 27ae1ef2e7d78f38e744f2e00e177302f2d6aa82 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Fri, 28 Apr 2017 00:35:22 -0400 Subject: Thread ParseError return values through CSS parsing. --- components/script/dom/canvasrenderingcontext2d.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 348ec08aced..8fb17c90fea 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -6,7 +6,7 @@ use canvas_traits::{Canvas2dMsg, CanvasCommonMsg, CanvasMsg}; use canvas_traits::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; use canvas_traits::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; use canvas_traits::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply}; -use cssparser::{Parser, RGBA}; +use cssparser::{Parser, ParserInput, RGBA}; use cssparser::Color as CSSColor; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods; @@ -463,7 +463,8 @@ impl CanvasRenderingContext2D { } fn parse_color(&self, string: &str) -> Result { - let mut parser = Parser::new(&string); + let mut input = ParserInput::new(string); + let mut parser = Parser::new(&mut input); let color = CSSColor::parse(&mut parser); if parser.is_exhausted() { match color { @@ -1314,7 +1315,8 @@ impl Drop for CanvasRenderingContext2D { } pub fn parse_color(string: &str) -> Result { - let mut parser = Parser::new(&string); + let mut input = ParserInput::new(string); + let mut parser = Parser::new(&mut input); match CSSColor::parse(&mut parser) { Ok(CSSColor::RGBA(rgba)) => { if parser.is_exhausted() { -- cgit v1.2.3 From 8617320500491fab91979404cec2087bac7ef362 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Fri, 2 Jun 2017 14:50:26 +0200 Subject: Bump euclid to 0.14. --- components/script/dom/canvasrenderingcontext2d.rs | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 8fb17c90fea..7f08ba1c13a 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -34,10 +34,7 @@ use dom::htmlimageelement::HTMLImageElement; use dom::imagedata::ImageData; use dom::node::{document_from_node, Node, NodeDamage, window_from_node}; use dom_struct::dom_struct; -use euclid::matrix2d::Matrix2D; -use euclid::point::Point2D; -use euclid::rect::Rect; -use euclid::size::Size2D; +use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D, vec2}; use ipc_channel::ipc::{self, IpcSender}; use net_traits::image::base::PixelFormat; use net_traits::image_cache::ImageResponse; @@ -82,7 +79,7 @@ struct CanvasContextState { line_cap: LineCapStyle, line_join: LineJoinStyle, miter_limit: f64, - transform: Matrix2D, + transform: Transform2D, shadow_offset_x: f64, shadow_offset_y: f64, shadow_blur: f64, @@ -102,7 +99,7 @@ impl CanvasContextState { line_cap: LineCapStyle::Butt, line_join: LineJoinStyle::Miter, miter_limit: 10.0, - transform: Matrix2D::identity(), + transform: Transform2D::identity(), shadow_offset_x: 0.0, shadow_offset_y: 0.0, shadow_blur: 0.0, @@ -559,7 +556,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } let transform = self.state.borrow().transform; - self.state.borrow_mut().transform = transform.pre_scaled(x as f32, y as f32); + self.state.borrow_mut().transform = transform.pre_scale(x as f32, y as f32); self.update_transform() } @@ -572,7 +569,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { let (sin, cos) = (angle.sin(), angle.cos()); let transform = self.state.borrow().transform; self.state.borrow_mut().transform = transform.pre_mul( - &Matrix2D::row_major(cos as f32, sin as f32, + &Transform2D::row_major(cos as f32, sin as f32, -sin as f32, cos as f32, 0.0, 0.0)); self.update_transform() @@ -585,7 +582,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } let transform = self.state.borrow().transform; - self.state.borrow_mut().transform = transform.pre_translated(x as f32, y as f32); + self.state.borrow_mut().transform = transform.pre_translate(vec2(x as f32, y as f32)); self.update_transform() } @@ -598,7 +595,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { let transform = self.state.borrow().transform; self.state.borrow_mut().transform = transform.pre_mul( - &Matrix2D::row_major(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32)); + &Transform2D::row_major(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32)); self.update_transform() } @@ -610,13 +607,13 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } self.state.borrow_mut().transform = - Matrix2D::row_major(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32); + Transform2D::row_major(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32); self.update_transform() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-resettransform fn ResetTransform(&self) { - self.state.borrow_mut().transform = Matrix2D::identity(); + self.state.borrow_mut().transform = Transform2D::identity(); self.update_transform() } @@ -1079,7 +1076,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { dirty_width: Finite, dirty_height: Finite) { let data = imagedata.get_data_array(); - let offset = Point2D::new(*dx, *dy); + let offset = Vector2D::new(*dx, *dy); let image_data_size = Size2D::new(imagedata.Width() as f64, imagedata.Height() as f64); let dirty_rect = Rect::new(Point2D::new(*dirty_x, *dirty_y), -- cgit v1.2.3 From e7b1e041c8c049f52b5083f89ced893cd5a31370 Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Fri, 16 Jun 2017 15:27:22 +1000 Subject: Update WR (CPU text optimizations, image format renames). --- components/script/dom/canvasrenderingcontext2d.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 7f08ba1c13a..293e81b6e1c 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -431,7 +431,7 @@ impl CanvasRenderingContext2D { let image_size = Size2D::new(img.width as i32, img.height as i32); let image_data = match img.format { - PixelFormat::RGBA8 => img.bytes.to_vec(), + PixelFormat::BGRA8 => img.bytes.to_vec(), PixelFormat::K8 => panic!("K8 color type not supported"), PixelFormat::RGB8 => panic!("RGB8 color type not supported"), PixelFormat::KA8 => panic!("KA8 color type not supported"), -- cgit v1.2.3 From 7af5a7fd5409ab8db0274eb829136e5953e718ed Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sun, 18 Jun 2017 13:21:32 +0200 Subject: Untry script --- components/script/dom/canvasrenderingcontext2d.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 293e81b6e1c..be7c8e945c2 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -1137,18 +1137,18 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#img-error // If the image argument is an HTMLImageElement object that is in the broken state, // then throw an InvalidStateError exception - try!(self.fetch_image_data(image).ok_or(Error::InvalidState)) + self.fetch_image_data(image).ok_or(Error::InvalidState)? }, HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::HTMLCanvasElement(ref canvas) => { let _ = canvas.get_or_init_2d_context(); - try!(canvas.fetch_all_data().ok_or(Error::InvalidState)) + canvas.fetch_all_data().ok_or(Error::InvalidState)? }, HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::CanvasRenderingContext2D(ref context) => { let canvas = context.Canvas(); let _ = canvas.get_or_init_2d_context(); - try!(canvas.fetch_all_data().ok_or(Error::InvalidState)) + canvas.fetch_all_data().ok_or(Error::InvalidState)? } }; -- cgit v1.2.3 From 328fb25a65b94a91005aa47dca5aa7013779c4ae Mon Sep 17 00:00:00 2001 From: Alan Jeffrey Date: Fri, 9 Jun 2017 12:47:39 -0500 Subject: Implemented paint worklet rendering context. --- components/script/dom/canvasrenderingcontext2d.rs | 57 ++++++++++++++++------- 1 file changed, 40 insertions(+), 17 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index be7c8e945c2..c1a2be92bcc 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -61,7 +61,9 @@ pub struct CanvasRenderingContext2D { reflector_: Reflector, #[ignore_heap_size_of = "Defined in ipc-channel"] ipc_renderer: IpcSender, - canvas: JS, + // For rendering contexts created by an HTML canvas element, this is Some, + // for ones created by a paint worklet, this is None. + canvas: Option>, state: DOMRefCell, saved_states: DOMRefCell>, origin_clean: Cell, @@ -109,18 +111,21 @@ impl CanvasContextState { } impl CanvasRenderingContext2D { - fn new_inherited(global: &GlobalScope, - canvas: &HTMLCanvasElement, - size: Size2D) - -> CanvasRenderingContext2D { + pub fn new_inherited(global: &GlobalScope, + canvas: Option<&HTMLCanvasElement>, + size: Size2D) + -> CanvasRenderingContext2D { + debug!("Creating new canvas rendering context."); let (sender, receiver) = ipc::channel().unwrap(); let constellation_chan = global.constellation_chan(); + debug!("Asking constellation to create new canvas thread."); constellation_chan.send(ConstellationMsg::CreateCanvasPaintThread(size, sender)).unwrap(); let ipc_renderer = receiver.recv().unwrap(); + debug!("Done."); CanvasRenderingContext2D { reflector_: Reflector::new(), ipc_renderer: ipc_renderer, - canvas: JS::from_ref(canvas), + canvas: canvas.map(JS::from_ref), state: DOMRefCell::new(CanvasContextState::new()), saved_states: DOMRefCell::new(Vec::new()), origin_clean: Cell::new(true), @@ -131,7 +136,7 @@ impl CanvasRenderingContext2D { canvas: &HTMLCanvasElement, size: Size2D) -> Root { - reflect_dom_object(box CanvasRenderingContext2D::new_inherited(global, canvas, size), + reflect_dom_object(box CanvasRenderingContext2D::new_inherited(global, Some(canvas), size), global, CanvasRenderingContext2DBinding::Wrap) } @@ -155,7 +160,9 @@ impl CanvasRenderingContext2D { } fn mark_as_dirty(&self) { - self.canvas.upcast::().dirty(NodeDamage::OtherNodeDamage); + if let Some(ref canvas) = self.canvas { + canvas.upcast::().dirty(NodeDamage::OtherNodeDamage); + } } fn update_transform(&self) { @@ -226,8 +233,12 @@ impl CanvasRenderingContext2D { HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::CanvasRenderingContext2D(image) => image.origin_is_clean(), HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::HTMLImageElement(image) => { + let canvas = match self.canvas { + Some(ref canvas) => canvas, + None => return false, + }; let image_origin = image.get_origin().expect("Image's origin is missing"); - let document = document_from_node(&*self.canvas); + let document = document_from_node(&**canvas); document.url().clone().origin() == image_origin } } @@ -347,7 +358,7 @@ impl CanvasRenderingContext2D { let smoothing_enabled = self.state.borrow().image_smoothing_enabled; - if &*self.canvas == canvas { + if self.canvas.as_ref().map_or(false, |c| &**c == canvas) { let msg = CanvasMsg::Canvas2d(Canvas2dMsg::DrawImageSelf( image_size, dest_rect, source_rect, smoothing_enabled)); self.ipc_renderer.send(msg).unwrap(); @@ -442,8 +453,10 @@ impl CanvasRenderingContext2D { #[inline] fn request_image_from_cache(&self, url: ServoUrl) -> ImageResponse { - let window = window_from_node(&*self.canvas); - canvas_utils::request_image_from_cache(&window, url) + self.canvas.as_ref() + .map(|canvas| window_from_node(&**canvas)) + .map(|window| canvas_utils::request_image_from_cache(&window, url)) + .unwrap_or(ImageResponse::None) } fn create_drawable_rect(&self, x: f64, y: f64, w: f64, h: f64) -> Option> { @@ -472,12 +485,20 @@ impl CanvasRenderingContext2D { // TODO: will need to check that the context bitmap mode is fixed // once we implement CanvasProxy - let window = window_from_node(&*self.canvas); + let canvas = match self.canvas { + // https://drafts.css-houdini.org/css-paint-api/#2d-rendering-context + // Whenever "currentColor" is used as a color in the PaintRenderingContext2D API, + // it is treated as opaque black. + None => return Ok(RGBA::new(0, 0, 0, 255)), + Some(ref canvas) => &**canvas, + }; + + let window = window_from_node(canvas); - let style = window.GetComputedStyle(&*self.canvas.upcast(), None); + let style = window.GetComputedStyle(canvas.upcast(), None); let element_not_rendered = - !self.canvas.upcast::().is_in_doc() || + !canvas.upcast::().is_in_doc() || style.GetPropertyValue(DOMString::from("display")) == "none"; if element_not_rendered { @@ -530,7 +551,9 @@ impl LayoutCanvasRenderingContext2DHelpers for LayoutJS Root { - Root::from_ref(&*self.canvas) + // This method is not called from a paint worklet rendering context, + // so it's OK to panic if self.canvas is None. + Root::from_ref(self.canvas.as_ref().expect("No canvas.")) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-save @@ -1037,7 +1060,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { let (sender, receiver) = ipc::channel::>().unwrap(); let dest_rect = Rect::new(Point2D::new(sx.to_i32().unwrap(), sy.to_i32().unwrap()), Size2D::new(sw as i32, sh as i32)); - let canvas_size = self.canvas.get_size(); + let canvas_size = self.canvas.as_ref().map(|c| c.get_size()).unwrap_or(Size2D::zero()); let canvas_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64); self.ipc_renderer .send(CanvasMsg::Canvas2d(Canvas2dMsg::GetImageData(dest_rect, canvas_size, sender))) -- cgit v1.2.3 From 2318caf002ab13cd9c9bf30676eaca5e7b9b0dc1 Mon Sep 17 00:00:00 2001 From: Alan Jeffrey Date: Wed, 5 Jul 2017 15:18:08 -0500 Subject: Implement drawing an image from a CSS style value into a canvas. --- components/script/dom/canvasrenderingcontext2d.rs | 170 +++++++++++++++------- 1 file changed, 117 insertions(+), 53 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index c1a2be92bcc..f57df77cfa4 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -12,12 +12,12 @@ use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasFillRule; +use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasImageSource; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineCap; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineJoin; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods; use dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; -use dom::bindings::codegen::UnionTypes::HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D; use dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; @@ -29,21 +29,25 @@ use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeSty use dom::canvaspattern::CanvasPattern; use dom::globalscope::GlobalScope; use dom::htmlcanvaselement::HTMLCanvasElement; -use dom::htmlcanvaselement::utils as canvas_utils; -use dom::htmlimageelement::HTMLImageElement; use dom::imagedata::ImageData; use dom::node::{document_from_node, Node, NodeDamage, window_from_node}; use dom_struct::dom_struct; use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D, vec2}; use ipc_channel::ipc::{self, IpcSender}; use net_traits::image::base::PixelFormat; +use net_traits::image_cache::CanRequestImages; +use net_traits::image_cache::ImageCache; +use net_traits::image_cache::ImageOrMetadataAvailable; use net_traits::image_cache::ImageResponse; +use net_traits::image_cache::ImageState; +use net_traits::image_cache::UsePlaceholder; use num_traits::ToPrimitive; use script_traits::ScriptMsg as ConstellationMsg; use servo_url::ServoUrl; -use std::{cmp, fmt}; +use std::{cmp, fmt, mem}; use std::cell::Cell; use std::str::FromStr; +use std::sync::Arc; use unpremultiplytable::UNPREMULTIPLY_TABLE; #[must_root] @@ -61,9 +65,16 @@ pub struct CanvasRenderingContext2D { reflector_: Reflector, #[ignore_heap_size_of = "Defined in ipc-channel"] ipc_renderer: IpcSender, - // For rendering contexts created by an HTML canvas element, this is Some, - // for ones created by a paint worklet, this is None. + /// For rendering contexts created by an HTML canvas element, this is Some, + /// for ones created by a paint worklet, this is None. canvas: Option>, + #[ignore_heap_size_of = "Arc"] + image_cache: Arc, + /// Any missing image URLs. + missing_image_urls: DOMRefCell>, + /// The base URL for resolving CSS image URL values. + /// Needed because of https://github.com/servo/servo/issues/17625 + base_url: ServoUrl, state: DOMRefCell, saved_states: DOMRefCell>, origin_clean: Cell, @@ -113,6 +124,8 @@ impl CanvasContextState { impl CanvasRenderingContext2D { pub fn new_inherited(global: &GlobalScope, canvas: Option<&HTMLCanvasElement>, + image_cache: Arc, + base_url: ServoUrl, size: Size2D) -> CanvasRenderingContext2D { debug!("Creating new canvas rendering context."); @@ -126,6 +139,9 @@ impl CanvasRenderingContext2D { reflector_: Reflector::new(), ipc_renderer: ipc_renderer, canvas: canvas.map(JS::from_ref), + image_cache: image_cache, + missing_image_urls: DOMRefCell::new(Vec::new()), + base_url: base_url, state: DOMRefCell::new(CanvasContextState::new()), saved_states: DOMRefCell::new(Vec::new()), origin_clean: Cell::new(true), @@ -136,9 +152,11 @@ impl CanvasRenderingContext2D { canvas: &HTMLCanvasElement, size: Size2D) -> Root { - reflect_dom_object(box CanvasRenderingContext2D::new_inherited(global, Some(canvas), size), - global, - CanvasRenderingContext2DBinding::Wrap) + let window = window_from_node(canvas); + let image_cache = window.image_cache(); + let base_url = window.get_url(); + let boxed = box CanvasRenderingContext2D::new_inherited(global, Some(canvas), image_cache, base_url, size); + reflect_dom_object(boxed, global, CanvasRenderingContext2DBinding::Wrap) } // https://html.spec.whatwg.org/multipage/#concept-canvas-set-bitmap-dimensions @@ -224,15 +242,15 @@ impl CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#the-image-argument-is-not-origin-clean fn is_origin_clean(&self, - image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D) + image: CanvasImageSource) -> bool { match image { - HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::HTMLCanvasElement(canvas) => { + CanvasImageSource::HTMLCanvasElement(canvas) => { canvas.origin_is_clean() } - HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::CanvasRenderingContext2D(image) => + CanvasImageSource::CanvasRenderingContext2D(image) => image.origin_is_clean(), - HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::HTMLImageElement(image) => { + CanvasImageSource::HTMLImageElement(image) => { let canvas = match self.canvas { Some(ref canvas) => canvas, None => return false, @@ -241,6 +259,7 @@ impl CanvasRenderingContext2D { let document = document_from_node(&**canvas); document.url().clone().origin() == image_origin } + CanvasImageSource::CSSStyleValue(_) => true, } } @@ -266,7 +285,7 @@ impl CanvasRenderingContext2D { // // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage fn draw_image(&self, - image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D, + image: CanvasImageSource, sx: f64, sy: f64, sw: Option, @@ -277,38 +296,30 @@ impl CanvasRenderingContext2D { dh: Option) -> ErrorResult { let result = match image { - HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::HTMLCanvasElement(ref canvas) => { + CanvasImageSource::HTMLCanvasElement(ref canvas) => { self.draw_html_canvas_element(&canvas, sx, sy, sw, sh, dx, dy, dw, dh) } - HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::CanvasRenderingContext2D(ref image) => { + CanvasImageSource::CanvasRenderingContext2D(ref image) => { self.draw_html_canvas_element(&image.Canvas(), sx, sy, sw, sh, dx, dy, dw, dh) } - HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::HTMLImageElement(ref image) => { + CanvasImageSource::HTMLImageElement(ref image) => { // https://html.spec.whatwg.org/multipage/#img-error // If the image argument is an HTMLImageElement object that is in the broken state, // then throw an InvalidStateError exception - let (image_data, image_size) = match self.fetch_image_data(image) { - Some((mut data, size)) => { - // Pixels come from cache in BGRA order and drawImage expects RGBA so we - // have to swap the color values - byte_swap_and_premultiply(&mut data); - let size = Size2D::new(size.width as f64, size.height as f64); - (data, size) - }, - None => return Err(Error::InvalidState), - }; - let dw = dw.unwrap_or(image_size.width); - let dh = dh.unwrap_or(image_size.height); - let sw = sw.unwrap_or(image_size.width); - let sh = sh.unwrap_or(image_size.height); - self.draw_image_data(image_data, - image_size, - sx, sy, sw, sh, - dx, dy, dw, dh) + let url = image.get_url().ok_or(Error::InvalidState)?; + self.fetch_and_draw_image_data(url, + sx, sy, sw, sh, + dx, dy, dw, dh) + } + CanvasImageSource::CSSStyleValue(ref value) => { + let url = value.get_url(self.base_url.clone()).ok_or(Error::InvalidState)?; + self.fetch_and_draw_image_data(url, + sx, sy, sw, sh, + dx, dy, dw, dh) } }; @@ -386,6 +397,41 @@ impl CanvasRenderingContext2D { Ok(()) } + fn fetch_and_draw_image_data(&self, + url: ServoUrl, + sx: f64, + sy: f64, + sw: Option, + sh: Option, + dx: f64, + dy: f64, + dw: Option, + dh: Option) + -> ErrorResult { + debug!("Fetching image {}.", url); + // https://html.spec.whatwg.org/multipage/#img-error + // If the image argument is an HTMLImageElement object that is in the broken state, + // then throw an InvalidStateError exception + let (image_data, image_size) = match self.fetch_image_data(url) { + Some((mut data, size)) => { + // Pixels come from cache in BGRA order and drawImage expects RGBA so we + // have to swap the color values + byte_swap_and_premultiply(&mut data); + let size = Size2D::new(size.width as f64, size.height as f64); + (data, size) + }, + None => return Err(Error::InvalidState), + }; + let dw = dw.unwrap_or(image_size.width); + let dh = dh.unwrap_or(image_size.height); + let sw = sw.unwrap_or(image_size.width); + let sh = sh.unwrap_or(image_size.height); + self.draw_image_data(image_data, + image_size, + sx, sy, sw, sh, + dx, dy, dw, dh) + } + fn draw_image_data(&self, image_data: Vec, image_size: Size2D, @@ -425,12 +471,7 @@ impl CanvasRenderingContext2D { Ok(()) } - fn fetch_image_data(&self, image_element: &HTMLImageElement) -> Option<(Vec, Size2D)> { - let url = match image_element.get_url() { - Some(url) => url, - None => return None, - }; - + fn fetch_image_data(&self, url: ServoUrl) -> Option<(Vec, Size2D)> { let img = match self.request_image_from_cache(url) { ImageResponse::Loaded(img, _) => img, ImageResponse::PlaceholderLoaded(_, _) | @@ -453,10 +494,26 @@ impl CanvasRenderingContext2D { #[inline] fn request_image_from_cache(&self, url: ServoUrl) -> ImageResponse { - self.canvas.as_ref() - .map(|canvas| window_from_node(&**canvas)) - .map(|window| canvas_utils::request_image_from_cache(&window, url)) - .unwrap_or(ImageResponse::None) + let response = self.image_cache + .find_image_or_metadata(url.clone(), + UsePlaceholder::No, + CanRequestImages::No); + match response { + Ok(ImageOrMetadataAvailable::ImageAvailable(image, url)) => + ImageResponse::Loaded(image, url), + Err(ImageState::Pending(_)) => + ImageResponse::None, + _ => { + // Rather annoyingly, we get the same response back from + // A load which really failed and from a load which hasn't started yet. + self.missing_image_urls.borrow_mut().push(url); + ImageResponse::None + }, + } + } + + pub fn take_missing_image_urls(&self) -> Vec { + mem::replace(&mut self.missing_image_urls.borrow_mut(), vec![]) } fn create_drawable_rect(&self, x: f64, y: f64, w: f64, h: f64) -> Option> { @@ -749,7 +806,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage fn DrawImage(&self, - image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D, + image: CanvasImageSource, dx: f64, dy: f64) -> ErrorResult { @@ -762,7 +819,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage fn DrawImage_(&self, - image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D, + image: CanvasImageSource, dx: f64, dy: f64, dw: f64, @@ -777,7 +834,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage fn DrawImage__(&self, - image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D, + image: CanvasImageSource, sx: f64, sy: f64, sw: f64, @@ -1152,27 +1209,34 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern fn CreatePattern(&self, - image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D, + image: CanvasImageSource, mut repetition: DOMString) -> Fallible> { let (image_data, image_size) = match image { - HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::HTMLImageElement(ref image) => { + CanvasImageSource::HTMLImageElement(ref image) => { // https://html.spec.whatwg.org/multipage/#img-error // If the image argument is an HTMLImageElement object that is in the broken state, // then throw an InvalidStateError exception - self.fetch_image_data(image).ok_or(Error::InvalidState)? + image.get_url() + .and_then(|url| self.fetch_image_data(url)) + .ok_or(Error::InvalidState)? }, - HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::HTMLCanvasElement(ref canvas) => { + CanvasImageSource::HTMLCanvasElement(ref canvas) => { let _ = canvas.get_or_init_2d_context(); canvas.fetch_all_data().ok_or(Error::InvalidState)? }, - HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::CanvasRenderingContext2D(ref context) => { + CanvasImageSource::CanvasRenderingContext2D(ref context) => { let canvas = context.Canvas(); let _ = canvas.get_or_init_2d_context(); canvas.fetch_all_data().ok_or(Error::InvalidState)? } + CanvasImageSource::CSSStyleValue(ref value) => { + value.get_url(self.base_url.clone()) + .and_then(|url| self.fetch_image_data(url)) + .ok_or(Error::InvalidState)? + } }; if repetition.is_empty() { -- cgit v1.2.3 From d2413891292bfb4d5f17d7eb1e3882e07f6ac626 Mon Sep 17 00:00:00 2001 From: Paul Rouget Date: Tue, 18 Jul 2017 08:19:44 +0200 Subject: make use of ScriptToConstellationChan --- components/script/dom/canvasrenderingcontext2d.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index f57df77cfa4..55d2ef3ceb4 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -42,7 +42,7 @@ use net_traits::image_cache::ImageResponse; use net_traits::image_cache::ImageState; use net_traits::image_cache::UsePlaceholder; use num_traits::ToPrimitive; -use script_traits::ScriptMsg as ConstellationMsg; +use script_traits::ScriptMsg; use servo_url::ServoUrl; use std::{cmp, fmt, mem}; use std::cell::Cell; @@ -130,9 +130,9 @@ impl CanvasRenderingContext2D { -> CanvasRenderingContext2D { debug!("Creating new canvas rendering context."); let (sender, receiver) = ipc::channel().unwrap(); - let constellation_chan = global.constellation_chan(); + let script_to_constellation_chan = global.script_to_constellation_chan(); debug!("Asking constellation to create new canvas thread."); - constellation_chan.send(ConstellationMsg::CreateCanvasPaintThread(size, sender)).unwrap(); + script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, sender)).unwrap(); let ipc_renderer = receiver.recv().unwrap(); debug!("Done."); CanvasRenderingContext2D { -- cgit v1.2.3 From 703962fe61d673536eb982b45795ae13748f0f6a Mon Sep 17 00:00:00 2001 From: Imanol Fernandez Date: Tue, 15 Aug 2017 16:05:22 +0200 Subject: Improve WebGL architecture. --- components/script/dom/canvasrenderingcontext2d.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 55d2ef3ceb4..d4fcfae4ab8 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -2,10 +2,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::{Canvas2dMsg, CanvasCommonMsg, CanvasMsg}; -use canvas_traits::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; -use canvas_traits::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; -use canvas_traits::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply}; +use canvas_traits::canvas::{Canvas2dMsg, CanvasMsg}; +use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; +use canvas_traits::canvas::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; +use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply}; use cssparser::{Parser, ParserInput, RGBA}; use cssparser::Color as CSSColor; use dom::bindings::cell::DOMRefCell; @@ -163,7 +163,7 @@ impl CanvasRenderingContext2D { pub fn set_bitmap_dimensions(&self, size: Size2D) { self.reset_to_initial_state(); self.ipc_renderer - .send(CanvasMsg::Common(CanvasCommonMsg::Recreate(size))) + .send(CanvasMsg::Recreate(size)) .unwrap(); } @@ -173,10 +173,6 @@ impl CanvasRenderingContext2D { *self.state.borrow_mut() = CanvasContextState::new(); } - pub fn ipc_renderer(&self) -> IpcSender { - self.ipc_renderer.clone() - } - fn mark_as_dirty(&self) { if let Some(ref canvas) = self.canvas { canvas.upcast::().dirty(NodeDamage::OtherNodeDamage); @@ -1392,7 +1388,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { impl Drop for CanvasRenderingContext2D { fn drop(&mut self) { - if let Err(err) = self.ipc_renderer.send(CanvasMsg::Common(CanvasCommonMsg::Close)) { + if let Err(err) = self.ipc_renderer.send(CanvasMsg::Close) { warn!("Could not close canvas: {}", err) } } -- cgit v1.2.3 From cfe22e3979b7270833a4b450b25fb2157deb1da2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 16 Aug 2017 16:42:13 +0200 Subject: Revert "Auto merge of #17891 - MortimerGoro:webgl_move, r=glennw,emilio" This reverts commit 90f55ea4580e2a15f7d70d0491444f18b972d450, reversing changes made to 2e60b27a2186a8cba4b952960155dfcf3f47d7db. --- components/script/dom/canvasrenderingcontext2d.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index d4fcfae4ab8..55d2ef3ceb4 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -2,10 +2,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::canvas::{Canvas2dMsg, CanvasMsg}; -use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; -use canvas_traits::canvas::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; -use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply}; +use canvas_traits::{Canvas2dMsg, CanvasCommonMsg, CanvasMsg}; +use canvas_traits::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; +use canvas_traits::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; +use canvas_traits::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply}; use cssparser::{Parser, ParserInput, RGBA}; use cssparser::Color as CSSColor; use dom::bindings::cell::DOMRefCell; @@ -163,7 +163,7 @@ impl CanvasRenderingContext2D { pub fn set_bitmap_dimensions(&self, size: Size2D) { self.reset_to_initial_state(); self.ipc_renderer - .send(CanvasMsg::Recreate(size)) + .send(CanvasMsg::Common(CanvasCommonMsg::Recreate(size))) .unwrap(); } @@ -173,6 +173,10 @@ impl CanvasRenderingContext2D { *self.state.borrow_mut() = CanvasContextState::new(); } + pub fn ipc_renderer(&self) -> IpcSender { + self.ipc_renderer.clone() + } + fn mark_as_dirty(&self) { if let Some(ref canvas) = self.canvas { canvas.upcast::().dirty(NodeDamage::OtherNodeDamage); @@ -1388,7 +1392,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { impl Drop for CanvasRenderingContext2D { fn drop(&mut self) { - if let Err(err) = self.ipc_renderer.send(CanvasMsg::Close) { + if let Err(err) = self.ipc_renderer.send(CanvasMsg::Common(CanvasCommonMsg::Close)) { warn!("Could not close canvas: {}", err) } } -- cgit v1.2.3 From 676f2c8acf6fec8ad77d4daa51bef5bdcae101c5 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Wed, 16 Aug 2017 23:23:18 +0200 Subject: Revert "Auto merge of #18114 - emilio:revert-webgl-refactor, r=nox" This reverts commit 4d10d39e8fe841c5fe2ac58da2daaa13c10c140e, reversing changes made to ee94e2b7c0bd327abe8f9545b2a1f792f67a2bdd. --- components/script/dom/canvasrenderingcontext2d.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 55d2ef3ceb4..d4fcfae4ab8 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -2,10 +2,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::{Canvas2dMsg, CanvasCommonMsg, CanvasMsg}; -use canvas_traits::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; -use canvas_traits::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; -use canvas_traits::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply}; +use canvas_traits::canvas::{Canvas2dMsg, CanvasMsg}; +use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; +use canvas_traits::canvas::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; +use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply}; use cssparser::{Parser, ParserInput, RGBA}; use cssparser::Color as CSSColor; use dom::bindings::cell::DOMRefCell; @@ -163,7 +163,7 @@ impl CanvasRenderingContext2D { pub fn set_bitmap_dimensions(&self, size: Size2D) { self.reset_to_initial_state(); self.ipc_renderer - .send(CanvasMsg::Common(CanvasCommonMsg::Recreate(size))) + .send(CanvasMsg::Recreate(size)) .unwrap(); } @@ -173,10 +173,6 @@ impl CanvasRenderingContext2D { *self.state.borrow_mut() = CanvasContextState::new(); } - pub fn ipc_renderer(&self) -> IpcSender { - self.ipc_renderer.clone() - } - fn mark_as_dirty(&self) { if let Some(ref canvas) = self.canvas { canvas.upcast::().dirty(NodeDamage::OtherNodeDamage); @@ -1392,7 +1388,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { impl Drop for CanvasRenderingContext2D { fn drop(&mut self) { - if let Err(err) = self.ipc_renderer.send(CanvasMsg::Common(CanvasCommonMsg::Close)) { + if let Err(err) = self.ipc_renderer.send(CanvasMsg::Close) { warn!("Could not close canvas: {}", err) } } -- cgit v1.2.3 From 2af828485fefbf6d2a2e01b9c9602c14aaff5a0e Mon Sep 17 00:00:00 2001 From: Bruno Bernardino Date: Wed, 9 Aug 2017 12:34:12 +0100 Subject: Implement CanvasRenderingContext2d.fillText's "unimplemented" message --- components/script/dom/canvasrenderingcontext2d.rs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index d4fcfae4ab8..db71c10551b 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -800,6 +800,13 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { receiver.recv().unwrap() } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-filltext + fn FillText(&self, text: DOMString, x: f64, y: f64, max_width: Option) { + let parsed_text: String = text.into(); + self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::FillText(parsed_text, x, y, max_width))).unwrap(); + self.mark_as_dirty(); + } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage fn DrawImage(&self, image: CanvasImageSource, -- cgit v1.2.3 From c5fe2351124c673d1dc4d59355a03654b4fcc541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20DAVID?= Date: Wed, 23 Aug 2017 14:10:08 +0200 Subject: order derivable traits lists Ignoring : - **generated**.rs - python/tidy/servo_tidy_tests/rust_tidy.rs --- components/script/dom/canvasrenderingcontext2d.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index d4fcfae4ab8..6d895efa05f 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -51,7 +51,7 @@ use std::sync::Arc; use unpremultiplytable::UNPREMULTIPLY_TABLE; #[must_root] -#[derive(JSTraceable, Clone, HeapSizeOf)] +#[derive(Clone, HeapSizeOf, JSTraceable)] #[allow(dead_code)] enum CanvasFillOrStrokeStyle { Color(RGBA), @@ -81,7 +81,7 @@ pub struct CanvasRenderingContext2D { } #[must_root] -#[derive(JSTraceable, Clone, HeapSizeOf)] +#[derive(Clone, HeapSizeOf, JSTraceable)] struct CanvasContextState { global_alpha: f64, global_composition: CompositionOrBlending, -- cgit v1.2.3 From 57e283aaabaf1c481fa14dff9e85a53eac4d8113 Mon Sep 17 00:00:00 2001 From: Joone Hur Date: Thu, 17 Aug 2017 10:43:19 -0700 Subject: Implement Ellipse Canvas 2D API * Update rust-azure to 0.21.0 * Mark the following test case as fail: tests/wpt/mozilla/tests/mozilla/css-paint-api/background-image-tiled.html * Make the ellipse test case pass. BUG: https://github.com/servo/servo/issues/17598 --- components/script/dom/canvasrenderingcontext2d.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 399c1faf30f..e6007c8b6ee 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -957,6 +957,26 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { Ok(()) } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-ellipse + fn Ellipse(&self, x: f64, y: f64, rx: f64, ry: f64, rotation: f64, start: f64, end: f64, ccw: bool) -> ErrorResult { + if !([x, y, rx, ry, rotation, start, end].iter().all(|x| x.is_finite())) { + return Ok(()); + } + if rx < 0.0 || ry < 0.0 { + return Err(Error::IndexSize); + } + + let msg = CanvasMsg::Canvas2d(Canvas2dMsg::Ellipse(Point2D::new(x as f32, y as f32), + rx as f32, + ry as f32, + rotation as f32, + start as f32, + end as f32, + ccw)); + self.ipc_renderer.send(msg).unwrap(); + Ok(()) + } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-imagesmoothingenabled fn ImageSmoothingEnabled(&self) -> bool { let state = self.state.borrow(); -- cgit v1.2.3 From 0e3c54c1911ba2c3bf305ee04f04fcd9bf2fc2fe Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 25 Sep 2017 23:30:24 +0200 Subject: Rename dom::bindings::js to dom::bindings::root --- components/script/dom/canvasrenderingcontext2d.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index e6007c8b6ee..4e98345eb07 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -21,9 +21,9 @@ use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, LayoutJS, Root}; use dom::bindings::num::Finite; use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; +use dom::bindings::root::{JS, LayoutJS, Root}; use dom::bindings::str::DOMString; use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle}; use dom::canvaspattern::CanvasPattern; -- cgit v1.2.3 From 7be32fb2371a14ba61b008a37e79761f66c073c7 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 25 Sep 2017 23:56:32 +0200 Subject: Rename JS to Dom --- components/script/dom/canvasrenderingcontext2d.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 4e98345eb07..4eafb0907e8 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -23,7 +23,7 @@ use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; use dom::bindings::num::Finite; use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; -use dom::bindings::root::{JS, LayoutJS, Root}; +use dom::bindings::root::{Dom, LayoutJS, Root}; use dom::bindings::str::DOMString; use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle}; use dom::canvaspattern::CanvasPattern; @@ -55,8 +55,8 @@ use unpremultiplytable::UNPREMULTIPLY_TABLE; #[allow(dead_code)] enum CanvasFillOrStrokeStyle { Color(RGBA), - Gradient(JS), - Pattern(JS), + Gradient(Dom), + Pattern(Dom), } // https://html.spec.whatwg.org/multipage/#canvasrenderingcontext2d @@ -67,7 +67,7 @@ pub struct CanvasRenderingContext2D { ipc_renderer: IpcSender, /// For rendering contexts created by an HTML canvas element, this is Some, /// for ones created by a paint worklet, this is None. - canvas: Option>, + canvas: Option>, #[ignore_heap_size_of = "Arc"] image_cache: Arc, /// Any missing image URLs. @@ -138,7 +138,7 @@ impl CanvasRenderingContext2D { CanvasRenderingContext2D { reflector_: Reflector::new(), ipc_renderer: ipc_renderer, - canvas: canvas.map(JS::from_ref), + canvas: canvas.map(Dom::from_ref), image_cache: image_cache, missing_image_urls: DOMRefCell::new(Vec::new()), base_url: base_url, @@ -1019,14 +1019,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { }, StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => { self.state.borrow_mut().stroke_style = - CanvasFillOrStrokeStyle::Gradient(JS::from_ref(&*gradient)); + CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient)); let msg = CanvasMsg::Canvas2d( Canvas2dMsg::SetStrokeStyle(gradient.to_fill_or_stroke_style())); self.ipc_renderer.send(msg).unwrap(); }, StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => { self.state.borrow_mut().stroke_style = - CanvasFillOrStrokeStyle::Pattern(JS::from_ref(&*pattern)); + CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern)); let msg = CanvasMsg::Canvas2d( Canvas2dMsg::SetStrokeStyle(pattern.to_fill_or_stroke_style())); self.ipc_renderer.send(msg).unwrap(); @@ -1068,14 +1068,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => { self.state.borrow_mut().fill_style = - CanvasFillOrStrokeStyle::Gradient(JS::from_ref(&*gradient)); + CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient)); let msg = CanvasMsg::Canvas2d( Canvas2dMsg::SetFillStyle(gradient.to_fill_or_stroke_style())); self.ipc_renderer.send(msg).unwrap(); } StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => { self.state.borrow_mut().fill_style = - CanvasFillOrStrokeStyle::Pattern(JS::from_ref(&*pattern)); + CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern)); let msg = CanvasMsg::Canvas2d( Canvas2dMsg::SetFillStyle(pattern.to_fill_or_stroke_style())); self.ipc_renderer.send(msg).unwrap(); -- cgit v1.2.3 From e2dac78d3600cb4b2b4474f1db4f0fcaadbe24ea Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 26 Sep 2017 01:30:06 +0200 Subject: Rename LayoutJS to LayoutDom --- components/script/dom/canvasrenderingcontext2d.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 4eafb0907e8..cf898b06880 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -23,7 +23,7 @@ use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; use dom::bindings::num::Finite; use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; -use dom::bindings::root::{Dom, LayoutJS, Root}; +use dom::bindings::root::{Dom, LayoutDom, Root}; use dom::bindings::str::DOMString; use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle}; use dom::canvaspattern::CanvasPattern; @@ -585,7 +585,7 @@ pub trait LayoutCanvasRenderingContext2DHelpers { unsafe fn get_ipc_renderer(&self) -> IpcSender; } -impl LayoutCanvasRenderingContext2DHelpers for LayoutJS { +impl LayoutCanvasRenderingContext2DHelpers for LayoutDom { #[allow(unsafe_code)] unsafe fn get_ipc_renderer(&self) -> IpcSender { (*self.unsafe_get()).ipc_renderer.clone() -- cgit v1.2.3 From 577370746e2ce3da7fa25a20b8e1bbeed319df65 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 26 Sep 2017 01:32:40 +0200 Subject: Rename DOMRefCell to DomRefCell I don't want to do such a gratuitous rename, but with all the other types now having "Dom" as part of their name, and especially with "DomOnceCell", I feel like the other cell type that we already have should also follow the convention. That argument loses weight though when we realise there is still DOMString and other things. --- components/script/dom/canvasrenderingcontext2d.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index cf898b06880..b9e7def9a1c 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -8,7 +8,7 @@ use canvas_traits::canvas::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply}; use cssparser::{Parser, ParserInput, RGBA}; use cssparser::Color as CSSColor; -use dom::bindings::cell::DOMRefCell; +use dom::bindings::cell::DomRefCell; use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasFillRule; @@ -71,12 +71,12 @@ pub struct CanvasRenderingContext2D { #[ignore_heap_size_of = "Arc"] image_cache: Arc, /// Any missing image URLs. - missing_image_urls: DOMRefCell>, + missing_image_urls: DomRefCell>, /// The base URL for resolving CSS image URL values. /// Needed because of https://github.com/servo/servo/issues/17625 base_url: ServoUrl, - state: DOMRefCell, - saved_states: DOMRefCell>, + state: DomRefCell, + saved_states: DomRefCell>, origin_clean: Cell, } @@ -140,10 +140,10 @@ impl CanvasRenderingContext2D { ipc_renderer: ipc_renderer, canvas: canvas.map(Dom::from_ref), image_cache: image_cache, - missing_image_urls: DOMRefCell::new(Vec::new()), + missing_image_urls: DomRefCell::new(Vec::new()), base_url: base_url, - state: DOMRefCell::new(CanvasContextState::new()), - saved_states: DOMRefCell::new(Vec::new()), + state: DomRefCell::new(CanvasContextState::new()), + saved_states: DomRefCell::new(Vec::new()), origin_clean: Cell::new(true), } } -- cgit v1.2.3 From f87c2a8d7616112ca924e30292db2d244cf87eec Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 26 Sep 2017 01:53:40 +0200 Subject: Rename Root to DomRoot In a later PR, DomRoot will become a type alias of Root>, where Root will be able to handle all the things that need to be rooted that have a stable traceable address that doesn't move for the whole lifetime of the root. Stay tuned. --- components/script/dom/canvasrenderingcontext2d.rs | 28 +++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index b9e7def9a1c..de56cb28deb 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -23,7 +23,7 @@ use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; use dom::bindings::num::Finite; use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; -use dom::bindings::root::{Dom, LayoutDom, Root}; +use dom::bindings::root::{Dom, DomRoot, LayoutDom}; use dom::bindings::str::DOMString; use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle}; use dom::canvaspattern::CanvasPattern; @@ -151,7 +151,7 @@ impl CanvasRenderingContext2D { pub fn new(global: &GlobalScope, canvas: &HTMLCanvasElement, size: Size2D) - -> Root { + -> DomRoot { let window = window_from_node(canvas); let image_cache = window.image_cache(); let base_url = window.get_url(); @@ -603,10 +603,10 @@ impl LayoutCanvasRenderingContext2DHelpers for LayoutDom Root { + fn Canvas(&self) -> DomRoot { // This method is not called from a paint worklet rendering context, // so it's OK to panic if self.canvas is None. - Root::from_ref(self.canvas.as_ref().expect("No canvas.")) + DomRoot::from_ref(self.canvas.as_ref().expect("No canvas.")) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-save @@ -997,10 +997,10 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { StringOrCanvasGradientOrCanvasPattern::String(DOMString::from(result)) }, CanvasFillOrStrokeStyle::Gradient(ref gradient) => { - StringOrCanvasGradientOrCanvasPattern::CanvasGradient(Root::from_ref(&*gradient)) + StringOrCanvasGradientOrCanvasPattern::CanvasGradient(DomRoot::from_ref(&*gradient)) }, CanvasFillOrStrokeStyle::Pattern(ref pattern) => { - StringOrCanvasGradientOrCanvasPattern::CanvasPattern(Root::from_ref(&*pattern)) + StringOrCanvasGradientOrCanvasPattern::CanvasPattern(DomRoot::from_ref(&*pattern)) } } } @@ -1046,10 +1046,10 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { StringOrCanvasGradientOrCanvasPattern::String(DOMString::from(result)) }, CanvasFillOrStrokeStyle::Gradient(ref gradient) => { - StringOrCanvasGradientOrCanvasPattern::CanvasGradient(Root::from_ref(&*gradient)) + StringOrCanvasGradientOrCanvasPattern::CanvasGradient(DomRoot::from_ref(&*gradient)) }, CanvasFillOrStrokeStyle::Pattern(ref pattern) => { - StringOrCanvasGradientOrCanvasPattern::CanvasPattern(Root::from_ref(&*pattern)) + StringOrCanvasGradientOrCanvasPattern::CanvasPattern(DomRoot::from_ref(&*pattern)) } } } @@ -1087,7 +1087,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata - fn CreateImageData(&self, sw: Finite, sh: Finite) -> Fallible> { + fn CreateImageData(&self, sw: Finite, sh: Finite) -> Fallible> { if *sw == 0.0 || *sh == 0.0 { return Err(Error::IndexSize); } @@ -1098,7 +1098,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata - fn CreateImageData_(&self, imagedata: &ImageData) -> Fallible> { + fn CreateImageData_(&self, imagedata: &ImageData) -> Fallible> { ImageData::new(&self.global(), imagedata.Width(), imagedata.Height(), @@ -1111,7 +1111,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { sy: Finite, sw: Finite, sh: Finite) - -> Fallible> { + -> Fallible> { if !self.origin_is_clean() { return Err(Error::Security) } @@ -1198,7 +1198,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { y0: Finite, x1: Finite, y1: Finite) - -> Root { + -> DomRoot { CanvasGradient::new(&self.global(), CanvasGradientStyle::Linear(LinearGradientStyle::new(*x0, *y0, @@ -1215,7 +1215,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { x1: Finite, y1: Finite, r1: Finite) - -> Fallible> { + -> Fallible> { if *r0 < 0. || *r1 < 0. { return Err(Error::IndexSize); } @@ -1234,7 +1234,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { fn CreatePattern(&self, image: CanvasImageSource, mut repetition: DOMString) - -> Fallible> { + -> Fallible> { let (image_data, image_size) = match image { CanvasImageSource::HTMLImageElement(ref image) => { // https://html.spec.whatwg.org/multipage/#img-error -- cgit v1.2.3 From aa15dc269f41503d81ad44cd7e85d69e6f4aeac7 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 16 Oct 2017 14:35:30 +0200 Subject: Remove use of unstable box syntax. http://www.robohornet.org gives a score of 101.36 on master, and 102.68 with this PR. The latter is slightly better, but probably within noise level. So it looks like this PR does not affect DOM performance. This is expected since `Box::new` is defined as: ```rust impl Box { #[inline(always)] pub fn new(x: T) -> Box { box x } } ``` With inlining, it should compile to the same as box syntax. --- components/script/dom/canvasrenderingcontext2d.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index de56cb28deb..69cf670efe4 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -155,7 +155,9 @@ impl CanvasRenderingContext2D { let window = window_from_node(canvas); let image_cache = window.image_cache(); let base_url = window.get_url(); - let boxed = box CanvasRenderingContext2D::new_inherited(global, Some(canvas), image_cache, base_url, size); + let boxed = Box::new(CanvasRenderingContext2D::new_inherited( + global, Some(canvas), image_cache, base_url, size + )); reflect_dom_object(boxed, global, CanvasRenderingContext2DBinding::Wrap) } -- cgit v1.2.3 From 4506f0d30cbbb02df32e9c16135ef288ad6b7e2e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 18 Oct 2017 10:42:01 +1100 Subject: Replace all uses of the `heapsize` crate with `malloc_size_of`. Servo currently uses `heapsize`, but Stylo/Gecko use `malloc_size_of`. `malloc_size_of` is better -- it handles various cases that `heapsize` does not -- so this patch changes Servo to use `malloc_size_of`. This patch makes the following changes to the `malloc_size_of` crate. - Adds `MallocSizeOf` trait implementations for numerous types, some built-in (e.g. `VecDeque`), some external and Servo-only (e.g. `string_cache`). - Makes `enclosing_size_of_op` optional, because vanilla jemalloc doesn't support that operation. - For `HashSet`/`HashMap`, falls back to a computed estimate when `enclosing_size_of_op` isn't available. - Adds an extern "C" `malloc_size_of` function that does the actual heap measurement; this is based on the same functions from the `heapsize` crate. This patch makes the following changes elsewhere. - Converts all the uses of `heapsize` to instead use `malloc_size_of`. - Disables the "heapsize"/"heap_size" feature for the external crates that provide it. - Removes the `HeapSizeOf` implementation from `hashglobe`. - Adds `ignore` annotations to a few `Rc`/`Arc`, because `malloc_size_of` doesn't derive those types, unlike `heapsize`. --- components/script/dom/canvasrenderingcontext2d.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 69cf670efe4..cf6b92bc404 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -51,7 +51,7 @@ use std::sync::Arc; use unpremultiplytable::UNPREMULTIPLY_TABLE; #[must_root] -#[derive(Clone, HeapSizeOf, JSTraceable)] +#[derive(Clone, JSTraceable, MallocSizeOf)] #[allow(dead_code)] enum CanvasFillOrStrokeStyle { Color(RGBA), @@ -63,12 +63,12 @@ enum CanvasFillOrStrokeStyle { #[dom_struct] pub struct CanvasRenderingContext2D { reflector_: Reflector, - #[ignore_heap_size_of = "Defined in ipc-channel"] + #[ignore_malloc_size_of = "Defined in ipc-channel"] ipc_renderer: IpcSender, /// For rendering contexts created by an HTML canvas element, this is Some, /// for ones created by a paint worklet, this is None. canvas: Option>, - #[ignore_heap_size_of = "Arc"] + #[ignore_malloc_size_of = "Arc"] image_cache: Arc, /// Any missing image URLs. missing_image_urls: DomRefCell>, @@ -81,7 +81,7 @@ pub struct CanvasRenderingContext2D { } #[must_root] -#[derive(Clone, HeapSizeOf, JSTraceable)] +#[derive(Clone, JSTraceable, MallocSizeOf)] struct CanvasContextState { global_alpha: f64, global_composition: CompositionOrBlending, -- cgit v1.2.3 From 80a81f2774c756863d97efa7d518f242a5f0ef2b Mon Sep 17 00:00:00 2001 From: tigercosmos Date: Tue, 5 Dec 2017 15:10:55 +0800 Subject: use entry global's origin in `is_origin_clean` check for canvas rendering --- components/script/dom/canvasrenderingcontext2d.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index cf6b92bc404..93d4981d2bb 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -30,7 +30,7 @@ use dom::canvaspattern::CanvasPattern; use dom::globalscope::GlobalScope; use dom::htmlcanvaselement::HTMLCanvasElement; use dom::imagedata::ImageData; -use dom::node::{document_from_node, Node, NodeDamage, window_from_node}; +use dom::node::{Node, NodeDamage, window_from_node}; use dom_struct::dom_struct; use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D, vec2}; use ipc_channel::ipc::{self, IpcSender}; @@ -249,13 +249,8 @@ impl CanvasRenderingContext2D { CanvasImageSource::CanvasRenderingContext2D(image) => image.origin_is_clean(), CanvasImageSource::HTMLImageElement(image) => { - let canvas = match self.canvas { - Some(ref canvas) => canvas, - None => return false, - }; let image_origin = image.get_origin().expect("Image's origin is missing"); - let document = document_from_node(&**canvas); - document.url().clone().origin() == image_origin + image_origin.same_origin(GlobalScope::entry().origin()) } CanvasImageSource::CSSStyleValue(_) => true, } -- cgit v1.2.3 From a504c9358b70fcf02bd8f2067fcbd17d16c89439 Mon Sep 17 00:00:00 2001 From: tigercosmos Date: Tue, 12 Dec 2017 15:20:04 +0800 Subject: Send IPC receiver for canvas as part of CreateCanvasPaintThread message --- components/script/dom/canvasrenderingcontext2d.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 93d4981d2bb..1c9dc16c445 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -129,11 +129,10 @@ impl CanvasRenderingContext2D { size: Size2D) -> CanvasRenderingContext2D { debug!("Creating new canvas rendering context."); - let (sender, receiver) = ipc::channel().unwrap(); + let (ipc_renderer, receiver) = ipc::channel::().unwrap(); let script_to_constellation_chan = global.script_to_constellation_chan(); debug!("Asking constellation to create new canvas thread."); - script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, sender)).unwrap(); - let ipc_renderer = receiver.recv().unwrap(); + script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, receiver)).unwrap(); debug!("Done."); CanvasRenderingContext2D { reflector_: Reflector::new(), -- cgit v1.2.3 From 0e211d0d8f297084304860e3181eb21880921333 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Mon, 18 Dec 2017 10:51:00 -0500 Subject: Revert "Send IPC receiver for canvas as part of CreateCanvasPaintThread message" This reverts commit a504c9358b70fcf02bd8f2067fcbd17d16c89439. --- components/script/dom/canvasrenderingcontext2d.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 1c9dc16c445..93d4981d2bb 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -129,10 +129,11 @@ impl CanvasRenderingContext2D { size: Size2D) -> CanvasRenderingContext2D { debug!("Creating new canvas rendering context."); - let (ipc_renderer, receiver) = ipc::channel::().unwrap(); + let (sender, receiver) = ipc::channel().unwrap(); let script_to_constellation_chan = global.script_to_constellation_chan(); debug!("Asking constellation to create new canvas thread."); - script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, receiver)).unwrap(); + script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, sender)).unwrap(); + let ipc_renderer = receiver.recv().unwrap(); debug!("Done."); CanvasRenderingContext2D { reflector_: Reflector::new(), -- cgit v1.2.3 From 8d093982307275026d79af45afa29512cef1180c Mon Sep 17 00:00:00 2001 From: Alex Fong Date: Mon, 12 Feb 2018 20:36:23 +0800 Subject: Avoid `Window::GetComputedStyle` when checking for `display: none` --- components/script/dom/canvasrenderingcontext2d.rs | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 93d4981d2bb..1e2278e81ca 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -9,7 +9,6 @@ use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle, byte_swap_and_ use cssparser::{Parser, ParserInput, RGBA}; use cssparser::Color as CSSColor; use dom::bindings::cell::DomRefCell; -use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasFillRule; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasImageSource; @@ -17,7 +16,6 @@ use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLin use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineJoin; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods; use dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods; -use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; @@ -27,6 +25,7 @@ use dom::bindings::root::{Dom, DomRoot, LayoutDom}; use dom::bindings::str::DOMString; use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle}; use dom::canvaspattern::CanvasPattern; +use dom::element::Element; use dom::globalscope::GlobalScope; use dom::htmlcanvaselement::HTMLCanvasElement; use dom::imagedata::ImageData; @@ -543,18 +542,11 @@ impl CanvasRenderingContext2D { Some(ref canvas) => &**canvas, }; - let window = window_from_node(canvas); + let canvas_element = canvas.upcast::(); - let style = window.GetComputedStyle(canvas.upcast(), None); - - let element_not_rendered = - !canvas.upcast::().is_in_doc() || - style.GetPropertyValue(DOMString::from("display")) == "none"; - - if element_not_rendered { - Ok(RGBA::new(0, 0, 0, 255)) - } else { - self.parse_color(&style.GetPropertyValue(DOMString::from("color"))) + match canvas_element.style() { + Some(ref s) if canvas_element.has_css_layout_box() => Ok(s.get_color().color), + _ => Ok(RGBA::new(0, 0, 0, 255)) } }, _ => Err(()) -- cgit v1.2.3 From 7d4e2b11e940545eaa74877b75908e1e02f6eeb5 Mon Sep 17 00:00:00 2001 From: Nakul Jindal Date: Mon, 26 Feb 2018 09:07:08 -0800 Subject: Implements profiler for blocked recv --- components/script/dom/canvasrenderingcontext2d.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 1e2278e81ca..a837fc02fd7 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -32,7 +32,7 @@ use dom::imagedata::ImageData; use dom::node::{Node, NodeDamage, window_from_node}; use dom_struct::dom_struct; use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D, vec2}; -use ipc_channel::ipc::{self, IpcSender}; +use ipc_channel::ipc::IpcSender; use net_traits::image::base::PixelFormat; use net_traits::image_cache::CanRequestImages; use net_traits::image_cache::ImageCache; @@ -41,6 +41,7 @@ use net_traits::image_cache::ImageResponse; use net_traits::image_cache::ImageState; use net_traits::image_cache::UsePlaceholder; use num_traits::ToPrimitive; +use profile_traits::ipc; use script_traits::ScriptMsg; use servo_url::ServoUrl; use std::{cmp, fmt, mem}; @@ -128,7 +129,7 @@ impl CanvasRenderingContext2D { size: Size2D) -> CanvasRenderingContext2D { debug!("Creating new canvas rendering context."); - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(global.time_profiler_chan().clone()).unwrap(); let script_to_constellation_chan = global.script_to_constellation_chan(); debug!("Asking constellation to create new canvas thread."); script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, sender)).unwrap(); @@ -371,7 +372,7 @@ impl CanvasRenderingContext2D { None => return Err(Error::InvalidState), }; - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); let msg = CanvasMsg::Canvas2d(Canvas2dMsg::DrawImageInOther( self.ipc_renderer.clone(), image_size, @@ -782,7 +783,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { CanvasFillRule::Nonzero => FillRule::Nonzero, CanvasFillRule::Evenodd => FillRule::Evenodd, }; - let (sender, receiver) = ipc::channel::().unwrap(); + let (sender, receiver) = ipc::channel::(self.global().time_profiler_chan().clone()).unwrap(); self.ipc_renderer .send(CanvasMsg::Canvas2d(Canvas2dMsg::IsPointInPath(x, y, fill_rule, sender))) .unwrap(); @@ -1126,7 +1127,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { let sh = cmp::max(1, sh.to_u32().unwrap()); let sw = cmp::max(1, sw.to_u32().unwrap()); - let (sender, receiver) = ipc::channel::>().unwrap(); + let (sender, receiver) = ipc::channel::>(self.global().time_profiler_chan().clone()).unwrap(); let dest_rect = Rect::new(Point2D::new(sx.to_i32().unwrap(), sy.to_i32().unwrap()), Size2D::new(sw as i32, sh as i32)); let canvas_size = self.canvas.as_ref().map(|c| c.get_size()).unwrap_or(Size2D::zero()); -- cgit v1.2.3 From ce81420befd0fd0e8335cb676487479e2cc0f985 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Fri, 23 Mar 2018 18:41:32 +0100 Subject: Use ByteBuf for the canvas messages The type Vec is super unefficient to work with in Serde if all you want to represent is a simple blob. --- components/script/dom/canvasrenderingcontext2d.rs | 28 ++++++++++++----------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index a837fc02fd7..1e95ef3836a 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -453,13 +453,13 @@ impl CanvasRenderingContext2D { } let smoothing_enabled = self.state.borrow().image_smoothing_enabled; - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::DrawImage(image_data, - image_size, - dest_rect, - source_rect, - smoothing_enabled))) - .unwrap(); + self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::DrawImage( + image_data.into(), + image_size, + dest_rect, + source_rect, + smoothing_enabled, + ))).unwrap(); self.mark_as_dirty(); Ok(()) } @@ -1127,7 +1127,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { let sh = cmp::max(1, sh.to_u32().unwrap()); let sw = cmp::max(1, sw.to_u32().unwrap()); - let (sender, receiver) = ipc::channel::>(self.global().time_profiler_chan().clone()).unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); let dest_rect = Rect::new(Point2D::new(sx.to_i32().unwrap(), sy.to_i32().unwrap()), Size2D::new(sw as i32, sh as i32)); let canvas_size = self.canvas.as_ref().map(|c| c.get_size()).unwrap_or(Size2D::zero()); @@ -1135,7 +1135,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { self.ipc_renderer .send(CanvasMsg::Canvas2d(Canvas2dMsg::GetImageData(dest_rect, canvas_size, sender))) .unwrap(); - let mut data = receiver.recv().unwrap(); + let mut data = Vec::from(receiver.recv().unwrap()); // Un-premultiply alpha for chunk in data.chunks_mut(4) { @@ -1174,10 +1174,12 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { let dirty_rect = Rect::new(Point2D::new(*dirty_x, *dirty_y), Size2D::new(*dirty_width, *dirty_height)); - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::PutImageData(data, - offset, - image_data_size, - dirty_rect)); + let msg = CanvasMsg::Canvas2d(Canvas2dMsg::PutImageData( + data.into(), + offset, + image_data_size, + dirty_rect, + )); self.ipc_renderer.send(msg).unwrap(); self.mark_as_dirty(); } -- cgit v1.2.3 From 8a1590efc6ab6690cd9aab5ec3d46f854b891b4f Mon Sep 17 00:00:00 2001 From: Brody Eastwood Date: Tue, 20 Mar 2018 15:04:15 -0400 Subject: Add unique canvas IDs to all canvas operations. --- components/script/dom/canvasrenderingcontext2d.rs | 214 ++++++++++------------ 1 file changed, 92 insertions(+), 122 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 1e95ef3836a..ee101251635 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::canvas::{Canvas2dMsg, CanvasMsg}; +use canvas_traits::canvas::{Canvas2dMsg, CanvasMsg, CanvasId}; use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; use canvas_traits::canvas::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply}; @@ -78,6 +78,7 @@ pub struct CanvasRenderingContext2D { state: DomRefCell, saved_states: DomRefCell>, origin_clean: Cell, + canvas_id: CanvasId, } #[must_root] @@ -133,7 +134,7 @@ impl CanvasRenderingContext2D { let script_to_constellation_chan = global.script_to_constellation_chan(); debug!("Asking constellation to create new canvas thread."); script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, sender)).unwrap(); - let ipc_renderer = receiver.recv().unwrap(); + let (ipc_renderer, canvas_id) = receiver.recv().unwrap(); debug!("Done."); CanvasRenderingContext2D { reflector_: Reflector::new(), @@ -145,6 +146,7 @@ impl CanvasRenderingContext2D { state: DomRefCell::new(CanvasContextState::new()), saved_states: DomRefCell::new(Vec::new()), origin_clean: Cell::new(true), + canvas_id: canvas_id, } } @@ -165,7 +167,7 @@ impl CanvasRenderingContext2D { pub fn set_bitmap_dimensions(&self, size: Size2D) { self.reset_to_initial_state(); self.ipc_renderer - .send(CanvasMsg::Recreate(size)) + .send(CanvasMsg::Recreate(size, self.get_canvas_id())) .unwrap(); } @@ -182,9 +184,7 @@ impl CanvasRenderingContext2D { } fn update_transform(&self) { - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::SetTransform(self.state.borrow().transform))) - .unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetTransform(self.state.borrow().transform)) } // It is used by DrawImage to calculate the size of the source and destination rectangles based @@ -363,9 +363,8 @@ impl CanvasRenderingContext2D { let smoothing_enabled = self.state.borrow().image_smoothing_enabled; if self.canvas.as_ref().map_or(false, |c| &**c == canvas) { - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::DrawImageSelf( + self.send_canvas_2d_msg(Canvas2dMsg::DrawImageSelf( image_size, dest_rect, source_rect, smoothing_enabled)); - self.ipc_renderer.send(msg).unwrap(); } else { let context = match canvas.get_or_init_2d_context() { Some(context) => context, @@ -375,11 +374,13 @@ impl CanvasRenderingContext2D { let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); let msg = CanvasMsg::Canvas2d(Canvas2dMsg::DrawImageInOther( self.ipc_renderer.clone(), + self.get_canvas_id(), image_size, dest_rect, source_rect, smoothing_enabled, - sender)); + sender), + context.get_canvas_id()); let renderer = context.get_ipc_renderer(); renderer.send(msg).unwrap(); @@ -453,13 +454,13 @@ impl CanvasRenderingContext2D { } let smoothing_enabled = self.state.borrow().image_smoothing_enabled; - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::DrawImage( + self.send_canvas_2d_msg(Canvas2dMsg::DrawImage( image_data.into(), image_size, dest_rect, source_rect, smoothing_enabled, - ))).unwrap(); + )); self.mark_as_dirty(); Ok(()) } @@ -557,6 +558,14 @@ impl CanvasRenderingContext2D { } } + pub fn get_canvas_id(&self) -> CanvasId { + self.canvas_id.clone() + } + + pub fn send_canvas_2d_msg(&self, msg: Canvas2dMsg) { + self.ipc_renderer.send(CanvasMsg::Canvas2d(msg, self.get_canvas_id())).unwrap() + } + pub fn get_ipc_renderer(&self) -> IpcSender { self.ipc_renderer.clone() } @@ -573,6 +582,8 @@ impl CanvasRenderingContext2D { pub trait LayoutCanvasRenderingContext2DHelpers { #[allow(unsafe_code)] unsafe fn get_ipc_renderer(&self) -> IpcSender; + #[allow(unsafe_code)] + unsafe fn get_canvas_id(&self) -> CanvasId; } impl LayoutCanvasRenderingContext2DHelpers for LayoutDom { @@ -580,6 +591,11 @@ impl LayoutCanvasRenderingContext2DHelpers for LayoutDom IpcSender { (*self.unsafe_get()).ipc_renderer.clone() } + + #[allow(unsafe_code)] + unsafe fn get_canvas_id(&self) -> CanvasId { + (*self.unsafe_get()).canvas_id.clone() + } } // We add a guard to each of methods by the spec: @@ -602,7 +618,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-save fn Save(&self) { self.saved_states.borrow_mut().push(self.state.borrow().clone()); - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SaveContext)).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::SaveContext); } #[allow(unrooted_must_root)] @@ -611,7 +627,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { let mut saved_states = self.saved_states.borrow_mut(); if let Some(state) = saved_states.pop() { self.state.borrow_mut().clone_from(&state); - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::RestoreContext)).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::RestoreContext); } } @@ -696,9 +712,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } self.state.borrow_mut().global_alpha = alpha; - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::SetGlobalAlpha(alpha as f32))) - .unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetGlobalAlpha(alpha as f32)) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation @@ -714,16 +728,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { fn SetGlobalCompositeOperation(&self, op_str: DOMString) { if let Ok(op) = CompositionOrBlending::from_str(&op_str) { self.state.borrow_mut().global_composition = op; - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::SetGlobalComposition(op))) - .unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetGlobalComposition(op)) } } // https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) { if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::FillRect(rect))).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::FillRect(rect)); self.mark_as_dirty(); } } @@ -731,9 +743,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-clearrect fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) { if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::ClearRect(rect))) - .unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::ClearRect(rect)); self.mark_as_dirty(); } } @@ -741,40 +751,38 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokerect fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) { if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::StrokeRect(rect))) - .unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::StrokeRect(rect)); self.mark_as_dirty(); } } // https://html.spec.whatwg.org/multipage/#dom-context-2d-beginpath fn BeginPath(&self) { - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::BeginPath)).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::BeginPath); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-closepath fn ClosePath(&self) { - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::ClosePath)).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::ClosePath); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-fill fn Fill(&self, _: CanvasFillRule) { // TODO: Process fill rule - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Fill)).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::Fill); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-stroke fn Stroke(&self) { - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Stroke)).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::Stroke); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-clip fn Clip(&self, _: CanvasFillRule) { // TODO: Process fill rule - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Clip)).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::Clip); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-ispointinpath @@ -784,16 +792,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { CanvasFillRule::Evenodd => FillRule::Evenodd, }; let (sender, receiver) = ipc::channel::(self.global().time_profiler_chan().clone()).unwrap(); - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::IsPointInPath(x, y, fill_rule, sender))) - .unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::IsPointInPath(x, y, fill_rule, sender)); receiver.recv().unwrap() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-filltext fn FillText(&self, text: DOMString, x: f64, y: f64, max_width: Option) { let parsed_text: String = text.into(); - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::FillText(parsed_text, x, y, max_width))).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::FillText(parsed_text, x, y, max_width)); self.mark_as_dirty(); } @@ -858,9 +864,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { if !(x.is_finite() && y.is_finite()) { return; } - - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::MoveTo(Point2D::new(x as f32, y as f32))); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::MoveTo(Point2D::new(x as f32, y as f32))); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-lineto @@ -868,9 +872,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { if !(x.is_finite() && y.is_finite()) { return; } - - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::LineTo(Point2D::new(x as f32, y as f32))); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::LineTo(Point2D::new(x as f32, y as f32))); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-rect @@ -878,8 +880,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { if [x, y, width, height].iter().all(|val| val.is_finite()) { let rect = Rect::new(Point2D::new(x as f32, y as f32), Size2D::new(width as f32, height as f32)); - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::Rect(rect)); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::Rect(rect)); } } @@ -888,12 +889,10 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { if !(cpx.is_finite() && cpy.is_finite() && x.is_finite() && y.is_finite()) { return; } - - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::QuadraticCurveTo(Point2D::new(cpx as f32, - cpy as f32), - Point2D::new(x as f32, - y as f32))); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::QuadraticCurveTo(Point2D::new(cpx as f32, + cpy as f32), + Point2D::new(x as f32, + y as f32))); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-beziercurveto @@ -902,13 +901,11 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { x.is_finite() && y.is_finite()) { return; } - - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::BezierCurveTo(Point2D::new(cp1x as f32, - cp1y as f32), - Point2D::new(cp2x as f32, - cp2y as f32), - Point2D::new(x as f32, y as f32))); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::BezierCurveTo(Point2D::new(cp1x as f32, + cp1y as f32), + Point2D::new(cp2x as f32, + cp2y as f32), + Point2D::new(x as f32, y as f32))); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-arc @@ -921,13 +918,11 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { return Err(Error::IndexSize); } - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::Arc(Point2D::new(x as f32, y as f32), - r as f32, - start as f32, - end as f32, - ccw)); - - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::Arc(Point2D::new(x as f32, y as f32), + r as f32, + start as f32, + end as f32, + ccw)); Ok(()) } @@ -940,10 +935,9 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { return Err(Error::IndexSize); } - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::ArcTo(Point2D::new(cp1x as f32, cp1y as f32), - Point2D::new(cp2x as f32, cp2y as f32), - r as f32)); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::ArcTo(Point2D::new(cp1x as f32, cp1y as f32), + Point2D::new(cp2x as f32, cp2y as f32), + r as f32)); Ok(()) } @@ -956,14 +950,13 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { return Err(Error::IndexSize); } - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::Ellipse(Point2D::new(x as f32, y as f32), - rx as f32, - ry as f32, - rotation as f32, - start as f32, - end as f32, - ccw)); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::Ellipse(Point2D::new(x as f32, y as f32), + rx as f32, + ry as f32, + rotation as f32, + start as f32, + end as f32, + ccw)); Ok(()) } @@ -1001,25 +994,19 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { StringOrCanvasGradientOrCanvasPattern::String(string) => { if let Ok(rgba) = self.parse_color(&string) { self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Color(rgba); - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::SetStrokeStyle( - FillOrStrokeStyle::Color(rgba)))) - .unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle( + FillOrStrokeStyle::Color(rgba))); } }, StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => { self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient)); - let msg = CanvasMsg::Canvas2d( - Canvas2dMsg::SetStrokeStyle(gradient.to_fill_or_stroke_style())); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(gradient.to_fill_or_stroke_style())); }, StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => { self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern)); - let msg = CanvasMsg::Canvas2d( - Canvas2dMsg::SetStrokeStyle(pattern.to_fill_or_stroke_style())); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(pattern.to_fill_or_stroke_style())); if !pattern.origin_is_clean() { self.set_origin_unclean(); } @@ -1050,25 +1037,19 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { StringOrCanvasGradientOrCanvasPattern::String(string) => { if let Ok(rgba) = self.parse_color(&string) { self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Color(rgba); - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::SetFillStyle( - FillOrStrokeStyle::Color(rgba)))) - .unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle( + FillOrStrokeStyle::Color(rgba))) } } StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => { self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient)); - let msg = CanvasMsg::Canvas2d( - Canvas2dMsg::SetFillStyle(gradient.to_fill_or_stroke_style())); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(gradient.to_fill_or_stroke_style())); } StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => { self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern)); - let msg = CanvasMsg::Canvas2d( - Canvas2dMsg::SetFillStyle(pattern.to_fill_or_stroke_style())); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(pattern.to_fill_or_stroke_style())); if !pattern.origin_is_clean() { self.set_origin_unclean(); } @@ -1132,10 +1113,8 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { Size2D::new(sw as i32, sh as i32)); let canvas_size = self.canvas.as_ref().map(|c| c.get_size()).unwrap_or(Size2D::zero()); let canvas_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64); - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::GetImageData(dest_rect, canvas_size, sender))) - .unwrap(); - let mut data = Vec::from(receiver.recv().unwrap()); + self.send_canvas_2d_msg(Canvas2dMsg::GetImageData(dest_rect, canvas_size, sender)); + let mut data = receiver.recv().unwrap(); // Un-premultiply alpha for chunk in data.chunks_mut(4) { @@ -1145,7 +1124,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { chunk[2] = UNPREMULTIPLY_TABLE[256 * alpha + chunk[2] as usize]; } - ImageData::new(&self.global(), sw, sh, Some(data)) + ImageData::new(&self.global(), sw, sh, Some(data.to_vec())) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata @@ -1174,13 +1153,10 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { let dirty_rect = Rect::new(Point2D::new(*dirty_x, *dirty_y), Size2D::new(*dirty_width, *dirty_height)); - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::PutImageData( - data.into(), - offset, - image_data_size, - dirty_rect, - )); - self.ipc_renderer.send(msg).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::PutImageData(data.into(), + offset, + image_data_size, + dirty_rect)); self.mark_as_dirty(); } @@ -1282,9 +1258,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } self.state.borrow_mut().line_width = width; - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::SetLineWidth(width as f32))) - .unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetLineWidth(width as f32)) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap @@ -1304,7 +1278,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { CanvasLineCap::Square => LineCapStyle::Square, }; self.state.borrow_mut().line_cap = line_cap; - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetLineCap(line_cap))).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::SetLineCap(line_cap)); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin @@ -1324,7 +1298,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { CanvasLineJoin::Miter => LineJoinStyle::Miter, }; self.state.borrow_mut().line_join = line_join; - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetLineJoin(line_join))).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::SetLineJoin(line_join)); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit @@ -1340,9 +1314,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } self.state.borrow_mut().miter_limit = limit; - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::SetMiterLimit(limit as f32))) - .unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetMiterLimit(limit as f32)) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx @@ -1356,7 +1328,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { return; } self.state.borrow_mut().shadow_offset_x = value; - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetShadowOffsetX(value))).unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetShadowOffsetX(value)) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety @@ -1370,7 +1342,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { return; } self.state.borrow_mut().shadow_offset_y = value; - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetShadowOffsetY(value))).unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetShadowOffsetY(value)) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur @@ -1384,7 +1356,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { return; } self.state.borrow_mut().shadow_blur = value; - self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetShadowBlur(value))).unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetShadowBlur(value)) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor @@ -1398,16 +1370,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { fn SetShadowColor(&self, value: DOMString) { if let Ok(color) = parse_color(&value) { self.state.borrow_mut().shadow_color = color; - self.ipc_renderer - .send(CanvasMsg::Canvas2d(Canvas2dMsg::SetShadowColor(color))) - .unwrap() + self.send_canvas_2d_msg(Canvas2dMsg::SetShadowColor(color)) } } } impl Drop for CanvasRenderingContext2D { fn drop(&mut self) { - if let Err(err) = self.ipc_renderer.send(CanvasMsg::Close) { + if let Err(err) = self.ipc_renderer.send(CanvasMsg::Close(self.get_canvas_id())) { warn!("Could not close canvas: {}", err) } } -- cgit v1.2.3 From f3065f370723566b570625dead7042f4cd553b74 Mon Sep 17 00:00:00 2001 From: Brody-Eastwood <37410352+Brody-Eastwood@users.noreply.github.com> Date: Sun, 22 Apr 2018 20:21:38 -0400 Subject: Moved Canvas rendering to a single thread. --- components/script/dom/canvasrenderingcontext2d.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index ee101251635..67cbceab896 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -371,20 +371,19 @@ impl CanvasRenderingContext2D { None => return Err(Error::InvalidState), }; - let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); - let msg = CanvasMsg::Canvas2d(Canvas2dMsg::DrawImageInOther( - self.ipc_renderer.clone(), - self.get_canvas_id(), - image_size, - dest_rect, - source_rect, - smoothing_enabled, - sender), - context.get_canvas_id()); + let msg = CanvasMsg::Canvas2d( + Canvas2dMsg::DrawImageInOther( + self.get_canvas_id(), + image_size, + dest_rect, + source_rect, + smoothing_enabled + ), + context.get_canvas_id() + ); let renderer = context.get_ipc_renderer(); renderer.send(msg).unwrap(); - receiver.recv().unwrap(); }; self.mark_as_dirty(); -- cgit v1.2.3 From b5c469d52ec0c91d29f1c314406b591a8f75c46a Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 13 Sep 2018 16:12:47 +0200 Subject: Merge byte swap and unmultiplying loops in ctx.getImageData() --- components/script/dom/canvasrenderingcontext2d.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 67cbceab896..e362fe40a05 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -1115,12 +1115,12 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { self.send_canvas_2d_msg(Canvas2dMsg::GetImageData(dest_rect, canvas_size, sender)); let mut data = receiver.recv().unwrap(); - // Un-premultiply alpha + // Byte swap and unmultiply alpha. for chunk in data.chunks_mut(4) { - let alpha = chunk[3] as usize; - chunk[0] = UNPREMULTIPLY_TABLE[256 * alpha + chunk[0] as usize]; - chunk[1] = UNPREMULTIPLY_TABLE[256 * alpha + chunk[1] as usize]; - chunk[2] = UNPREMULTIPLY_TABLE[256 * alpha + chunk[2] as usize]; + let (b, g, r, a) = (chunk[0], chunk[1], chunk[2], chunk[3]); + chunk[0] = UNPREMULTIPLY_TABLE[256 * (a as usize) + r as usize]; + chunk[1] = UNPREMULTIPLY_TABLE[256 * (a as usize) + g as usize]; + chunk[2] = UNPREMULTIPLY_TABLE[256 * (a as usize) + b as usize]; } ImageData::new(&self.global(), sw, sh, Some(data.to_vec())) -- cgit v1.2.3 From 2f2331f149cedf54618298bb537d308b84414e05 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 13 Sep 2018 16:21:57 +0200 Subject: Use a byte channel to retrieve pixels of 2D canvas --- components/script/dom/canvasrenderingcontext2d.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index e362fe40a05..5ee0a4c2204 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -32,7 +32,7 @@ use dom::imagedata::ImageData; use dom::node::{Node, NodeDamage, window_from_node}; use dom_struct::dom_struct; use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D, vec2}; -use ipc_channel::ipc::IpcSender; +use ipc_channel::ipc::{self, IpcSender}; use net_traits::image::base::PixelFormat; use net_traits::image_cache::CanRequestImages; use net_traits::image_cache::ImageCache; @@ -41,7 +41,7 @@ use net_traits::image_cache::ImageResponse; use net_traits::image_cache::ImageState; use net_traits::image_cache::UsePlaceholder; use num_traits::ToPrimitive; -use profile_traits::ipc; +use profile_traits::ipc as profiled_ipc; use script_traits::ScriptMsg; use servo_url::ServoUrl; use std::{cmp, fmt, mem}; @@ -130,7 +130,7 @@ impl CanvasRenderingContext2D { size: Size2D) -> CanvasRenderingContext2D { debug!("Creating new canvas rendering context."); - let (sender, receiver) = ipc::channel(global.time_profiler_chan().clone()).unwrap(); + let (sender, receiver) = profiled_ipc::channel(global.time_profiler_chan().clone()).unwrap(); let script_to_constellation_chan = global.script_to_constellation_chan(); debug!("Asking constellation to create new canvas thread."); script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, sender)).unwrap(); @@ -790,7 +790,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { CanvasFillRule::Nonzero => FillRule::Nonzero, CanvasFillRule::Evenodd => FillRule::Evenodd, }; - let (sender, receiver) = ipc::channel::(self.global().time_profiler_chan().clone()).unwrap(); + let (sender, receiver) = profiled_ipc::channel::(self.global().time_profiler_chan().clone()).unwrap(); self.send_canvas_2d_msg(Canvas2dMsg::IsPointInPath(x, y, fill_rule, sender)); receiver.recv().unwrap() } @@ -1107,7 +1107,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { let sh = cmp::max(1, sh.to_u32().unwrap()); let sw = cmp::max(1, sw.to_u32().unwrap()); - let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); + let (sender, receiver) = ipc::bytes_channel().unwrap(); let dest_rect = Rect::new(Point2D::new(sx.to_i32().unwrap(), sy.to_i32().unwrap()), Size2D::new(sw as i32, sh as i32)); let canvas_size = self.canvas.as_ref().map(|c| c.get_size()).unwrap_or(Size2D::zero()); -- cgit v1.2.3 From 3528ef30e56a1fce3e449eefa8f3c5bd06a595cd Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Fri, 14 Sep 2018 14:01:03 +0200 Subject: Update CanvasRenderingContext2D WebIDL definition CanvasImageSource was never supposed to include CanvasRenderingContext2D. --- components/script/dom/canvasrenderingcontext2d.rs | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 5ee0a4c2204..24d6af0282d 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -246,8 +246,6 @@ impl CanvasRenderingContext2D { CanvasImageSource::HTMLCanvasElement(canvas) => { canvas.origin_is_clean() } - CanvasImageSource::CanvasRenderingContext2D(image) => - image.origin_is_clean(), CanvasImageSource::HTMLImageElement(image) => { let image_origin = image.get_origin().expect("Image's origin is missing"); image_origin.same_origin(GlobalScope::entry().origin()) @@ -294,11 +292,6 @@ impl CanvasRenderingContext2D { sx, sy, sw, sh, dx, dy, dw, dh) } - CanvasImageSource::CanvasRenderingContext2D(ref image) => { - self.draw_html_canvas_element(&image.Canvas(), - sx, sy, sw, sh, - dx, dy, dw, dh) - } CanvasImageSource::HTMLImageElement(ref image) => { // https://html.spec.whatwg.org/multipage/#img-error // If the image argument is an HTMLImageElement object that is in the broken state, @@ -1216,12 +1209,6 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { canvas.fetch_all_data().ok_or(Error::InvalidState)? }, - CanvasImageSource::CanvasRenderingContext2D(ref context) => { - let canvas = context.Canvas(); - let _ = canvas.get_or_init_2d_context(); - - canvas.fetch_all_data().ok_or(Error::InvalidState)? - } CanvasImageSource::CSSStyleValue(ref value) => { value.get_url(self.base_url.clone()) .and_then(|url| self.fetch_image_data(url)) -- cgit v1.2.3 From f1e8eb640cd59864a3f32c0557a35a1c65a2b8d3 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 15 Sep 2018 12:28:53 +0200 Subject: Don't create 2D canvas contexts arbitrarily Sometimes, the canvas still has no rendering context, in this case it represents a transparent black rectangle. --- components/script/dom/canvasrenderingcontext2d.rs | 104 ++++++++++++---------- 1 file changed, 58 insertions(+), 46 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 24d6af0282d..12e3ad17959 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -27,7 +27,7 @@ use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeSty use dom::canvaspattern::CanvasPattern; use dom::element::Element; use dom::globalscope::GlobalScope; -use dom::htmlcanvaselement::HTMLCanvasElement; +use dom::htmlcanvaselement::{CanvasContext, HTMLCanvasElement}; use dom::imagedata::ImageData; use dom::node::{Node, NodeDamage, window_from_node}; use dom_struct::dom_struct; @@ -315,17 +315,18 @@ impl CanvasRenderingContext2D { result } - fn draw_html_canvas_element(&self, - canvas: &HTMLCanvasElement, - sx: f64, - sy: f64, - sw: Option, - sh: Option, - dx: f64, - dy: f64, - dw: Option, - dh: Option) - -> ErrorResult { + fn draw_html_canvas_element( + &self, + canvas: &HTMLCanvasElement, + sx: f64, + sy: f64, + sw: Option, + sh: Option, + dx: f64, + dy: f64, + dw: Option, + dh: Option, + ) -> ErrorResult { // 1. Check the usability of the image argument if !canvas.is_valid() { return Err(Error::InvalidState); @@ -339,15 +340,17 @@ impl CanvasRenderingContext2D { let image_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64); // 2. Establish the source and destination rectangles - let (source_rect, dest_rect) = self.adjust_source_dest_rects(image_size, - sx, - sy, - sw, - sh, - dx, - dy, - dw, - dh); + let (source_rect, dest_rect) = self.adjust_source_dest_rects( + image_size, + sx, + sy, + sw, + sh, + dx, + dy, + dw, + dh, + ); if !is_rect_valid(source_rect) || !is_rect_valid(dest_rect) { return Ok(()); @@ -355,29 +358,40 @@ impl CanvasRenderingContext2D { let smoothing_enabled = self.state.borrow().image_smoothing_enabled; - if self.canvas.as_ref().map_or(false, |c| &**c == canvas) { - self.send_canvas_2d_msg(Canvas2dMsg::DrawImageSelf( - image_size, dest_rect, source_rect, smoothing_enabled)); + if let Some(context) = canvas.context() { + match *context { + CanvasContext::Context2d(ref context) => { + if self.canvas.as_ref().map_or(false, |c| &**c == canvas) { + self.send_canvas_2d_msg(Canvas2dMsg::DrawImageSelf( + image_size, + dest_rect, + source_rect, + smoothing_enabled, + )); + } else { + context.get_ipc_renderer().send(CanvasMsg::Canvas2d( + Canvas2dMsg::DrawImageInOther( + self.get_canvas_id(), + image_size, + dest_rect, + source_rect, + smoothing_enabled, + ), + context.get_canvas_id(), + )).unwrap(); + } + }, + _ => return Err(Error::InvalidState), + } } else { - let context = match canvas.get_or_init_2d_context() { - Some(context) => context, - None => return Err(Error::InvalidState), - }; - - let msg = CanvasMsg::Canvas2d( - Canvas2dMsg::DrawImageInOther( - self.get_canvas_id(), - image_size, - dest_rect, - source_rect, - smoothing_enabled - ), - context.get_canvas_id() - ); - - let renderer = context.get_ipc_renderer(); - renderer.send(msg).unwrap(); - }; + self.send_canvas_2d_msg(Canvas2dMsg::DrawImage( + None, + image_size, + dest_rect, + source_rect, + smoothing_enabled, + )); + } self.mark_as_dirty(); Ok(()) @@ -447,7 +461,7 @@ impl CanvasRenderingContext2D { let smoothing_enabled = self.state.borrow().image_smoothing_enabled; self.send_canvas_2d_msg(Canvas2dMsg::DrawImage( - image_data.into(), + Some(image_data.into()), image_size, dest_rect, source_rect, @@ -1205,8 +1219,6 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { .ok_or(Error::InvalidState)? }, CanvasImageSource::HTMLCanvasElement(ref canvas) => { - let _ = canvas.get_or_init_2d_context(); - canvas.fetch_all_data().ok_or(Error::InvalidState)? }, CanvasImageSource::CSSStyleValue(ref value) => { -- cgit v1.2.3 From 36c8cd229e0734efc374968964c8485ac45bbbf3 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 16 Sep 2018 22:12:44 +0200 Subject: Remove Canvas2dMsg::DrawImageSelf Now that all canvas share the same thread, it's useless to have a separate message for that. --- components/script/dom/canvasrenderingcontext2d.rs | 26 ++++++----------------- 1 file changed, 7 insertions(+), 19 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 12e3ad17959..0da01cc8453 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -361,25 +361,13 @@ impl CanvasRenderingContext2D { if let Some(context) = canvas.context() { match *context { CanvasContext::Context2d(ref context) => { - if self.canvas.as_ref().map_or(false, |c| &**c == canvas) { - self.send_canvas_2d_msg(Canvas2dMsg::DrawImageSelf( - image_size, - dest_rect, - source_rect, - smoothing_enabled, - )); - } else { - context.get_ipc_renderer().send(CanvasMsg::Canvas2d( - Canvas2dMsg::DrawImageInOther( - self.get_canvas_id(), - image_size, - dest_rect, - source_rect, - smoothing_enabled, - ), - context.get_canvas_id(), - )).unwrap(); - } + context.send_canvas_2d_msg(Canvas2dMsg::DrawImageInOther( + self.get_canvas_id(), + image_size, + dest_rect, + source_rect, + smoothing_enabled, + )); }, _ => return Err(Error::InvalidState), } -- cgit v1.2.3 From 8c100b23b1e2d29911f44802adc3b8cdffce38bf Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 17 Sep 2018 17:56:56 +0200 Subject: Implement proper origin checks for WebGL textures (fixes #21522) --- components/script/dom/canvasrenderingcontext2d.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 0da01cc8453..948fd0b9efe 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -247,8 +247,7 @@ impl CanvasRenderingContext2D { canvas.origin_is_clean() } CanvasImageSource::HTMLImageElement(image) => { - let image_origin = image.get_origin().expect("Image's origin is missing"); - image_origin.same_origin(GlobalScope::entry().origin()) + image.same_origin(GlobalScope::entry().origin()) } CanvasImageSource::CSSStyleValue(_) => true, } -- cgit v1.2.3 From c37a345dc9f4dda6ea29c42f96f6c7201c42cbac Mon Sep 17 00:00:00 2001 From: chansuke Date: Tue, 18 Sep 2018 23:24:15 +0900 Subject: Format script component --- components/script/dom/canvasrenderingcontext2d.rs | 718 ++++++++++++---------- 1 file changed, 408 insertions(+), 310 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 948fd0b9efe..e3ca01c311e 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -123,17 +123,21 @@ impl CanvasContextState { } impl CanvasRenderingContext2D { - pub fn new_inherited(global: &GlobalScope, - canvas: Option<&HTMLCanvasElement>, - image_cache: Arc, - base_url: ServoUrl, - size: Size2D) - -> CanvasRenderingContext2D { + pub fn new_inherited( + global: &GlobalScope, + canvas: Option<&HTMLCanvasElement>, + image_cache: Arc, + base_url: ServoUrl, + size: Size2D, + ) -> CanvasRenderingContext2D { debug!("Creating new canvas rendering context."); - let (sender, receiver) = profiled_ipc::channel(global.time_profiler_chan().clone()).unwrap(); + let (sender, receiver) = + profiled_ipc::channel(global.time_profiler_chan().clone()).unwrap(); let script_to_constellation_chan = global.script_to_constellation_chan(); debug!("Asking constellation to create new canvas thread."); - script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, sender)).unwrap(); + script_to_constellation_chan + .send(ScriptMsg::CreateCanvasPaintThread(size, sender)) + .unwrap(); let (ipc_renderer, canvas_id) = receiver.recv().unwrap(); debug!("Done."); CanvasRenderingContext2D { @@ -150,15 +154,20 @@ impl CanvasRenderingContext2D { } } - pub fn new(global: &GlobalScope, - canvas: &HTMLCanvasElement, - size: Size2D) - -> DomRoot { + pub fn new( + global: &GlobalScope, + canvas: &HTMLCanvasElement, + size: Size2D, + ) -> DomRoot { let window = window_from_node(canvas); let image_cache = window.image_cache(); let base_url = window.get_url(); let boxed = Box::new(CanvasRenderingContext2D::new_inherited( - global, Some(canvas), image_cache, base_url, size + global, + Some(canvas), + image_cache, + base_url, + size, )); reflect_dom_object(boxed, global, CanvasRenderingContext2DBinding::Wrap) } @@ -191,28 +200,35 @@ impl CanvasRenderingContext2D { // on the drawImage call arguments // source rectangle = area of the original image to be copied // destination rectangle = area of the destination canvas where the source image is going to be drawn - fn adjust_source_dest_rects(&self, - image_size: Size2D, - sx: f64, - sy: f64, - sw: f64, - sh: f64, - dx: f64, - dy: f64, - dw: f64, - dh: f64) - -> (Rect, Rect) { - let image_rect = Rect::new(Point2D::new(0f64, 0f64), - Size2D::new(image_size.width as f64, image_size.height as f64)); + fn adjust_source_dest_rects( + &self, + image_size: Size2D, + sx: f64, + sy: f64, + sw: f64, + sh: f64, + dx: f64, + dy: f64, + dw: f64, + dh: f64, + ) -> (Rect, Rect) { + let image_rect = Rect::new( + Point2D::new(0f64, 0f64), + Size2D::new(image_size.width as f64, image_size.height as f64), + ); // The source rectangle is the rectangle whose corners are the four points (sx, sy), // (sx+sw, sy), (sx+sw, sy+sh), (sx, sy+sh). - let source_rect = Rect::new(Point2D::new(sx.min(sx + sw), sy.min(sy + sh)), - Size2D::new(sw.abs(), sh.abs())); + let source_rect = Rect::new( + Point2D::new(sx.min(sx + sw), sy.min(sy + sh)), + Size2D::new(sw.abs(), sh.abs()), + ); // When the source rectangle is outside the source image, // the source rectangle must be clipped to the source image - let source_rect_clipped = source_rect.intersection(&image_rect).unwrap_or(Rect::zero()); + let source_rect_clipped = source_rect + .intersection(&image_rect) + .unwrap_or(Rect::zero()); // Width and height ratios between the non clipped and clipped source rectangles let width_ratio: f64 = source_rect_clipped.size.width / source_rect.size.width; @@ -225,27 +241,29 @@ impl CanvasRenderingContext2D { // The destination rectangle is the rectangle whose corners are the four points (dx, dy), // (dx+dw, dy), (dx+dw, dy+dh), (dx, dy+dh). - let dest_rect = Rect::new(Point2D::new(dx.min(dx + dest_rect_width_scaled), - dy.min(dy + dest_rect_height_scaled)), - Size2D::new(dest_rect_width_scaled.abs(), - dest_rect_height_scaled.abs())); + let dest_rect = Rect::new( + Point2D::new( + dx.min(dx + dest_rect_width_scaled), + dy.min(dy + dest_rect_height_scaled), + ), + Size2D::new(dest_rect_width_scaled.abs(), dest_rect_height_scaled.abs()), + ); - let source_rect = Rect::new(Point2D::new(source_rect_clipped.origin.x, - source_rect_clipped.origin.y), - Size2D::new(source_rect_clipped.size.width, - source_rect_clipped.size.height)); + let source_rect = Rect::new( + Point2D::new(source_rect_clipped.origin.x, source_rect_clipped.origin.y), + Size2D::new( + source_rect_clipped.size.width, + source_rect_clipped.size.height, + ), + ); (source_rect, dest_rect) } // https://html.spec.whatwg.org/multipage/#the-image-argument-is-not-origin-clean - fn is_origin_clean(&self, - image: CanvasImageSource) - -> bool { + fn is_origin_clean(&self, image: CanvasImageSource) -> bool { match image { - CanvasImageSource::HTMLCanvasElement(canvas) => { - canvas.origin_is_clean() - } + CanvasImageSource::HTMLCanvasElement(canvas) => canvas.origin_is_clean(), CanvasImageSource::HTMLImageElement(image) => { image.same_origin(GlobalScope::entry().origin()) } @@ -274,38 +292,35 @@ impl CanvasRenderingContext2D { // is copied on the rectangle (dx, dy, dh, dw) of the destination canvas // // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage - fn draw_image(&self, - image: CanvasImageSource, - sx: f64, - sy: f64, - sw: Option, - sh: Option, - dx: f64, - dy: f64, - dw: Option, - dh: Option) - -> ErrorResult { + fn draw_image( + &self, + image: CanvasImageSource, + sx: f64, + sy: f64, + sw: Option, + sh: Option, + dx: f64, + dy: f64, + dw: Option, + dh: Option, + ) -> ErrorResult { let result = match image { CanvasImageSource::HTMLCanvasElement(ref canvas) => { - self.draw_html_canvas_element(&canvas, - sx, sy, sw, sh, - dx, dy, dw, dh) - } + self.draw_html_canvas_element(&canvas, sx, sy, sw, sh, dx, dy, dw, dh) + }, CanvasImageSource::HTMLImageElement(ref image) => { // https://html.spec.whatwg.org/multipage/#img-error // If the image argument is an HTMLImageElement object that is in the broken state, // then throw an InvalidStateError exception let url = image.get_url().ok_or(Error::InvalidState)?; - self.fetch_and_draw_image_data(url, - sx, sy, sw, sh, - dx, dy, dw, dh) - } + self.fetch_and_draw_image_data(url, sx, sy, sw, sh, dx, dy, dw, dh) + }, CanvasImageSource::CSSStyleValue(ref value) => { - let url = value.get_url(self.base_url.clone()).ok_or(Error::InvalidState)?; - self.fetch_and_draw_image_data(url, - sx, sy, sw, sh, - dx, dy, dw, dh) - } + let url = value + .get_url(self.base_url.clone()) + .ok_or(Error::InvalidState)?; + self.fetch_and_draw_image_data(url, sx, sy, sw, sh, dx, dy, dw, dh) + }, }; if result.is_ok() && !self.is_origin_clean(image) { @@ -339,17 +354,8 @@ impl CanvasRenderingContext2D { let image_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64); // 2. Establish the source and destination rectangles - let (source_rect, dest_rect) = self.adjust_source_dest_rects( - image_size, - sx, - sy, - sw, - sh, - dx, - dy, - dw, - dh, - ); + let (source_rect, dest_rect) = + self.adjust_source_dest_rects(image_size, sx, sy, sw, sh, dx, dy, dw, dh); if !is_rect_valid(source_rect) || !is_rect_valid(dest_rect) { return Ok(()); @@ -384,17 +390,18 @@ impl CanvasRenderingContext2D { Ok(()) } - fn fetch_and_draw_image_data(&self, - url: ServoUrl, - sx: f64, - sy: f64, - sw: Option, - sh: Option, - dx: f64, - dy: f64, - dw: Option, - dh: Option) - -> ErrorResult { + fn fetch_and_draw_image_data( + &self, + url: ServoUrl, + sx: f64, + sy: f64, + sw: Option, + sh: Option, + dx: f64, + dy: f64, + dw: Option, + dh: Option, + ) -> ErrorResult { debug!("Fetching image {}.", url); // https://html.spec.whatwg.org/multipage/#img-error // If the image argument is an HTMLImageElement object that is in the broken state, @@ -413,34 +420,25 @@ impl CanvasRenderingContext2D { let dh = dh.unwrap_or(image_size.height); let sw = sw.unwrap_or(image_size.width); let sh = sh.unwrap_or(image_size.height); - self.draw_image_data(image_data, - image_size, - sx, sy, sw, sh, - dx, dy, dw, dh) - } - - fn draw_image_data(&self, - image_data: Vec, - image_size: Size2D, - sx: f64, - sy: f64, - sw: f64, - sh: f64, - dx: f64, - dy: f64, - dw: f64, - dh: f64) - -> ErrorResult { + self.draw_image_data(image_data, image_size, sx, sy, sw, sh, dx, dy, dw, dh) + } + + fn draw_image_data( + &self, + image_data: Vec, + image_size: Size2D, + sx: f64, + sy: f64, + sw: f64, + sh: f64, + dx: f64, + dy: f64, + dw: f64, + dh: f64, + ) -> ErrorResult { // Establish the source and destination rectangles - let (source_rect, dest_rect) = self.adjust_source_dest_rects(image_size, - sx, - sy, - sw, - sh, - dx, - dy, - dw, - dh); + let (source_rect, dest_rect) = + self.adjust_source_dest_rects(image_size, sx, sy, sw, sh, dx, dy, dw, dh); if !is_rect_valid(source_rect) || !is_rect_valid(dest_rect) { return Ok(()); @@ -465,7 +463,7 @@ impl CanvasRenderingContext2D { ImageResponse::None | ImageResponse::MetadataLoaded(_) => { return None; - } + }, }; let image_size = Size2D::new(img.width as i32, img.height as i32); @@ -481,15 +479,16 @@ impl CanvasRenderingContext2D { #[inline] fn request_image_from_cache(&self, url: ServoUrl) -> ImageResponse { - let response = self.image_cache - .find_image_or_metadata(url.clone(), - UsePlaceholder::No, - CanRequestImages::No); + let response = self.image_cache.find_image_or_metadata( + url.clone(), + UsePlaceholder::No, + CanRequestImages::No, + ); match response { - Ok(ImageOrMetadataAvailable::ImageAvailable(image, url)) => - ImageResponse::Loaded(image, url), - Err(ImageState::Pending(_)) => - ImageResponse::None, + Ok(ImageOrMetadataAvailable::ImageAvailable(image, url)) => { + ImageResponse::Loaded(image, url) + }, + Err(ImageState::Pending(_)) => ImageResponse::None, _ => { // Rather annoyingly, we get the same response back from // A load which really failed and from a load which hasn't started yet. @@ -512,8 +511,10 @@ impl CanvasRenderingContext2D { return None; } - Some(Rect::new(Point2D::new(x as f32, y as f32), - Size2D::new(w as f32, h as f32))) + Some(Rect::new( + Point2D::new(x as f32, y as f32), + Size2D::new(w as f32, h as f32), + )) } fn parse_color(&self, string: &str) -> Result { @@ -540,11 +541,13 @@ impl CanvasRenderingContext2D { let canvas_element = canvas.upcast::(); match canvas_element.style() { - Some(ref s) if canvas_element.has_css_layout_box() => Ok(s.get_color().color), - _ => Ok(RGBA::new(0, 0, 0, 255)) + Some(ref s) if canvas_element.has_css_layout_box() => { + Ok(s.get_color().color) + }, + _ => Ok(RGBA::new(0, 0, 0, 255)), } }, - _ => Err(()) + _ => Err(()), } } else { Err(()) @@ -556,7 +559,9 @@ impl CanvasRenderingContext2D { } pub fn send_canvas_2d_msg(&self, msg: Canvas2dMsg) { - self.ipc_renderer.send(CanvasMsg::Canvas2d(msg, self.get_canvas_id())).unwrap() + self.ipc_renderer + .send(CanvasMsg::Canvas2d(msg, self.get_canvas_id())) + .unwrap() } pub fn get_ipc_renderer(&self) -> IpcSender { @@ -610,7 +615,9 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-save fn Save(&self) { - self.saved_states.borrow_mut().push(self.state.borrow().clone()); + self.saved_states + .borrow_mut() + .push(self.state.borrow().clone()); self.send_canvas_2d_msg(Canvas2dMsg::SaveContext); } @@ -643,10 +650,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { let (sin, cos) = (angle.sin(), angle.cos()); let transform = self.state.borrow().transform; - self.state.borrow_mut().transform = transform.pre_mul( - &Transform2D::row_major(cos as f32, sin as f32, - -sin as f32, cos as f32, - 0.0, 0.0)); + self.state.borrow_mut().transform = transform.pre_mul(&Transform2D::row_major( + cos as f32, + sin as f32, + -sin as f32, + cos as f32, + 0.0, + 0.0, + )); self.update_transform() } @@ -663,21 +674,32 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-transform fn Transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) { - if !(a.is_finite() && b.is_finite() && c.is_finite() && - d.is_finite() && e.is_finite() && f.is_finite()) { + if !(a.is_finite() && + b.is_finite() && + c.is_finite() && + d.is_finite() && + e.is_finite() && + f.is_finite()) + { return; } let transform = self.state.borrow().transform; - self.state.borrow_mut().transform = transform.pre_mul( - &Transform2D::row_major(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32)); + self.state.borrow_mut().transform = transform.pre_mul(&Transform2D::row_major( + a as f32, b as f32, c as f32, d as f32, e as f32, f as f32, + )); self.update_transform() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-settransform fn SetTransform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) { - if !(a.is_finite() && b.is_finite() && c.is_finite() && - d.is_finite() && e.is_finite() && f.is_finite()) { + if !(a.is_finite() && + b.is_finite() && + c.is_finite() && + d.is_finite() && + e.is_finite() && + f.is_finite()) + { return; } @@ -784,7 +806,8 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { CanvasFillRule::Nonzero => FillRule::Nonzero, CanvasFillRule::Evenodd => FillRule::Evenodd, }; - let (sender, receiver) = profiled_ipc::channel::(self.global().time_profiler_chan().clone()).unwrap(); + let (sender, receiver) = + profiled_ipc::channel::(self.global().time_profiler_chan().clone()).unwrap(); self.send_canvas_2d_msg(Canvas2dMsg::IsPointInPath(x, y, fill_rule, sender)); receiver.recv().unwrap() } @@ -797,11 +820,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage - fn DrawImage(&self, - image: CanvasImageSource, - dx: f64, - dy: f64) - -> ErrorResult { + fn DrawImage(&self, image: CanvasImageSource, dx: f64, dy: f64) -> ErrorResult { if !(dx.is_finite() && dy.is_finite()) { return Ok(()); } @@ -810,13 +829,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage - fn DrawImage_(&self, - image: CanvasImageSource, - dx: f64, - dy: f64, - dw: f64, - dh: f64) - -> ErrorResult { + fn DrawImage_( + &self, + image: CanvasImageSource, + dx: f64, + dy: f64, + dw: f64, + dh: f64, + ) -> ErrorResult { if !(dx.is_finite() && dy.is_finite() && dw.is_finite() && dh.is_finite()) { return Ok(()); } @@ -825,31 +845,41 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage - fn DrawImage__(&self, - image: CanvasImageSource, - sx: f64, - sy: f64, - sw: f64, - sh: f64, - dx: f64, - dy: f64, - dw: f64, - dh: f64) - -> ErrorResult { - if !(sx.is_finite() && sy.is_finite() && sw.is_finite() && sh.is_finite() && - dx.is_finite() && dy.is_finite() && dw.is_finite() && dh.is_finite()) { + fn DrawImage__( + &self, + image: CanvasImageSource, + sx: f64, + sy: f64, + sw: f64, + sh: f64, + dx: f64, + dy: f64, + dw: f64, + dh: f64, + ) -> ErrorResult { + if !(sx.is_finite() && + sy.is_finite() && + sw.is_finite() && + sh.is_finite() && + dx.is_finite() && + dy.is_finite() && + dw.is_finite() && + dh.is_finite()) + { return Ok(()); } - self.draw_image(image, - sx, - sy, - Some(sw), - Some(sh), - dx, - dy, - Some(dw), - Some(dh)) + self.draw_image( + image, + sx, + sy, + Some(sw), + Some(sh), + dx, + dy, + Some(dw), + Some(dh), + ) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-moveto @@ -871,8 +901,10 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-rect fn Rect(&self, x: f64, y: f64, width: f64, height: f64) { if [x, y, width, height].iter().all(|val| val.is_finite()) { - let rect = Rect::new(Point2D::new(x as f32, y as f32), - Size2D::new(width as f32, height as f32)); + let rect = Rect::new( + Point2D::new(x as f32, y as f32), + Size2D::new(width as f32, height as f32), + ); self.send_canvas_2d_msg(Canvas2dMsg::Rect(rect)); } } @@ -882,23 +914,28 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { if !(cpx.is_finite() && cpy.is_finite() && x.is_finite() && y.is_finite()) { return; } - self.send_canvas_2d_msg(Canvas2dMsg::QuadraticCurveTo(Point2D::new(cpx as f32, - cpy as f32), - Point2D::new(x as f32, - y as f32))); + self.send_canvas_2d_msg(Canvas2dMsg::QuadraticCurveTo( + Point2D::new(cpx as f32, cpy as f32), + Point2D::new(x as f32, y as f32), + )); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-beziercurveto fn BezierCurveTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) { - if !(cp1x.is_finite() && cp1y.is_finite() && cp2x.is_finite() && cp2y.is_finite() && - x.is_finite() && y.is_finite()) { + if !(cp1x.is_finite() && + cp1y.is_finite() && + cp2x.is_finite() && + cp2y.is_finite() && + x.is_finite() && + y.is_finite()) + { return; } - self.send_canvas_2d_msg(Canvas2dMsg::BezierCurveTo(Point2D::new(cp1x as f32, - cp1y as f32), - Point2D::new(cp2x as f32, - cp2y as f32), - Point2D::new(x as f32, y as f32))); + self.send_canvas_2d_msg(Canvas2dMsg::BezierCurveTo( + Point2D::new(cp1x as f32, cp1y as f32), + Point2D::new(cp2x as f32, cp2y as f32), + Point2D::new(x as f32, y as f32), + )); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-arc @@ -911,11 +948,13 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { return Err(Error::IndexSize); } - self.send_canvas_2d_msg(Canvas2dMsg::Arc(Point2D::new(x as f32, y as f32), - r as f32, - start as f32, - end as f32, - ccw)); + self.send_canvas_2d_msg(Canvas2dMsg::Arc( + Point2D::new(x as f32, y as f32), + r as f32, + start as f32, + end as f32, + ccw, + )); Ok(()) } @@ -928,28 +967,45 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { return Err(Error::IndexSize); } - self.send_canvas_2d_msg(Canvas2dMsg::ArcTo(Point2D::new(cp1x as f32, cp1y as f32), - Point2D::new(cp2x as f32, cp2y as f32), - r as f32)); + self.send_canvas_2d_msg(Canvas2dMsg::ArcTo( + Point2D::new(cp1x as f32, cp1y as f32), + Point2D::new(cp2x as f32, cp2y as f32), + r as f32, + )); Ok(()) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-ellipse - fn Ellipse(&self, x: f64, y: f64, rx: f64, ry: f64, rotation: f64, start: f64, end: f64, ccw: bool) -> ErrorResult { - if !([x, y, rx, ry, rotation, start, end].iter().all(|x| x.is_finite())) { + fn Ellipse( + &self, + x: f64, + y: f64, + rx: f64, + ry: f64, + rotation: f64, + start: f64, + end: f64, + ccw: bool, + ) -> ErrorResult { + if !([x, y, rx, ry, rotation, start, end] + .iter() + .all(|x| x.is_finite())) + { return Ok(()); } if rx < 0.0 || ry < 0.0 { return Err(Error::IndexSize); } - self.send_canvas_2d_msg(Canvas2dMsg::Ellipse(Point2D::new(x as f32, y as f32), - rx as f32, - ry as f32, - rotation as f32, - start as f32, - end as f32, - ccw)); + self.send_canvas_2d_msg(Canvas2dMsg::Ellipse( + Point2D::new(x as f32, y as f32), + rx as f32, + ry as f32, + rotation as f32, + start as f32, + end as f32, + ccw, + )); Ok(()) } @@ -977,7 +1033,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { }, CanvasFillOrStrokeStyle::Pattern(ref pattern) => { StringOrCanvasGradientOrCanvasPattern::CanvasPattern(DomRoot::from_ref(&*pattern)) - } + }, } } @@ -987,23 +1043,28 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { StringOrCanvasGradientOrCanvasPattern::String(string) => { if let Ok(rgba) = self.parse_color(&string) { self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Color(rgba); - self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle( - FillOrStrokeStyle::Color(rgba))); + self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(FillOrStrokeStyle::Color( + rgba, + ))); } }, StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => { self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient)); - self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(gradient.to_fill_or_stroke_style())); + self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle( + gradient.to_fill_or_stroke_style(), + )); }, StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => { self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern)); - self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(pattern.to_fill_or_stroke_style())); + self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle( + pattern.to_fill_or_stroke_style(), + )); if !pattern.origin_is_clean() { self.set_origin_unclean(); } - } + }, } } @@ -1020,7 +1081,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { }, CanvasFillOrStrokeStyle::Pattern(ref pattern) => { StringOrCanvasGradientOrCanvasPattern::CanvasPattern(DomRoot::from_ref(&*pattern)) - } + }, } } @@ -1030,23 +1091,28 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { StringOrCanvasGradientOrCanvasPattern::String(string) => { if let Ok(rgba) = self.parse_color(&string) { self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Color(rgba); - self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle( - FillOrStrokeStyle::Color(rgba))) + self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(FillOrStrokeStyle::Color( + rgba, + ))) } - } + }, StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => { self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient)); - self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(gradient.to_fill_or_stroke_style())); - } + self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle( + gradient.to_fill_or_stroke_style(), + )); + }, StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => { self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern)); - self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(pattern.to_fill_or_stroke_style())); + self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle( + pattern.to_fill_or_stroke_style(), + )); if !pattern.origin_is_clean() { self.set_origin_unclean(); } - } + }, } } @@ -1063,21 +1129,19 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata fn CreateImageData_(&self, imagedata: &ImageData) -> Fallible> { - ImageData::new(&self.global(), - imagedata.Width(), - imagedata.Height(), - None) + ImageData::new(&self.global(), imagedata.Width(), imagedata.Height(), None) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata - fn GetImageData(&self, - sx: Finite, - sy: Finite, - sw: Finite, - sh: Finite) - -> Fallible> { + fn GetImageData( + &self, + sx: Finite, + sy: Finite, + sw: Finite, + sh: Finite, + ) -> Fallible> { if !self.origin_is_clean() { - return Err(Error::Security) + return Err(Error::Security); } let mut sx = *sx; @@ -1102,9 +1166,15 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { let sw = cmp::max(1, sw.to_u32().unwrap()); let (sender, receiver) = ipc::bytes_channel().unwrap(); - let dest_rect = Rect::new(Point2D::new(sx.to_i32().unwrap(), sy.to_i32().unwrap()), - Size2D::new(sw as i32, sh as i32)); - let canvas_size = self.canvas.as_ref().map(|c| c.get_size()).unwrap_or(Size2D::zero()); + let dest_rect = Rect::new( + Point2D::new(sx.to_i32().unwrap(), sy.to_i32().unwrap()), + Size2D::new(sw as i32, sh as i32), + ); + let canvas_size = self + .canvas + .as_ref() + .map(|c| c.get_size()) + .unwrap_or(Size2D::zero()); let canvas_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64); self.send_canvas_2d_msg(Canvas2dMsg::GetImageData(dest_rect, canvas_size, sender)); let mut data = receiver.recv().unwrap(); @@ -1122,97 +1192,110 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata fn PutImageData(&self, imagedata: &ImageData, dx: Finite, dy: Finite) { - self.PutImageData_(imagedata, - dx, - dy, - Finite::wrap(0f64), - Finite::wrap(0f64), - Finite::wrap(imagedata.Width() as f64), - Finite::wrap(imagedata.Height() as f64)) + self.PutImageData_( + imagedata, + dx, + dy, + Finite::wrap(0f64), + Finite::wrap(0f64), + Finite::wrap(imagedata.Width() as f64), + Finite::wrap(imagedata.Height() as f64), + ) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata - fn PutImageData_(&self, - imagedata: &ImageData, - dx: Finite, - dy: Finite, - dirty_x: Finite, - dirty_y: Finite, - dirty_width: Finite, - dirty_height: Finite) { + fn PutImageData_( + &self, + imagedata: &ImageData, + dx: Finite, + dy: Finite, + dirty_x: Finite, + dirty_y: Finite, + dirty_width: Finite, + dirty_height: Finite, + ) { let data = imagedata.get_data_array(); let offset = Vector2D::new(*dx, *dy); let image_data_size = Size2D::new(imagedata.Width() as f64, imagedata.Height() as f64); - let dirty_rect = Rect::new(Point2D::new(*dirty_x, *dirty_y), - Size2D::new(*dirty_width, *dirty_height)); - self.send_canvas_2d_msg(Canvas2dMsg::PutImageData(data.into(), - offset, - image_data_size, - dirty_rect)); + let dirty_rect = Rect::new( + Point2D::new(*dirty_x, *dirty_y), + Size2D::new(*dirty_width, *dirty_height), + ); + self.send_canvas_2d_msg(Canvas2dMsg::PutImageData( + data.into(), + offset, + image_data_size, + dirty_rect, + )); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createlineargradient - fn CreateLinearGradient(&self, - x0: Finite, - y0: Finite, - x1: Finite, - y1: Finite) - -> DomRoot { - CanvasGradient::new(&self.global(), - CanvasGradientStyle::Linear(LinearGradientStyle::new(*x0, - *y0, - *x1, - *y1, - Vec::new()))) + fn CreateLinearGradient( + &self, + x0: Finite, + y0: Finite, + x1: Finite, + y1: Finite, + ) -> DomRoot { + CanvasGradient::new( + &self.global(), + CanvasGradientStyle::Linear(LinearGradientStyle::new(*x0, *y0, *x1, *y1, Vec::new())), + ) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createradialgradient - fn CreateRadialGradient(&self, - x0: Finite, - y0: Finite, - r0: Finite, - x1: Finite, - y1: Finite, - r1: Finite) - -> Fallible> { + fn CreateRadialGradient( + &self, + x0: Finite, + y0: Finite, + r0: Finite, + x1: Finite, + y1: Finite, + r1: Finite, + ) -> Fallible> { if *r0 < 0. || *r1 < 0. { return Err(Error::IndexSize); } - Ok(CanvasGradient::new(&self.global(), - CanvasGradientStyle::Radial(RadialGradientStyle::new(*x0, - *y0, - *r0, - *x1, - *y1, - *r1, - Vec::new())))) + Ok(CanvasGradient::new( + &self.global(), + CanvasGradientStyle::Radial(RadialGradientStyle::new( + *x0, + *y0, + *r0, + *x1, + *y1, + *r1, + Vec::new(), + )), + )) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern - fn CreatePattern(&self, - image: CanvasImageSource, - mut repetition: DOMString) - -> Fallible> { + fn CreatePattern( + &self, + image: CanvasImageSource, + mut repetition: DOMString, + ) -> Fallible> { let (image_data, image_size) = match image { CanvasImageSource::HTMLImageElement(ref image) => { // https://html.spec.whatwg.org/multipage/#img-error // If the image argument is an HTMLImageElement object that is in the broken state, // then throw an InvalidStateError exception - image.get_url() + image + .get_url() .and_then(|url| self.fetch_image_data(url)) .ok_or(Error::InvalidState)? }, CanvasImageSource::HTMLCanvasElement(ref canvas) => { canvas.fetch_all_data().ok_or(Error::InvalidState)? }, - CanvasImageSource::CSSStyleValue(ref value) => { - value.get_url(self.base_url.clone()) - .and_then(|url| self.fetch_image_data(url)) - .ok_or(Error::InvalidState)? - } + CanvasImageSource::CSSStyleValue(ref value) => value + .get_url(self.base_url.clone()) + .and_then(|url| self.fetch_image_data(url)) + .ok_or(Error::InvalidState)?, }; if repetition.is_empty() { @@ -1220,11 +1303,13 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } if let Ok(rep) = RepetitionStyle::from_str(&repetition) { - Ok(CanvasPattern::new(&self.global(), - image_data, - image_size, - rep, - self.is_origin_clean(image))) + Ok(CanvasPattern::new( + &self.global(), + image_data, + image_size, + rep, + self.is_origin_clean(image), + )) } else { Err(Error::Syntax) } @@ -1362,7 +1447,10 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { impl Drop for CanvasRenderingContext2D { fn drop(&mut self) { - if let Err(err) = self.ipc_renderer.send(CanvasMsg::Close(self.get_canvas_id())) { + if let Err(err) = self + .ipc_renderer + .send(CanvasMsg::Close(self.get_canvas_id())) + { warn!("Could not close canvas: {}", err) } } @@ -1391,22 +1479,32 @@ fn is_rect_valid(rect: Rect) -> bool { // https://html.spec.whatwg.org/multipage/#serialisation-of-a-colour fn serialize(color: &RGBA, dest: &mut W) -> fmt::Result - where W: fmt::Write +where + W: fmt::Write, { let red = color.red; let green = color.green; let blue = color.blue; if color.alpha == 255 { - write!(dest, - "#{:x}{:x}{:x}{:x}{:x}{:x}", - red >> 4, - red & 0xF, - green >> 4, - green & 0xF, - blue >> 4, - blue & 0xF) + write!( + dest, + "#{:x}{:x}{:x}{:x}{:x}{:x}", + red >> 4, + red & 0xF, + green >> 4, + green & 0xF, + blue >> 4, + blue & 0xF + ) } else { - write!(dest, "rgba({}, {}, {}, {})", red, green, blue, color.alpha_f32()) + write!( + dest, + "rgba({}, {}, {}, {})", + red, + green, + blue, + color.alpha_f32() + ) } } -- cgit v1.2.3 From a3392610c3414a86a2294073bdc59c78c237bfda Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 2 Oct 2018 13:25:45 +0200 Subject: Make HTMLCanvasElement::get_size return a Size2D The changes keep trickling down. --- components/script/dom/canvasrenderingcontext2d.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index e3ca01c311e..2b364c3702d 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -128,7 +128,7 @@ impl CanvasRenderingContext2D { canvas: Option<&HTMLCanvasElement>, image_cache: Arc, base_url: ServoUrl, - size: Size2D, + size: Size2D, ) -> CanvasRenderingContext2D { debug!("Creating new canvas rendering context."); let (sender, receiver) = @@ -157,7 +157,7 @@ impl CanvasRenderingContext2D { pub fn new( global: &GlobalScope, canvas: &HTMLCanvasElement, - size: Size2D, + size: Size2D, ) -> DomRoot { let window = window_from_node(canvas); let image_cache = window.image_cache(); @@ -173,7 +173,7 @@ impl CanvasRenderingContext2D { } // https://html.spec.whatwg.org/multipage/#concept-canvas-set-bitmap-dimensions - pub fn set_bitmap_dimensions(&self, size: Size2D) { + pub fn set_bitmap_dimensions(&self, size: Size2D) { self.reset_to_initial_state(); self.ipc_renderer .send(CanvasMsg::Recreate(size, self.get_canvas_id())) @@ -456,7 +456,7 @@ impl CanvasRenderingContext2D { Ok(()) } - fn fetch_image_data(&self, url: ServoUrl) -> Option<(Vec, Size2D)> { + fn fetch_image_data(&self, url: ServoUrl) -> Option<(Vec, Size2D)> { let img = match self.request_image_from_cache(url) { ImageResponse::Loaded(img, _) => img, ImageResponse::PlaceholderLoaded(_, _) | @@ -466,7 +466,7 @@ impl CanvasRenderingContext2D { }, }; - let image_size = Size2D::new(img.width as i32, img.height as i32); + let image_size = Size2D::new(img.width, img.height); let image_data = match img.format { PixelFormat::BGRA8 => img.bytes.to_vec(), PixelFormat::K8 => panic!("K8 color type not supported"), -- cgit v1.2.3 From 62ea3c093a48362578b1f49d5a65270702015839 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Wed, 3 Oct 2018 12:11:28 +0200 Subject: Move canvas.putImageData checks to the DOM side --- components/script/dom/canvasrenderingcontext2d.rs | 71 +++++++++++++++++++---- 1 file changed, 60 insertions(+), 11 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 2b364c3702d..3482c3d925a 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -1214,19 +1214,68 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { dirty_width: Finite, dirty_height: Finite, ) { - let data = imagedata.get_data_array(); - let offset = Vector2D::new(*dx, *dy); - let image_data_size = Size2D::new(imagedata.Width() as f64, imagedata.Height() as f64); + let imagedata_size = Size2D::new(imagedata.Width() as f64, imagedata.Height() as f64); + if imagedata_size.width <= 0. || imagedata_size.height <= 0. { + return; + } - let dirty_rect = Rect::new( - Point2D::new(*dirty_x, *dirty_y), - Size2D::new(*dirty_width, *dirty_height), - ); + let mut dirty_x = *dirty_x; + let mut dirty_y = *dirty_y; + let mut dirty_width = *dirty_width; + let mut dirty_height = *dirty_height; + + // Step 1. + // Done later. + + // Step 2. + // TODO: throw InvalidState if buffer is detached. + + // Step 3. + if dirty_width < 0. { + dirty_x += dirty_width; + dirty_width = -dirty_width; + } + if dirty_height < 0. { + dirty_y += dirty_height; + dirty_height = -dirty_height; + } + + // Step 4. + if dirty_x < 0. { + dirty_width += dirty_x; + dirty_x = 0.; + } + if dirty_y < 0. { + dirty_height += dirty_y; + dirty_y = 0.; + } + + // Step 5. + if dirty_x + dirty_width > imagedata_size.width { + dirty_width = imagedata_size.width - dirty_x; + } + if dirty_y + dirty_height > imagedata_size.height { + dirty_height = imagedata_size.height - dirty_y; + } + + // Step 6. + if dirty_width <= 0. || dirty_height <= 0. { + return; + } + + // FIXME(nox): There is no need to make a Vec of all the pixels + // if we didn't want to put the entire image. + let buffer = imagedata.get_data_array(); + + // Step 7. self.send_canvas_2d_msg(Canvas2dMsg::PutImageData( - data.into(), - offset, - image_data_size, - dirty_rect, + buffer.into(), + Vector2D::new(*dx, *dy), + imagedata_size, + Rect::new( + Point2D::new(dirty_x, dirty_y), + Size2D::new(dirty_width, dirty_height), + ), )); self.mark_as_dirty(); } -- cgit v1.2.3 From 3d910feb3a59ced307b5152b2f3b74c7725322c0 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 4 Oct 2018 12:11:39 +0200 Subject: Align canvas.putImageData with spec The arguments are supposed to be long values, not floats. --- components/script/dom/canvasrenderingcontext2d.rs | 49 +++++++++-------------- 1 file changed, 18 insertions(+), 31 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 3482c3d925a..31298ccb648 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -1191,39 +1191,26 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata - fn PutImageData(&self, imagedata: &ImageData, dx: Finite, dy: Finite) { - self.PutImageData_( - imagedata, - dx, - dy, - Finite::wrap(0f64), - Finite::wrap(0f64), - Finite::wrap(imagedata.Width() as f64), - Finite::wrap(imagedata.Height() as f64), - ) + fn PutImageData(&self, imagedata: &ImageData, dx: i32, dy: i32) { + self.PutImageData_(imagedata, dx, dy, 0, 0, imagedata.Width() as i32, imagedata.Height() as i32) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata fn PutImageData_( &self, imagedata: &ImageData, - dx: Finite, - dy: Finite, - dirty_x: Finite, - dirty_y: Finite, - dirty_width: Finite, - dirty_height: Finite, + dx: i32, + dy: i32, + mut dirty_x: i32, + mut dirty_y: i32, + mut dirty_width: i32, + mut dirty_height: i32, ) { - let imagedata_size = Size2D::new(imagedata.Width() as f64, imagedata.Height() as f64); - if imagedata_size.width <= 0. || imagedata_size.height <= 0. { + let imagedata_size = Size2D::new(imagedata.Width() as i32, imagedata.Height() as i32); + if imagedata_size.width <= 0 || imagedata_size.height <= 0 { return; } - let mut dirty_x = *dirty_x; - let mut dirty_y = *dirty_y; - let mut dirty_width = *dirty_width; - let mut dirty_height = *dirty_height; - // Step 1. // Done later. @@ -1231,23 +1218,23 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // TODO: throw InvalidState if buffer is detached. // Step 3. - if dirty_width < 0. { + if dirty_width < 0 { dirty_x += dirty_width; dirty_width = -dirty_width; } - if dirty_height < 0. { + if dirty_height < 0 { dirty_y += dirty_height; dirty_height = -dirty_height; } // Step 4. - if dirty_x < 0. { + if dirty_x < 0 { dirty_width += dirty_x; - dirty_x = 0.; + dirty_x = 0; } - if dirty_y < 0. { + if dirty_y < 0 { dirty_height += dirty_y; - dirty_y = 0.; + dirty_y = 0; } // Step 5. @@ -1259,7 +1246,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } // Step 6. - if dirty_width <= 0. || dirty_height <= 0. { + if dirty_width <= 0 || dirty_height <= 0 { return; } @@ -1270,7 +1257,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // Step 7. self.send_canvas_2d_msg(Canvas2dMsg::PutImageData( buffer.into(), - Vector2D::new(*dx, *dy), + Vector2D::new(dx, dy), imagedata_size, Rect::new( Point2D::new(dirty_x, dirty_y), -- cgit v1.2.3 From 82c7d71811c072a29fb73df49664490dcba2d82f Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 4 Oct 2018 16:29:45 +0200 Subject: Improve gl.putImageData This commit should allow us to send smaller blobs to the canvas thread, I made it into its own commit just to try=wpt. --- components/script/dom/canvasrenderingcontext2d.rs | 30 +++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 31298ccb648..9adbaa3a734 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -31,7 +31,7 @@ use dom::htmlcanvaselement::{CanvasContext, HTMLCanvasElement}; use dom::imagedata::ImageData; use dom::node::{Node, NodeDamage, window_from_node}; use dom_struct::dom_struct; -use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D, vec2}; +use euclid::{Transform2D, Point2D, Rect, Size2D, vec2}; use ipc_channel::ipc::{self, IpcSender}; use net_traits::image::base::PixelFormat; use net_traits::image_cache::CanRequestImages; @@ -1206,6 +1206,9 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { mut dirty_width: i32, mut dirty_height: i32, ) { + // FIXME(nox): There are many arithmetic operations here that can + // overflow or underflow, this should probably be audited. + let imagedata_size = Size2D::new(imagedata.Width() as i32, imagedata.Height() as i32); if imagedata_size.width <= 0 || imagedata_size.height <= 0 { return; @@ -1227,6 +1230,21 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { dirty_height = -dirty_height; } + // Ignore any pixel that would be drawn before the beginning of the + // canvas surface. + let mut dest_x = dx + dirty_x; + let mut dest_y = dy + dirty_y; + if dest_x < 0 { + dirty_x -= dest_x; + dirty_width += dest_x; + dest_x = 0; + } + if dest_y < 0 { + dirty_y -= dest_y; + dirty_height += dest_y; + dest_y = 0; + } + // Step 4. if dirty_x < 0 { dirty_width += dirty_x; @@ -1245,6 +1263,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { dirty_height = imagedata_size.height - dirty_y; } + // We take care of ignoring any pixel that would be drawn after the end + // of the canvas surface. + let canvas_size = self.canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()).to_i32(); + let origin = Point2D::new(dest_x, dest_y); + let drawable_size = (origin - canvas_size.to_vector().to_point()).to_size().abs(); + dirty_width = dirty_width.min(drawable_size.width); + dirty_height = dirty_height.min(drawable_size.height); + // Step 6. if dirty_width <= 0 || dirty_height <= 0 { return; @@ -1257,7 +1283,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // Step 7. self.send_canvas_2d_msg(Canvas2dMsg::PutImageData( buffer.into(), - Vector2D::new(dx, dy), + origin.to_vector(), imagedata_size, Rect::new( Point2D::new(dirty_x, dirty_y), -- cgit v1.2.3 From 784fbb2bc17d311fe3322cc48d2dca8a902161ca Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 6 Oct 2018 00:40:48 +0200 Subject: Merge some byte swap/premultiply functions in their own crate --- components/script/dom/canvasrenderingcontext2d.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 9adbaa3a734..15b6eb9560f 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -5,7 +5,7 @@ use canvas_traits::canvas::{Canvas2dMsg, CanvasMsg, CanvasId}; use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; use canvas_traits::canvas::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; -use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply}; +use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle}; use cssparser::{Parser, ParserInput, RGBA}; use cssparser::Color as CSSColor; use dom::bindings::cell::DomRefCell; @@ -41,6 +41,7 @@ use net_traits::image_cache::ImageResponse; use net_traits::image_cache::ImageState; use net_traits::image_cache::UsePlaceholder; use num_traits::ToPrimitive; +use pixels; use profile_traits::ipc as profiled_ipc; use script_traits::ScriptMsg; use servo_url::ServoUrl; @@ -410,7 +411,7 @@ impl CanvasRenderingContext2D { Some((mut data, size)) => { // Pixels come from cache in BGRA order and drawImage expects RGBA so we // have to swap the color values - byte_swap_and_premultiply(&mut data); + pixels::byte_swap_and_premultiply_inplace(&mut data); let size = Size2D::new(size.width as f64, size.height as f64); (data, size) }, -- cgit v1.2.3 From 19f40cdf0ba09a767e65ee3f0bd37622cc341bde Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 6 Oct 2018 01:10:34 +0200 Subject: Introduce ImageData::get_rect We use that to send only the pixels that will be actually drawn to the canvas thread in CanvasRenderingContext2d::PutImageData. We also make the canvas thread byte swap and premultiply colours in-place. --- components/script/dom/canvasrenderingcontext2d.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 15b6eb9560f..1f3b9ab92cd 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -1277,19 +1277,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { return; } - // FIXME(nox): There is no need to make a Vec of all the pixels - // if we didn't want to put the entire image. - let buffer = imagedata.get_data_array(); + let dirty_size = Size2D::new(dirty_width, dirty_height); + let dirty_rect = Rect::new(Point2D::new(dirty_x, dirty_y), dirty_size); // Step 7. self.send_canvas_2d_msg(Canvas2dMsg::PutImageData( - buffer.into(), + imagedata.get_rect(dirty_rect.try_cast().unwrap()).into(), origin.to_vector(), - imagedata_size, - Rect::new( - Point2D::new(dirty_x, dirty_y), - Size2D::new(dirty_width, dirty_height), - ), + dirty_size, )); self.mark_as_dirty(); } -- cgit v1.2.3 From 75e6f5dfaabd8ff01916b929edaceedf47fe6309 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 6 Oct 2018 02:58:45 +0200 Subject: Avoid copying pixels in ctx.putImageData sometimes --- components/script/dom/canvasrenderingcontext2d.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 1f3b9ab92cd..69c7d4038cd 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -1197,6 +1197,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata + #[allow(unsafe_code)] fn PutImageData_( &self, imagedata: &ImageData, @@ -1281,11 +1282,13 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { let dirty_rect = Rect::new(Point2D::new(dirty_x, dirty_y), dirty_size); // Step 7. + let (sender, receiver) = ipc::bytes_channel().unwrap(); self.send_canvas_2d_msg(Canvas2dMsg::PutImageData( - imagedata.get_rect(dirty_rect.try_cast().unwrap()).into(), + receiver, origin.to_vector(), dirty_size, )); + sender.send(unsafe { &imagedata.get_rect(dirty_rect.try_cast().unwrap()) }).unwrap(); self.mark_as_dirty(); } -- cgit v1.2.3 From 241dba064ded04b3b2f97b098db637ce58cf9e19 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 6 Oct 2018 11:41:48 +0200 Subject: Align ctx.createImageData and ctx.getImageData with the spec --- components/script/dom/canvasrenderingcontext2d.rs | 77 ++++++++++------------- 1 file changed, 33 insertions(+), 44 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 69c7d4038cd..633fbbc3f14 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -40,12 +40,11 @@ use net_traits::image_cache::ImageOrMetadataAvailable; use net_traits::image_cache::ImageResponse; use net_traits::image_cache::ImageState; use net_traits::image_cache::UsePlaceholder; -use num_traits::ToPrimitive; use pixels; use profile_traits::ipc as profiled_ipc; use script_traits::ScriptMsg; use servo_url::ServoUrl; -use std::{cmp, fmt, mem}; +use std::{fmt, mem}; use std::cell::Cell; use std::str::FromStr; use std::sync::Arc; @@ -1118,14 +1117,11 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata - fn CreateImageData(&self, sw: Finite, sh: Finite) -> Fallible> { - if *sw == 0.0 || *sh == 0.0 { + fn CreateImageData(&self, sw: i32, sh: i32) -> Fallible> { + if sw == 0 || sh == 0 { return Err(Error::IndexSize); } - - let sw = cmp::max(1, sw.abs().to_u32().unwrap()); - let sh = cmp::max(1, sh.abs().to_u32().unwrap()); - ImageData::new(&self.global(), sw, sh, None) + ImageData::new(&self.global(), sw.abs() as u32, sh.abs() as u32, None) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata @@ -1136,59 +1132,49 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata fn GetImageData( &self, - sx: Finite, - sy: Finite, - sw: Finite, - sh: Finite, + mut sx: i32, + mut sy: i32, + mut sw: i32, + mut sh: i32, ) -> Fallible> { - if !self.origin_is_clean() { - return Err(Error::Security); + if sw == 0 || sh == 0 { + return Err(Error::IndexSize); } - let mut sx = *sx; - let mut sy = *sy; - let mut sw = *sw; - let mut sh = *sh; - - if sw == 0.0 || sh == 0.0 { - return Err(Error::IndexSize); + if !self.origin_is_clean() { + return Err(Error::Security); } - if sw < 0.0 { + if sw < 0 { sw = -sw; sx -= sw; } - if sh < 0.0 { + if sh < 0 { sh = -sh; sy -= sh; } - let sh = cmp::max(1, sh.to_u32().unwrap()); - let sw = cmp::max(1, sw.to_u32().unwrap()); - let (sender, receiver) = ipc::bytes_channel().unwrap(); - let dest_rect = Rect::new( - Point2D::new(sx.to_i32().unwrap(), sy.to_i32().unwrap()), - Size2D::new(sw as i32, sh as i32), - ); - let canvas_size = self - .canvas - .as_ref() - .map(|c| c.get_size()) - .unwrap_or(Size2D::zero()); - let canvas_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64); - self.send_canvas_2d_msg(Canvas2dMsg::GetImageData(dest_rect, canvas_size, sender)); + let dest_rect = Rect::new(Point2D::new(sx, sy), Size2D::new(sw, sh)); + // FIXME(nox): This is probably wrong when this is a context for an + // offscreen canvas. + let canvas_size = self.canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()); + self.send_canvas_2d_msg(Canvas2dMsg::GetImageData( + dest_rect, + canvas_size.to_i32(), + sender, + )); let mut data = receiver.recv().unwrap(); // Byte swap and unmultiply alpha. for chunk in data.chunks_mut(4) { - let (b, g, r, a) = (chunk[0], chunk[1], chunk[2], chunk[3]); - chunk[0] = UNPREMULTIPLY_TABLE[256 * (a as usize) + r as usize]; - chunk[1] = UNPREMULTIPLY_TABLE[256 * (a as usize) + g as usize]; - chunk[2] = UNPREMULTIPLY_TABLE[256 * (a as usize) + b as usize]; + let b = chunk[0]; + chunk[0] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + chunk[2] as usize]; + chunk[1] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + chunk[1] as usize]; + chunk[2] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + b as usize]; } - ImageData::new(&self.global(), sw, sh, Some(data.to_vec())) + ImageData::new(&self.global(), sw as u32, sh as u32, Some(data.to_vec())) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata @@ -1265,11 +1251,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { dirty_height = imagedata_size.height - dirty_y; } - // We take care of ignoring any pixel that would be drawn after the end - // of the canvas surface. + // FIXME(nox): This is probably wrong when this is a context for an + // offscreen canvas. let canvas_size = self.canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()).to_i32(); let origin = Point2D::new(dest_x, dest_y); let drawable_size = (origin - canvas_size.to_vector().to_point()).to_size().abs(); + + // We take care of ignoring any pixel that would be drawn after the end + // of the canvas surface. dirty_width = dirty_width.min(drawable_size.width); dirty_height = dirty_height.min(drawable_size.height); -- cgit v1.2.3 From e62dbabb46b8c5b6a5fc3dc6188976cbf2039d75 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 7 Oct 2018 02:52:06 +0200 Subject: Handle some transparent black cases in ctx.getImageData --- components/script/dom/canvasrenderingcontext2d.rs | 51 +++++++++++++++++------ 1 file changed, 38 insertions(+), 13 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 633fbbc3f14..f98da6f9a5e 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -1137,6 +1137,9 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { mut sw: i32, mut sh: i32, ) -> Fallible> { + // FIXME(nox): There are many arithmetic operations here that can + // overflow or underflow, this should probably be audited. + if sw == 0 || sh == 0 { return Err(Error::IndexSize); } @@ -1154,27 +1157,48 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { sy -= sh; } + let data_width = sw; + let data_height = sh; + + if sx < 0 { + sw += sx; + sx = 0; + } + if sy < 0 { + sh += sy; + sy = 0; + } + + if sw <= 0 || sh <= 0 { + // All the pixels are before the start of the canvas surface. + return ImageData::new(&self.global(), data_width as u32, data_height as u32, None); + } + let (sender, receiver) = ipc::bytes_channel().unwrap(); - let dest_rect = Rect::new(Point2D::new(sx, sy), Size2D::new(sw, sh)); + let src_rect = Rect::new(Point2D::new(sx, sy), Size2D::new(sw, sh)); // FIXME(nox): This is probably wrong when this is a context for an // offscreen canvas. - let canvas_size = self.canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()); - self.send_canvas_2d_msg(Canvas2dMsg::GetImageData( - dest_rect, - canvas_size.to_i32(), - sender, - )); - let mut data = receiver.recv().unwrap(); - - // Byte swap and unmultiply alpha. - for chunk in data.chunks_mut(4) { + let canvas_size = self.canvas + .as_ref() + .map_or(Size2D::zero(), |c| c.get_size()) + .try_cast().unwrap(); + let canvas_rect = Rect::from_size(canvas_size); + let read_rect = match src_rect.intersection(&canvas_rect) { + Some(rect) if !rect.is_empty() => rect, + _ => { + // All the pixels are past the end of the canvas surface. + return ImageData::new(&self.global(), data_width as u32, data_height as u32, None); + } + }; + self.send_canvas_2d_msg(Canvas2dMsg::GetImageData(read_rect, canvas_size, sender)); + let mut pixels = receiver.recv().unwrap(); + for chunk in pixels.chunks_mut(4) { let b = chunk[0]; chunk[0] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + chunk[2] as usize]; chunk[1] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + chunk[1] as usize]; chunk[2] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + b as usize]; } - - ImageData::new(&self.global(), sw as u32, sh as u32, Some(data.to_vec())) + ImageData::new(&self.global(), sw as u32, sh as u32, Some(pixels.to_vec())) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata @@ -1197,6 +1221,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // FIXME(nox): There are many arithmetic operations here that can // overflow or underflow, this should probably be audited. + let imagedata_size = Size2D::new(imagedata.Width() as i32, imagedata.Height() as i32); if imagedata_size.width <= 0 || imagedata_size.height <= 0 { return; -- cgit v1.2.3 From 77c28bdfc9050c645eaae02b0f11636fc73a11fb Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 8 Oct 2018 11:09:38 +0200 Subject: Abstract some stuff common to ctx.getImageData and ctx.putImageData --- components/script/dom/canvasrenderingcontext2d.rs | 199 +++++++++------------- 1 file changed, 80 insertions(+), 119 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index f98da6f9a5e..5aa1518932d 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -1130,13 +1130,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } // https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata - fn GetImageData( - &self, - mut sx: i32, - mut sy: i32, - mut sw: i32, - mut sh: i32, - ) -> Fallible> { + fn GetImageData(&self, sx: i32, sy: i32, sw: i32, sh: i32) -> Fallible> { // FIXME(nox): There are many arithmetic operations here that can // overflow or underflow, this should probably be audited. @@ -1148,57 +1142,30 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { return Err(Error::Security); } - if sw < 0 { - sw = -sw; - sx -= sw; - } - if sh < 0 { - sh = -sh; - sy -= sh; - } - - let data_width = sw; - let data_height = sh; - - if sx < 0 { - sw += sx; - sx = 0; - } - if sy < 0 { - sh += sy; - sy = 0; - } - - if sw <= 0 || sh <= 0 { - // All the pixels are before the start of the canvas surface. - return ImageData::new(&self.global(), data_width as u32, data_height as u32, None); - } - - let (sender, receiver) = ipc::bytes_channel().unwrap(); - let src_rect = Rect::new(Point2D::new(sx, sy), Size2D::new(sw, sh)); + let (origin, size) = adjust_size_sign(Point2D::new(sx, sy), Size2D::new(sw, sh)); // FIXME(nox): This is probably wrong when this is a context for an // offscreen canvas. - let canvas_size = self.canvas - .as_ref() - .map_or(Size2D::zero(), |c| c.get_size()) - .try_cast().unwrap(); - let canvas_rect = Rect::from_size(canvas_size); - let read_rect = match src_rect.intersection(&canvas_rect) { - Some(rect) if !rect.is_empty() => rect, - _ => { - // All the pixels are past the end of the canvas surface. - return ImageData::new(&self.global(), data_width as u32, data_height as u32, None); - } + let canvas_size = self.canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()); + let read_rect = match clip(origin, size, canvas_size) { + Some(rect) => rect, + None => { + // All the pixels are outside the canvas surface. + return ImageData::new(&self.global(), size.width, size.height, None); + }, }; + + let (sender, receiver) = ipc::bytes_channel().unwrap(); self.send_canvas_2d_msg(Canvas2dMsg::GetImageData(read_rect, canvas_size, sender)); - let mut pixels = receiver.recv().unwrap(); + let mut pixels = receiver.recv().unwrap().to_vec(); + for chunk in pixels.chunks_mut(4) { let b = chunk[0]; chunk[0] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + chunk[2] as usize]; chunk[1] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + chunk[1] as usize]; chunk[2] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + b as usize]; } - ImageData::new(&self.global(), sw as u32, sh as u32, Some(pixels.to_vec())) + + ImageData::new(&self.global(), size.width, size.height, Some(pixels)) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata @@ -1213,17 +1180,17 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { imagedata: &ImageData, dx: i32, dy: i32, - mut dirty_x: i32, - mut dirty_y: i32, - mut dirty_width: i32, - mut dirty_height: i32, + dirty_x: i32, + dirty_y: i32, + dirty_width: i32, + dirty_height: i32, ) { // FIXME(nox): There are many arithmetic operations here that can // overflow or underflow, this should probably be audited. - let imagedata_size = Size2D::new(imagedata.Width() as i32, imagedata.Height() as i32); - if imagedata_size.width <= 0 || imagedata_size.height <= 0 { + let imagedata_size = Size2D::new(imagedata.Width(), imagedata.Height()); + if imagedata_size.area() == 0 { return; } @@ -1233,76 +1200,37 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // Step 2. // TODO: throw InvalidState if buffer is detached. - // Step 3. - if dirty_width < 0 { - dirty_x += dirty_width; - dirty_width = -dirty_width; - } - if dirty_height < 0 { - dirty_y += dirty_height; - dirty_height = -dirty_height; - } - - // Ignore any pixel that would be drawn before the beginning of the - // canvas surface. - let mut dest_x = dx + dirty_x; - let mut dest_y = dy + dirty_y; - if dest_x < 0 { - dirty_x -= dest_x; - dirty_width += dest_x; - dest_x = 0; - } - if dest_y < 0 { - dirty_y -= dest_y; - dirty_height += dest_y; - dest_y = 0; - } - - // Step 4. - if dirty_x < 0 { - dirty_width += dirty_x; - dirty_x = 0; - } - if dirty_y < 0 { - dirty_height += dirty_y; - dirty_y = 0; - } - - // Step 5. - if dirty_x + dirty_width > imagedata_size.width { - dirty_width = imagedata_size.width - dirty_x; - } - if dirty_y + dirty_height > imagedata_size.height { - dirty_height = imagedata_size.height - dirty_y; - } - // FIXME(nox): This is probably wrong when this is a context for an // offscreen canvas. - let canvas_size = self.canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()).to_i32(); - let origin = Point2D::new(dest_x, dest_y); - let drawable_size = (origin - canvas_size.to_vector().to_point()).to_size().abs(); - - // We take care of ignoring any pixel that would be drawn after the end - // of the canvas surface. - dirty_width = dirty_width.min(drawable_size.width); - dirty_height = dirty_height.min(drawable_size.height); - - // Step 6. - if dirty_width <= 0 || dirty_height <= 0 { - return; - } + let canvas_size = self.canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()); - let dirty_size = Size2D::new(dirty_width, dirty_height); - let dirty_rect = Rect::new(Point2D::new(dirty_x, dirty_y), dirty_size); + // Steps 3-6. + let (src_origin, src_size) = adjust_size_sign( + Point2D::new(dirty_x, dirty_y), + Size2D::new(dirty_width, dirty_height), + ); + let src_rect = match clip(src_origin, src_size, imagedata_size) { + Some(rect) => rect, + None => return, + }; + let (dst_origin, _) = adjust_size_sign( + Point2D::new(dirty_x.saturating_add(dx), dirty_y.saturating_add(dy)), + Size2D::new(dirty_width, dirty_height), + ); + // By clipping to the canvas surface, we avoid sending any pixel + // that would fall outside it. + let dst_rect = match clip(dst_origin, src_rect.size, canvas_size) { + Some(rect) => rect, + None => return, + }; // Step 7. let (sender, receiver) = ipc::bytes_channel().unwrap(); - self.send_canvas_2d_msg(Canvas2dMsg::PutImageData( - receiver, - origin.to_vector(), - dirty_size, - )); - sender.send(unsafe { &imagedata.get_rect(dirty_rect.try_cast().unwrap()) }).unwrap(); + let pixels = unsafe { + &imagedata.get_rect(Rect::new(src_rect.origin, dst_rect.size)) + }; + self.send_canvas_2d_msg(Canvas2dMsg::PutImageData(dst_rect, receiver)); + sender.send(pixels).unwrap(); self.mark_as_dirty(); } @@ -1552,7 +1480,7 @@ fn is_rect_valid(rect: Rect) -> bool { rect.size.width > 0.0 && rect.size.height > 0.0 } -// https://html.spec.whatwg.org/multipage/#serialisation-of-a-colour +// https://html.spec.whatwg.org/multipage/#serialisation-of-a-color fn serialize(color: &RGBA, dest: &mut W) -> fmt::Result where W: fmt::Write, @@ -1583,3 +1511,36 @@ where ) } } + +fn adjust_size_sign( + mut origin: Point2D, + mut size: Size2D, +) -> (Point2D, Size2D) { + if size.width < 0 { + size.width = -size.width; + origin.x = origin.x.saturating_sub(size.width); + } + if size.height < 0 { + size.height = -size.height; + origin.y = origin.y.saturating_sub(size.height); + } + (origin, size.to_u32()) +} + +fn clip( + mut origin: Point2D, + mut size: Size2D, + surface: Size2D, +) -> Option> { + if origin.x < 0 { + size.width = size.width.saturating_sub(-origin.x as u32); + origin.x = 0; + } + if origin.y < 0 { + size.height = size.height.saturating_sub(-origin.y as u32); + origin.y = 0; + } + Rect::new(origin.to_u32(), size) + .intersection(&Rect::from_size(surface)) + .filter(|rect| !rect.is_empty()) +} -- cgit v1.2.3 From 551c405b0fc03350109b560f75169edf43284297 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 8 Oct 2018 12:19:10 +0200 Subject: Avoid ctx.getImageData in canvas.toDataURL --- components/script/dom/canvasrenderingcontext2d.rs | 35 +++++++++++++++-------- 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 5aa1518932d..2617f9e7ed5 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -575,6 +575,28 @@ impl CanvasRenderingContext2D { fn set_origin_unclean(&self) { self.origin_clean.set(false) } + + pub fn get_rect(&self, rect: Rect) -> Vec { + assert!(self.origin_is_clean()); + + // FIXME(nox): This is probably wrong when this is a context for an + // offscreen canvas. + let canvas_size = self.canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()); + assert!(Rect::from_size(canvas_size).contains_rect(&rect)); + + let (sender, receiver) = ipc::bytes_channel().unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::GetImageData(rect, canvas_size, sender)); + let mut pixels = receiver.recv().unwrap().to_vec(); + + for chunk in pixels.chunks_mut(4) { + let b = chunk[0]; + chunk[0] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + chunk[2] as usize]; + chunk[1] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + chunk[1] as usize]; + chunk[2] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + b as usize]; + } + + pixels + } } pub trait LayoutCanvasRenderingContext2DHelpers { @@ -1154,18 +1176,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { }, }; - let (sender, receiver) = ipc::bytes_channel().unwrap(); - self.send_canvas_2d_msg(Canvas2dMsg::GetImageData(read_rect, canvas_size, sender)); - let mut pixels = receiver.recv().unwrap().to_vec(); - - for chunk in pixels.chunks_mut(4) { - let b = chunk[0]; - chunk[0] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + chunk[2] as usize]; - chunk[1] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + chunk[1] as usize]; - chunk[2] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + b as usize]; - } - - ImageData::new(&self.global(), size.width, size.height, Some(pixels)) + ImageData::new(&self.global(), size.width, size.height, Some(self.get_rect(read_rect))) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata -- cgit v1.2.3 From 6c469b90b1ae34bddcb7da19eacfa6ad4467cf35 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 8 Oct 2018 13:49:58 +0200 Subject: Share some code between 2D canvas and WebGL --- components/script/dom/canvasrenderingcontext2d.rs | 24 +++-------------------- 1 file changed, 3 insertions(+), 21 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 2617f9e7ed5..dacabcccce5 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -1168,7 +1168,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // FIXME(nox): This is probably wrong when this is a context for an // offscreen canvas. let canvas_size = self.canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()); - let read_rect = match clip(origin, size, canvas_size) { + let read_rect = match pixels::clip(origin, size, canvas_size) { Some(rect) => rect, None => { // All the pixels are outside the canvas surface. @@ -1220,7 +1220,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { Point2D::new(dirty_x, dirty_y), Size2D::new(dirty_width, dirty_height), ); - let src_rect = match clip(src_origin, src_size, imagedata_size) { + let src_rect = match pixels::clip(src_origin, src_size, imagedata_size) { Some(rect) => rect, None => return, }; @@ -1230,7 +1230,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { ); // By clipping to the canvas surface, we avoid sending any pixel // that would fall outside it. - let dst_rect = match clip(dst_origin, src_rect.size, canvas_size) { + let dst_rect = match pixels::clip(dst_origin, src_rect.size, canvas_size) { Some(rect) => rect, None => return, }; @@ -1537,21 +1537,3 @@ fn adjust_size_sign( } (origin, size.to_u32()) } - -fn clip( - mut origin: Point2D, - mut size: Size2D, - surface: Size2D, -) -> Option> { - if origin.x < 0 { - size.width = size.width.saturating_sub(-origin.x as u32); - origin.x = 0; - } - if origin.y < 0 { - size.height = size.height.saturating_sub(-origin.y as u32); - origin.y = 0; - } - Rect::new(origin.to_u32(), size) - .intersection(&Rect::from_size(surface)) - .filter(|rect| !rect.is_empty()) -} -- cgit v1.2.3 From bb2101f540f542b51c431d694b09fc1da5a0fac3 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 11 Oct 2018 15:46:42 +0200 Subject: Simplify ctx.drawImage a bit There is no need to swap between RGBA and BGRA twice. --- components/script/dom/canvasrenderingcontext2d.rs | 33 ++++------------------- 1 file changed, 5 insertions(+), 28 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index dacabcccce5..f88ae42e452 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -403,39 +403,16 @@ impl CanvasRenderingContext2D { dh: Option, ) -> ErrorResult { debug!("Fetching image {}.", url); - // https://html.spec.whatwg.org/multipage/#img-error - // If the image argument is an HTMLImageElement object that is in the broken state, - // then throw an InvalidStateError exception - let (image_data, image_size) = match self.fetch_image_data(url) { - Some((mut data, size)) => { - // Pixels come from cache in BGRA order and drawImage expects RGBA so we - // have to swap the color values - pixels::byte_swap_and_premultiply_inplace(&mut data); - let size = Size2D::new(size.width as f64, size.height as f64); - (data, size) - }, - None => return Err(Error::InvalidState), - }; + let (mut image_data, image_size) = + self.fetch_image_data(url).ok_or(Error::InvalidState)?; + pixels::premultiply_inplace(&mut image_data); + let image_size = image_size.to_f64(); + let dw = dw.unwrap_or(image_size.width); let dh = dh.unwrap_or(image_size.height); let sw = sw.unwrap_or(image_size.width); let sh = sh.unwrap_or(image_size.height); - self.draw_image_data(image_data, image_size, sx, sy, sw, sh, dx, dy, dw, dh) - } - fn draw_image_data( - &self, - image_data: Vec, - image_size: Size2D, - sx: f64, - sy: f64, - sw: f64, - sh: f64, - dx: f64, - dy: f64, - dw: f64, - dh: f64, - ) -> ErrorResult { // Establish the source and destination rectangles let (source_rect, dest_rect) = self.adjust_source_dest_rects(image_size, sx, sy, sw, sh, dx, dy, dw, dh); -- cgit v1.2.3 From 45f7199eee82c66637ec68287eafa40a651001c4 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 1 Nov 2018 23:45:06 +0100 Subject: `cargo fix --edition` --- components/script/dom/canvasrenderingcontext2d.rs | 46 +++++++++++------------ 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index f88ae42e452..99cb8399557 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -8,28 +8,28 @@ use canvas_traits::canvas::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle}; use cssparser::{Parser, ParserInput, RGBA}; use cssparser::Color as CSSColor; -use dom::bindings::cell::DomRefCell; -use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding; -use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasFillRule; -use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasImageSource; -use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineCap; -use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineJoin; -use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods; -use dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods; -use dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern; -use dom::bindings::error::{Error, ErrorResult, Fallible}; -use dom::bindings::inheritance::Castable; -use dom::bindings::num::Finite; -use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; -use dom::bindings::root::{Dom, DomRoot, LayoutDom}; -use dom::bindings::str::DOMString; -use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle}; -use dom::canvaspattern::CanvasPattern; -use dom::element::Element; -use dom::globalscope::GlobalScope; -use dom::htmlcanvaselement::{CanvasContext, HTMLCanvasElement}; -use dom::imagedata::ImageData; -use dom::node::{Node, NodeDamage, window_from_node}; +use crate::dom::bindings::cell::DomRefCell; +use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding; +use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasFillRule; +use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasImageSource; +use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineCap; +use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineJoin; +use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods; +use crate::dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods; +use crate::dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern; +use crate::dom::bindings::error::{Error, ErrorResult, Fallible}; +use crate::dom::bindings::inheritance::Castable; +use crate::dom::bindings::num::Finite; +use crate::dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; +use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom}; +use crate::dom::bindings::str::DOMString; +use crate::dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle}; +use crate::dom::canvaspattern::CanvasPattern; +use crate::dom::element::Element; +use crate::dom::globalscope::GlobalScope; +use crate::dom::htmlcanvaselement::{CanvasContext, HTMLCanvasElement}; +use crate::dom::imagedata::ImageData; +use crate::dom::node::{Node, NodeDamage, window_from_node}; use dom_struct::dom_struct; use euclid::{Transform2D, Point2D, Rect, Size2D, vec2}; use ipc_channel::ipc::{self, IpcSender}; @@ -48,7 +48,7 @@ use std::{fmt, mem}; use std::cell::Cell; use std::str::FromStr; use std::sync::Arc; -use unpremultiplytable::UNPREMULTIPLY_TABLE; +use crate::unpremultiplytable::UNPREMULTIPLY_TABLE; #[must_root] #[derive(Clone, JSTraceable, MallocSizeOf)] -- cgit v1.2.3 From 76e59a46d3aff701b2e8dfbaf047f6d5c3edcced Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 1 Nov 2018 17:23:56 +0100 Subject: Sort `use` statements --- components/script/dom/canvasrenderingcontext2d.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 99cb8399557..817250408d2 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -6,8 +6,6 @@ use canvas_traits::canvas::{Canvas2dMsg, CanvasMsg, CanvasId}; use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; use canvas_traits::canvas::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle}; -use cssparser::{Parser, ParserInput, RGBA}; -use cssparser::Color as CSSColor; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasFillRule; @@ -30,6 +28,9 @@ use crate::dom::globalscope::GlobalScope; use crate::dom::htmlcanvaselement::{CanvasContext, HTMLCanvasElement}; use crate::dom::imagedata::ImageData; use crate::dom::node::{Node, NodeDamage, window_from_node}; +use crate::unpremultiplytable::UNPREMULTIPLY_TABLE; +use cssparser::{Parser, ParserInput, RGBA}; +use cssparser::Color as CSSColor; use dom_struct::dom_struct; use euclid::{Transform2D, Point2D, Rect, Size2D, vec2}; use ipc_channel::ipc::{self, IpcSender}; @@ -48,7 +49,6 @@ use std::{fmt, mem}; use std::cell::Cell; use std::str::FromStr; use std::sync::Arc; -use crate::unpremultiplytable::UNPREMULTIPLY_TABLE; #[must_root] #[derive(Clone, JSTraceable, MallocSizeOf)] -- cgit v1.2.3 From cb07debcb6f3d3561177ce536c320986720791b7 Mon Sep 17 00:00:00 2001 From: Pyfisch Date: Tue, 6 Nov 2018 13:01:35 +0100 Subject: Format remaining files --- components/script/dom/canvasrenderingcontext2d.rs | 42 ++++++++++++++++------- 1 file changed, 30 insertions(+), 12 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 817250408d2..5ebc2eb98e1 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -266,7 +266,7 @@ impl CanvasRenderingContext2D { CanvasImageSource::HTMLCanvasElement(canvas) => canvas.origin_is_clean(), CanvasImageSource::HTMLImageElement(image) => { image.same_origin(GlobalScope::entry().origin()) - } + }, CanvasImageSource::CSSStyleValue(_) => true, } } @@ -403,8 +403,7 @@ impl CanvasRenderingContext2D { dh: Option, ) -> ErrorResult { debug!("Fetching image {}.", url); - let (mut image_data, image_size) = - self.fetch_image_data(url).ok_or(Error::InvalidState)?; + let (mut image_data, image_size) = self.fetch_image_data(url).ok_or(Error::InvalidState)?; pixels::premultiply_inplace(&mut image_data); let image_size = image_size.to_f64(); @@ -558,7 +557,10 @@ impl CanvasRenderingContext2D { // FIXME(nox): This is probably wrong when this is a context for an // offscreen canvas. - let canvas_size = self.canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()); + let canvas_size = self + .canvas + .as_ref() + .map_or(Size2D::zero(), |c| c.get_size()); assert!(Rect::from_size(canvas_size).contains_rect(&rect)); let (sender, receiver) = ipc::bytes_channel().unwrap(); @@ -1144,7 +1146,10 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { let (origin, size) = adjust_size_sign(Point2D::new(sx, sy), Size2D::new(sw, sh)); // FIXME(nox): This is probably wrong when this is a context for an // offscreen canvas. - let canvas_size = self.canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()); + let canvas_size = self + .canvas + .as_ref() + .map_or(Size2D::zero(), |c| c.get_size()); let read_rect = match pixels::clip(origin, size, canvas_size) { Some(rect) => rect, None => { @@ -1153,12 +1158,25 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { }, }; - ImageData::new(&self.global(), size.width, size.height, Some(self.get_rect(read_rect))) + ImageData::new( + &self.global(), + size.width, + size.height, + Some(self.get_rect(read_rect)), + ) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata fn PutImageData(&self, imagedata: &ImageData, dx: i32, dy: i32) { - self.PutImageData_(imagedata, dx, dy, 0, 0, imagedata.Width() as i32, imagedata.Height() as i32) + self.PutImageData_( + imagedata, + dx, + dy, + 0, + 0, + imagedata.Width() as i32, + imagedata.Height() as i32, + ) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata @@ -1176,7 +1194,6 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // FIXME(nox): There are many arithmetic operations here that can // overflow or underflow, this should probably be audited. - let imagedata_size = Size2D::new(imagedata.Width(), imagedata.Height()); if imagedata_size.area() == 0 { return; @@ -1190,7 +1207,10 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // FIXME(nox): This is probably wrong when this is a context for an // offscreen canvas. - let canvas_size = self.canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()); + let canvas_size = self + .canvas + .as_ref() + .map_or(Size2D::zero(), |c| c.get_size()); // Steps 3-6. let (src_origin, src_size) = adjust_size_sign( @@ -1214,9 +1234,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // Step 7. let (sender, receiver) = ipc::bytes_channel().unwrap(); - let pixels = unsafe { - &imagedata.get_rect(Rect::new(src_rect.origin, dst_rect.size)) - }; + let pixels = unsafe { &imagedata.get_rect(Rect::new(src_rect.origin, dst_rect.size)) }; self.send_canvas_2d_msg(Canvas2dMsg::PutImageData(dst_rect, receiver)); sender.send(pixels).unwrap(); self.mark_as_dirty(); -- cgit v1.2.3 From 9e92eb205a2a12fe0be883e42cb7f82deebc9031 Mon Sep 17 00:00:00 2001 From: Pyfisch Date: Tue, 6 Nov 2018 20:38:02 +0100 Subject: Reorder imports --- components/script/dom/canvasrenderingcontext2d.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 5ebc2eb98e1..1bf2a09b50f 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::canvas::{Canvas2dMsg, CanvasMsg, CanvasId}; +use canvas_traits::canvas::{Canvas2dMsg, CanvasId, CanvasMsg}; use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; use canvas_traits::canvas::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle}; @@ -18,7 +18,7 @@ use crate::dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPat use crate::dom::bindings::error::{Error, ErrorResult, Fallible}; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::num::Finite; -use crate::dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; +use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom}; use crate::dom::bindings::str::DOMString; use crate::dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle}; @@ -27,12 +27,12 @@ use crate::dom::element::Element; use crate::dom::globalscope::GlobalScope; use crate::dom::htmlcanvaselement::{CanvasContext, HTMLCanvasElement}; use crate::dom::imagedata::ImageData; -use crate::dom::node::{Node, NodeDamage, window_from_node}; +use crate::dom::node::{window_from_node, Node, NodeDamage}; use crate::unpremultiplytable::UNPREMULTIPLY_TABLE; -use cssparser::{Parser, ParserInput, RGBA}; use cssparser::Color as CSSColor; +use cssparser::{Parser, ParserInput, RGBA}; use dom_struct::dom_struct; -use euclid::{Transform2D, Point2D, Rect, Size2D, vec2}; +use euclid::{vec2, Point2D, Rect, Size2D, Transform2D}; use ipc_channel::ipc::{self, IpcSender}; use net_traits::image::base::PixelFormat; use net_traits::image_cache::CanRequestImages; @@ -45,10 +45,10 @@ use pixels; use profile_traits::ipc as profiled_ipc; use script_traits::ScriptMsg; use servo_url::ServoUrl; -use std::{fmt, mem}; use std::cell::Cell; use std::str::FromStr; use std::sync::Arc; +use std::{fmt, mem}; #[must_root] #[derive(Clone, JSTraceable, MallocSizeOf)] -- cgit v1.2.3 From 2012be4a8bd97f2fd69f986c8fffb1af1eec21dc Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 1 Nov 2018 21:43:04 +0100 Subject: `cargo fix --edition-idioms` --- components/script/dom/canvasrenderingcontext2d.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 1bf2a09b50f..6dbd1a860c5 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -126,7 +126,7 @@ impl CanvasRenderingContext2D { pub fn new_inherited( global: &GlobalScope, canvas: Option<&HTMLCanvasElement>, - image_cache: Arc, + image_cache: Arc, base_url: ServoUrl, size: Size2D, ) -> CanvasRenderingContext2D { -- cgit v1.2.3 From 9f977c52878e3638f475ca9a78e9f57d0d22893d Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 7 Nov 2018 17:08:14 +0100 Subject: Remove useless `use crate_name;` imports. A `crate_name::foo` path always works in 2018 --- components/script/dom/canvasrenderingcontext2d.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 6dbd1a860c5..3a031095dc8 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -41,7 +41,6 @@ use net_traits::image_cache::ImageOrMetadataAvailable; use net_traits::image_cache::ImageResponse; use net_traits::image_cache::ImageState; use net_traits::image_cache::UsePlaceholder; -use pixels; use profile_traits::ipc as profiled_ipc; use script_traits::ScriptMsg; use servo_url::ServoUrl; -- cgit v1.2.3 From a5779ad372b2b3c1c236c94680d01c60a99f19a4 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 15 Nov 2018 10:04:52 +0100 Subject: Prefix some pixels functions with rgba8_ --- components/script/dom/canvasrenderingcontext2d.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 3a031095dc8..18d6c978cae 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -403,7 +403,7 @@ impl CanvasRenderingContext2D { ) -> ErrorResult { debug!("Fetching image {}.", url); let (mut image_data, image_size) = self.fetch_image_data(url).ok_or(Error::InvalidState)?; - pixels::premultiply_inplace(&mut image_data); + pixels::rgba8_premultiply_inplace(&mut image_data); let image_size = image_size.to_f64(); let dw = dw.unwrap_or(image_size.width); -- cgit v1.2.3 From a1a14459c141afc6ac6771b8a6c9ca374537edf2 Mon Sep 17 00:00:00 2001 From: Jan Andre Ikenmeyer Date: Mon, 19 Nov 2018 14:47:12 +0100 Subject: Update MPL license to https (part 3) --- components/script/dom/canvasrenderingcontext2d.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 18d6c978cae..84aaef7a2d3 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -1,6 +1,6 @@ /* 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 http://mozilla.org/MPL/2.0/. */ + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use canvas_traits::canvas::{Canvas2dMsg, CanvasId, CanvasMsg}; use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; -- cgit v1.2.3 From 2c0acf6b9bf2c4082dfbd98763cd21de7ae56449 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 19 Nov 2018 10:42:50 +0100 Subject: Move PixelFormat to the pixels crate --- components/script/dom/canvasrenderingcontext2d.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 84aaef7a2d3..b9377a654fe 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -34,13 +34,13 @@ use cssparser::{Parser, ParserInput, RGBA}; use dom_struct::dom_struct; use euclid::{vec2, Point2D, Rect, Size2D, Transform2D}; use ipc_channel::ipc::{self, IpcSender}; -use net_traits::image::base::PixelFormat; use net_traits::image_cache::CanRequestImages; use net_traits::image_cache::ImageCache; use net_traits::image_cache::ImageOrMetadataAvailable; use net_traits::image_cache::ImageResponse; use net_traits::image_cache::ImageState; use net_traits::image_cache::UsePlaceholder; +use pixels::PixelFormat; use profile_traits::ipc as profiled_ipc; use script_traits::ScriptMsg; use servo_url::ServoUrl; -- cgit v1.2.3 From cfca906ee2325fad74896b7647db26625099cf66 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 19 Nov 2018 11:17:00 +0100 Subject: Call rgba8_byte_swap_colors_inplace on the WebGL thread --- components/script/dom/canvasrenderingcontext2d.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index b9377a654fe..4840966dfb4 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -444,9 +444,7 @@ impl CanvasRenderingContext2D { let image_size = Size2D::new(img.width, img.height); let image_data = match img.format { PixelFormat::BGRA8 => img.bytes.to_vec(), - PixelFormat::K8 => panic!("K8 color type not supported"), - PixelFormat::RGB8 => panic!("RGB8 color type not supported"), - PixelFormat::KA8 => panic!("KA8 color type not supported"), + pixel_format => unimplemented!("unsupported pixel format ({:?})", pixel_format), }; Some((image_data, image_size)) -- cgit v1.2.3 From 9a8d03a0f3047d8408b2368d46d144fea670f95d Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Wed, 21 Nov 2018 12:51:49 +0100 Subject: Make HTMLCanvasElement::fetch_all_data return a shared memory blob --- components/script/dom/canvasrenderingcontext2d.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 4840966dfb4..a50cce88870 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -1296,7 +1296,11 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { .ok_or(Error::InvalidState)? }, CanvasImageSource::HTMLCanvasElement(ref canvas) => { - canvas.fetch_all_data().ok_or(Error::InvalidState)? + let (data, size) = canvas.fetch_all_data().ok_or(Error::InvalidState)?; + let data = data + .map(|data| data.to_vec()) + .unwrap_or_else(|| vec![0; size.area() as usize * 4]); + (data, size) }, CanvasImageSource::CSSStyleValue(ref value) => value .get_url(self.base_url.clone()) -- cgit v1.2.3 From be69f9c3e6a6f5efb5ba1edd50955cb12c111bf8 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 14 Dec 2018 08:31:30 +0100 Subject: Rustfmt has changed its default style :/ --- components/script/dom/canvasrenderingcontext2d.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index a50cce88870..f21c7bfda1c 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -2,10 +2,6 @@ * 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 canvas_traits::canvas::{Canvas2dMsg, CanvasId, CanvasMsg}; -use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; -use canvas_traits::canvas::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; -use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle}; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasFillRule; @@ -29,6 +25,10 @@ use crate::dom::htmlcanvaselement::{CanvasContext, HTMLCanvasElement}; use crate::dom::imagedata::ImageData; use crate::dom::node::{window_from_node, Node, NodeDamage}; use crate::unpremultiplytable::UNPREMULTIPLY_TABLE; +use canvas_traits::canvas::{Canvas2dMsg, CanvasId, CanvasMsg}; +use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; +use canvas_traits::canvas::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; +use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle}; use cssparser::Color as CSSColor; use cssparser::{Parser, ParserInput, RGBA}; use dom_struct::dom_struct; -- cgit v1.2.3 From 6c6fb676b79e71621220a7226ca5558da6c879c6 Mon Sep 17 00:00:00 2001 From: Maharsh Date: Fri, 29 Mar 2019 15:12:53 -0400 Subject: Created CanvasRect fro OffscreenCanvas and Updated Testcases --- components/script/dom/canvasrenderingcontext2d.rs | 129 ++++++++++++++++------ 1 file changed, 97 insertions(+), 32 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index f21c7bfda1c..96da2168916 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -62,8 +62,8 @@ enum CanvasFillOrStrokeStyle { #[dom_struct] pub struct CanvasRenderingContext2D { reflector_: Reflector, - #[ignore_malloc_size_of = "Defined in ipc-channel"] - ipc_renderer: IpcSender, + //#[ignore_malloc_size_of = "Defined in ipc-channel"] + //ipc_renderer: IpcSender, /// For rendering contexts created by an HTML canvas element, this is Some, /// for ones created by a paint worklet, this is None. canvas: Option>, @@ -77,7 +77,8 @@ pub struct CanvasRenderingContext2D { state: DomRefCell, saved_states: DomRefCell>, origin_clean: Cell, - canvas_id: CanvasId, + //canvas_id: CanvasId, + canvas_state: DomRefCell, } #[must_root] @@ -121,6 +122,77 @@ impl CanvasContextState { } } +#[must_root] +#[derive(Clone, JSTraceable, MallocSizeOf)] +pub struct CanvasState { + //reflector_: Reflector, + #[ignore_malloc_size_of = "Defined in ipc-channel"] + ipc_renderer: IpcSender, + canvas_id: CanvasId, +} + +impl CanvasState { + pub fn new( + global: &GlobalScope, + ) -> CanvasState { + let (sender, receiver) = + profiled_ipc::channel(global.time_profiler_chan().clone()).unwrap(); + let (ipc_renderer, canvas_id) = receiver.recv().unwrap(); + debug!("Done."); + CanvasState { + //reflector_: Reflector::new(), + ipc_renderer: ipc_renderer, + canvas_id: canvas_id, + } + } + + pub fn get_canvas_id(&self) -> CanvasId { + self.canvas_id.clone() + } + + pub fn send_canvas_2d_msg(&self, msg: Canvas2dMsg) { + self.ipc_renderer + .send(CanvasMsg::Canvas2d(msg, self.get_canvas_id())) + .unwrap() + } + + fn create_drawable_rect(&self, x: f64, y: f64, w: f64, h: f64) -> Option> { + if !([x, y, w, h].iter().all(|val| val.is_finite())) { + return None; + } + + if w == 0.0 && h == 0.0 { + return None; + } + + Some(Rect::new( + Point2D::new(x as f32, y as f32), + Size2D::new(w as f32, h as f32), + )) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect + pub fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) { + if let Some(rect) = self.create_drawable_rect(x, y, width, height) { + self.send_canvas_2d_msg(Canvas2dMsg::FillRect(rect)); + } + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-clearrect + pub fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) { + if let Some(rect) = self.create_drawable_rect(x, y, width, height) { + self.send_canvas_2d_msg(Canvas2dMsg::ClearRect(rect)); + } + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokerect + pub fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) { + if let Some(rect) = self.create_drawable_rect(x, y, width, height) { + self.send_canvas_2d_msg(Canvas2dMsg::StrokeRect(rect)); + } + } +} + impl CanvasRenderingContext2D { pub fn new_inherited( global: &GlobalScope, @@ -137,19 +209,20 @@ impl CanvasRenderingContext2D { script_to_constellation_chan .send(ScriptMsg::CreateCanvasPaintThread(size, sender)) .unwrap(); - let (ipc_renderer, canvas_id) = receiver.recv().unwrap(); + //let (canvas_state.ipc_renderer, canvas_id) = receiver.recv().unwrap(); debug!("Done."); CanvasRenderingContext2D { reflector_: Reflector::new(), - ipc_renderer: ipc_renderer, canvas: canvas.map(Dom::from_ref), + //ipc_renderer: ipc_renderer, image_cache: image_cache, missing_image_urls: DomRefCell::new(Vec::new()), base_url: base_url, state: DomRefCell::new(CanvasContextState::new()), saved_states: DomRefCell::new(Vec::new()), origin_clean: Cell::new(true), - canvas_id: canvas_id, + //canvas_id: canvas_id, + canvas_state: DomRefCell::new(CanvasState::new(global)), } } @@ -174,8 +247,8 @@ impl CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#concept-canvas-set-bitmap-dimensions pub fn set_bitmap_dimensions(&self, size: Size2D) { self.reset_to_initial_state(); - self.ipc_renderer - .send(CanvasMsg::Recreate(size, self.get_canvas_id())) + self.canvas_state.borrow().ipc_renderer + .send(CanvasMsg::Recreate(size, self.canvas_state.borrow().get_canvas_id())) .unwrap(); } @@ -366,7 +439,7 @@ impl CanvasRenderingContext2D { match *context { CanvasContext::Context2d(ref context) => { context.send_canvas_2d_msg(Canvas2dMsg::DrawImageInOther( - self.get_canvas_id(), + self.canvas_state.borrow().get_canvas_id(), image_size, dest_rect, source_rect, @@ -475,7 +548,7 @@ impl CanvasRenderingContext2D { mem::replace(&mut self.missing_image_urls.borrow_mut(), vec![]) } - fn create_drawable_rect(&self, x: f64, y: f64, w: f64, h: f64) -> Option> { + /*fn create_drawable_rect(&self, x: f64, y: f64, w: f64, h: f64) -> Option> { if !([x, y, w, h].iter().all(|val| val.is_finite())) { return None; } @@ -488,7 +561,7 @@ impl CanvasRenderingContext2D { Point2D::new(x as f32, y as f32), Size2D::new(w as f32, h as f32), )) - } + }*/ fn parse_color(&self, string: &str) -> Result { let mut input = ParserInput::new(string); @@ -528,17 +601,15 @@ impl CanvasRenderingContext2D { } pub fn get_canvas_id(&self) -> CanvasId { - self.canvas_id.clone() + self.canvas_state.borrow().get_canvas_id() } pub fn send_canvas_2d_msg(&self, msg: Canvas2dMsg) { - self.ipc_renderer - .send(CanvasMsg::Canvas2d(msg, self.get_canvas_id())) - .unwrap() + self.canvas_state.borrow().send_canvas_2d_msg(msg) } pub fn get_ipc_renderer(&self) -> IpcSender { - self.ipc_renderer.clone() + self.canvas_state.borrow().ipc_renderer.clone() } pub fn origin_is_clean(&self) -> bool { @@ -585,12 +656,12 @@ pub trait LayoutCanvasRenderingContext2DHelpers { impl LayoutCanvasRenderingContext2DHelpers for LayoutDom { #[allow(unsafe_code)] unsafe fn get_ipc_renderer(&self) -> IpcSender { - (*self.unsafe_get()).ipc_renderer.clone() + (*self.unsafe_get()).canvas_state.borrow().ipc_renderer.clone() } #[allow(unsafe_code)] unsafe fn get_canvas_id(&self) -> CanvasId { - (*self.unsafe_get()).canvas_id.clone() + (*self.unsafe_get()).canvas_state.borrow().get_canvas_id() } } @@ -747,26 +818,20 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) { - if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.send_canvas_2d_msg(Canvas2dMsg::FillRect(rect)); - self.mark_as_dirty(); - } + self.canvas_state.borrow().FillRect(x, y, width, height); + self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-clearrect fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) { - if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.send_canvas_2d_msg(Canvas2dMsg::ClearRect(rect)); - self.mark_as_dirty(); - } + self.canvas_state.borrow().ClearRect(x, y, width, height); + self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokerect fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) { - if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.send_canvas_2d_msg(Canvas2dMsg::StrokeRect(rect)); - self.mark_as_dirty(); - } + self.canvas_state.borrow().StrokeRect(x, y, width, height); + self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-beginpath @@ -1458,8 +1523,8 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { impl Drop for CanvasRenderingContext2D { fn drop(&mut self) { if let Err(err) = self - .ipc_renderer - .send(CanvasMsg::Close(self.get_canvas_id())) + .canvas_state.borrow().ipc_renderer + .send(CanvasMsg::Close(self.canvas_state.borrow().get_canvas_id())) { warn!("Could not close canvas: {}", err) } -- cgit v1.2.3 From 30cc087526c1d06424c770db1d851ed90a28c926 Mon Sep 17 00:00:00 2001 From: Maharsh Date: Thu, 9 May 2019 18:30:25 -0400 Subject: Changes for gitignore --- components/script/dom/canvasrenderingcontext2d.rs | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 96da2168916..285925b7302 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -132,9 +132,7 @@ pub struct CanvasState { } impl CanvasState { - pub fn new( - global: &GlobalScope, - ) -> CanvasState { + pub fn new(global: &GlobalScope) -> CanvasState { let (sender, receiver) = profiled_ipc::channel(global.time_profiler_chan().clone()).unwrap(); let (ipc_renderer, canvas_id) = receiver.recv().unwrap(); @@ -247,8 +245,13 @@ impl CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#concept-canvas-set-bitmap-dimensions pub fn set_bitmap_dimensions(&self, size: Size2D) { self.reset_to_initial_state(); - self.canvas_state.borrow().ipc_renderer - .send(CanvasMsg::Recreate(size, self.canvas_state.borrow().get_canvas_id())) + self.canvas_state + .borrow() + .ipc_renderer + .send(CanvasMsg::Recreate( + size, + self.canvas_state.borrow().get_canvas_id(), + )) .unwrap(); } @@ -656,7 +659,11 @@ pub trait LayoutCanvasRenderingContext2DHelpers { impl LayoutCanvasRenderingContext2DHelpers for LayoutDom { #[allow(unsafe_code)] unsafe fn get_ipc_renderer(&self) -> IpcSender { - (*self.unsafe_get()).canvas_state.borrow().ipc_renderer.clone() + (*self.unsafe_get()) + .canvas_state + .borrow() + .ipc_renderer + .clone() } #[allow(unsafe_code)] @@ -1523,7 +1530,9 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { impl Drop for CanvasRenderingContext2D { fn drop(&mut self) { if let Err(err) = self - .canvas_state.borrow().ipc_renderer + .canvas_state + .borrow() + .ipc_renderer .send(CanvasMsg::Close(self.canvas_state.borrow().get_canvas_id())) { warn!("Could not close canvas: {}", err) -- cgit v1.2.3 From 1de8ddd89c49356bcf551c63dc8be1ad25c327af Mon Sep 17 00:00:00 2001 From: Maharsh Date: Thu, 9 May 2019 21:54:48 -0400 Subject: Changes for sender reciever --- components/script/dom/canvasrenderingcontext2d.rs | 31 +++++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 285925b7302..67c18ff0c22 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -132,17 +132,38 @@ pub struct CanvasState { } impl CanvasState { - pub fn new(global: &GlobalScope) -> CanvasState { + pub fn new( + global: &GlobalScope, + size: Size2D, + ) -> CanvasState { + debug!("Creating new canvas rendering context."); let (sender, receiver) = profiled_ipc::channel(global.time_profiler_chan().clone()).unwrap(); + let script_to_constellation_chan = global.script_to_constellation_chan(); + debug!("Asking constellation to create new canvas thread."); + script_to_constellation_chan + .send(ScriptMsg::CreateCanvasPaintThread(size, sender)) + .unwrap(); let (ipc_renderer, canvas_id) = receiver.recv().unwrap(); debug!("Done."); CanvasState { - //reflector_: Reflector::new(), ipc_renderer: ipc_renderer, canvas_id: canvas_id, + } } + /*pub fn new( + global: &GlobalScope, + size: Size2D, + ) -> CanvasState { + + /*let boxed = Box::new(CanvasState::new_inherited( + global, + size, + )); + + reflect_dom_object(boxed, global, CanvasState)*/ + }*/ pub fn get_canvas_id(&self) -> CanvasId { self.canvas_id.clone() @@ -199,7 +220,7 @@ impl CanvasRenderingContext2D { base_url: ServoUrl, size: Size2D, ) -> CanvasRenderingContext2D { - debug!("Creating new canvas rendering context."); + /*debug!("Creating new canvas rendering context."); let (sender, receiver) = profiled_ipc::channel(global.time_profiler_chan().clone()).unwrap(); let script_to_constellation_chan = global.script_to_constellation_chan(); @@ -208,7 +229,7 @@ impl CanvasRenderingContext2D { .send(ScriptMsg::CreateCanvasPaintThread(size, sender)) .unwrap(); //let (canvas_state.ipc_renderer, canvas_id) = receiver.recv().unwrap(); - debug!("Done."); + debug!("Done.");*/ CanvasRenderingContext2D { reflector_: Reflector::new(), canvas: canvas.map(Dom::from_ref), @@ -220,7 +241,7 @@ impl CanvasRenderingContext2D { saved_states: DomRefCell::new(Vec::new()), origin_clean: Cell::new(true), //canvas_id: canvas_id, - canvas_state: DomRefCell::new(CanvasState::new(global)), + canvas_state: DomRefCell::new(CanvasState::new(global,Size2D::new(size.width as u64, size.height as u64))), } } -- cgit v1.2.3 From 65e1f1fb3edf7cff7849bd9c6833d1a060d789a2 Mon Sep 17 00:00:00 2001 From: Maharsh Date: Sat, 11 May 2019 21:58:15 -0400 Subject: Updated Testcases and Formatting --- components/script/dom/canvasrenderingcontext2d.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 67c18ff0c22..18844a41ae4 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -132,10 +132,7 @@ pub struct CanvasState { } impl CanvasState { - pub fn new( - global: &GlobalScope, - size: Size2D, - ) -> CanvasState { + pub fn new(global: &GlobalScope, size: Size2D) -> CanvasState { debug!("Creating new canvas rendering context."); let (sender, receiver) = profiled_ipc::channel(global.time_profiler_chan().clone()).unwrap(); @@ -149,14 +146,13 @@ impl CanvasState { CanvasState { ipc_renderer: ipc_renderer, canvas_id: canvas_id, - } } /*pub fn new( global: &GlobalScope, size: Size2D, ) -> CanvasState { - + /*let boxed = Box::new(CanvasState::new_inherited( global, size, @@ -241,7 +237,10 @@ impl CanvasRenderingContext2D { saved_states: DomRefCell::new(Vec::new()), origin_clean: Cell::new(true), //canvas_id: canvas_id, - canvas_state: DomRefCell::new(CanvasState::new(global,Size2D::new(size.width as u64, size.height as u64))), + canvas_state: DomRefCell::new(CanvasState::new( + global, + Size2D::new(size.width as u64, size.height as u64), + )), } } -- cgit v1.2.3 From 854ba8d51461c2c9166335d16c9597630fc29ce5 Mon Sep 17 00:00:00 2001 From: Maharsh Date: Mon, 13 May 2019 12:04:17 -0400 Subject: Borrow Layout Change --- components/script/dom/canvasrenderingcontext2d.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 18844a41ae4..1092c9ea88f 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -681,14 +681,17 @@ impl LayoutCanvasRenderingContext2DHelpers for LayoutDom IpcSender { (*self.unsafe_get()) .canvas_state - .borrow() + .borrow_for_layout() .ipc_renderer .clone() } #[allow(unsafe_code)] unsafe fn get_canvas_id(&self) -> CanvasId { - (*self.unsafe_get()).canvas_state.borrow().get_canvas_id() + (*self.unsafe_get()) + .canvas_state + .borrow_for_layout() + .get_canvas_id() } } -- cgit v1.2.3 From cbff66928ffbd8a80b22e1f58feb9bc162425d5a Mon Sep 17 00:00:00 2001 From: Maharsh Date: Mon, 13 May 2019 14:17:12 -0400 Subject: removed comments --- components/script/dom/canvasrenderingcontext2d.rs | 46 +---------------------- 1 file changed, 1 insertion(+), 45 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 1092c9ea88f..0639e70549a 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -62,8 +62,6 @@ enum CanvasFillOrStrokeStyle { #[dom_struct] pub struct CanvasRenderingContext2D { reflector_: Reflector, - //#[ignore_malloc_size_of = "Defined in ipc-channel"] - //ipc_renderer: IpcSender, /// For rendering contexts created by an HTML canvas element, this is Some, /// for ones created by a paint worklet, this is None. canvas: Option>, @@ -77,7 +75,6 @@ pub struct CanvasRenderingContext2D { state: DomRefCell, saved_states: DomRefCell>, origin_clean: Cell, - //canvas_id: CanvasId, canvas_state: DomRefCell, } @@ -122,10 +119,8 @@ impl CanvasContextState { } } -#[must_root] -#[derive(Clone, JSTraceable, MallocSizeOf)] +#[derive(JSTraceable, MallocSizeOf)] pub struct CanvasState { - //reflector_: Reflector, #[ignore_malloc_size_of = "Defined in ipc-channel"] ipc_renderer: IpcSender, canvas_id: CanvasId, @@ -148,18 +143,6 @@ impl CanvasState { canvas_id: canvas_id, } } - /*pub fn new( - global: &GlobalScope, - size: Size2D, - ) -> CanvasState { - - /*let boxed = Box::new(CanvasState::new_inherited( - global, - size, - )); - - reflect_dom_object(boxed, global, CanvasState)*/ - }*/ pub fn get_canvas_id(&self) -> CanvasId { self.canvas_id.clone() @@ -216,27 +199,15 @@ impl CanvasRenderingContext2D { base_url: ServoUrl, size: Size2D, ) -> CanvasRenderingContext2D { - /*debug!("Creating new canvas rendering context."); - let (sender, receiver) = - profiled_ipc::channel(global.time_profiler_chan().clone()).unwrap(); - let script_to_constellation_chan = global.script_to_constellation_chan(); - debug!("Asking constellation to create new canvas thread."); - script_to_constellation_chan - .send(ScriptMsg::CreateCanvasPaintThread(size, sender)) - .unwrap(); - //let (canvas_state.ipc_renderer, canvas_id) = receiver.recv().unwrap(); - debug!("Done.");*/ CanvasRenderingContext2D { reflector_: Reflector::new(), canvas: canvas.map(Dom::from_ref), - //ipc_renderer: ipc_renderer, image_cache: image_cache, missing_image_urls: DomRefCell::new(Vec::new()), base_url: base_url, state: DomRefCell::new(CanvasContextState::new()), saved_states: DomRefCell::new(Vec::new()), origin_clean: Cell::new(true), - //canvas_id: canvas_id, canvas_state: DomRefCell::new(CanvasState::new( global, Size2D::new(size.width as u64, size.height as u64), @@ -571,21 +542,6 @@ impl CanvasRenderingContext2D { mem::replace(&mut self.missing_image_urls.borrow_mut(), vec![]) } - /*fn create_drawable_rect(&self, x: f64, y: f64, w: f64, h: f64) -> Option> { - if !([x, y, w, h].iter().all(|val| val.is_finite())) { - return None; - } - - if w == 0.0 && h == 0.0 { - return None; - } - - Some(Rect::new( - Point2D::new(x as f32, y as f32), - Size2D::new(w as f32, h as f32), - )) - }*/ - fn parse_color(&self, string: &str) -> Result { let mut input = ParserInput::new(string); let mut parser = Parser::new(&mut input); -- cgit v1.2.3 From 85c20db495b25af653e6cb77130e166fae8d4b20 Mon Sep 17 00:00:00 2001 From: Maharsh Date: Tue, 14 May 2019 02:15:20 -0400 Subject: Extract canvas operations for reuse by OffscreenCanvas. --- components/script/dom/canvasrenderingcontext2d.rs | 2024 +++++++++++++-------- 1 file changed, 1254 insertions(+), 770 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 0639e70549a..2a26a1c5752 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -23,7 +23,7 @@ use crate::dom::element::Element; use crate::dom::globalscope::GlobalScope; use crate::dom::htmlcanvaselement::{CanvasContext, HTMLCanvasElement}; use crate::dom::imagedata::ImageData; -use crate::dom::node::{window_from_node, Node, NodeDamage}; +use crate::dom::node::{Node, NodeDamage}; use crate::unpremultiplytable::UNPREMULTIPLY_TABLE; use canvas_traits::canvas::{Canvas2dMsg, CanvasId, CanvasMsg}; use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; @@ -65,16 +65,6 @@ pub struct CanvasRenderingContext2D { /// For rendering contexts created by an HTML canvas element, this is Some, /// for ones created by a paint worklet, this is None. canvas: Option>, - #[ignore_malloc_size_of = "Arc"] - image_cache: Arc, - /// Any missing image URLs. - missing_image_urls: DomRefCell>, - /// The base URL for resolving CSS image URL values. - /// Needed because of https://github.com/servo/servo/issues/17625 - base_url: ServoUrl, - state: DomRefCell, - saved_states: DomRefCell>, - origin_clean: Cell, canvas_state: DomRefCell, } @@ -119,11 +109,22 @@ impl CanvasContextState { } } +#[must_root] #[derive(JSTraceable, MallocSizeOf)] pub struct CanvasState { #[ignore_malloc_size_of = "Defined in ipc-channel"] ipc_renderer: IpcSender, canvas_id: CanvasId, + state: DomRefCell, + origin_clean: Cell, + #[ignore_malloc_size_of = "Arc"] + image_cache: Arc, + /// The base URL for resolving CSS image URL values. + /// Needed because of https://github.com/servo/servo/issues/17625 + base_url: ServoUrl, + /// Any missing image URLs. + missing_image_urls: DomRefCell>, + saved_states: DomRefCell>, } impl CanvasState { @@ -141,6 +142,12 @@ impl CanvasState { CanvasState { ipc_renderer: ipc_renderer, canvas_id: canvas_id, + state: DomRefCell::new(CanvasContextState::new()), + origin_clean: Cell::new(true), + image_cache: global.image_cache(), + base_url: global.api_base_url(), + missing_image_urls: DomRefCell::new(Vec::new()), + saved_states: DomRefCell::new(Vec::new()), } } @@ -169,172 +176,122 @@ impl CanvasState { )) } - // https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect - pub fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) { - if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.send_canvas_2d_msg(Canvas2dMsg::FillRect(rect)); - } - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-clearrect - pub fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) { - if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.send_canvas_2d_msg(Canvas2dMsg::ClearRect(rect)); - } + fn origin_is_clean(&self) -> bool { + self.origin_clean.get() } - // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokerect - pub fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) { - if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.send_canvas_2d_msg(Canvas2dMsg::StrokeRect(rect)); - } + fn set_origin_unclean(&self) { + self.origin_clean.set(false) } -} -impl CanvasRenderingContext2D { - pub fn new_inherited( - global: &GlobalScope, - canvas: Option<&HTMLCanvasElement>, - image_cache: Arc, - base_url: ServoUrl, - size: Size2D, - ) -> CanvasRenderingContext2D { - CanvasRenderingContext2D { - reflector_: Reflector::new(), - canvas: canvas.map(Dom::from_ref), - image_cache: image_cache, - missing_image_urls: DomRefCell::new(Vec::new()), - base_url: base_url, - state: DomRefCell::new(CanvasContextState::new()), - saved_states: DomRefCell::new(Vec::new()), - origin_clean: Cell::new(true), - canvas_state: DomRefCell::new(CanvasState::new( - global, - Size2D::new(size.width as u64, size.height as u64), - )), + // https://html.spec.whatwg.org/multipage/#the-image-argument-is-not-origin-clean + fn is_origin_clean(&self, image: CanvasImageSource) -> bool { + match image { + CanvasImageSource::HTMLCanvasElement(canvas) => canvas.origin_is_clean(), + CanvasImageSource::HTMLImageElement(image) => { + image.same_origin(GlobalScope::entry().origin()) + }, + CanvasImageSource::CSSStyleValue(_) => true, } } - pub fn new( - global: &GlobalScope, - canvas: &HTMLCanvasElement, - size: Size2D, - ) -> DomRoot { - let window = window_from_node(canvas); - let image_cache = window.image_cache(); - let base_url = window.get_url(); - let boxed = Box::new(CanvasRenderingContext2D::new_inherited( - global, - Some(canvas), - image_cache, - base_url, - size, - )); - reflect_dom_object(boxed, global, CanvasRenderingContext2DBinding::Wrap) - } + fn fetch_image_data(&self, url: ServoUrl) -> Option<(Vec, Size2D)> { + let img = match self.request_image_from_cache(url) { + ImageResponse::Loaded(img, _) => img, + ImageResponse::PlaceholderLoaded(_, _) | + ImageResponse::None | + ImageResponse::MetadataLoaded(_) => { + return None; + }, + }; - // https://html.spec.whatwg.org/multipage/#concept-canvas-set-bitmap-dimensions - pub fn set_bitmap_dimensions(&self, size: Size2D) { - self.reset_to_initial_state(); - self.canvas_state - .borrow() - .ipc_renderer - .send(CanvasMsg::Recreate( - size, - self.canvas_state.borrow().get_canvas_id(), - )) - .unwrap(); - } + let image_size = Size2D::new(img.width, img.height); + let image_data = match img.format { + PixelFormat::BGRA8 => img.bytes.to_vec(), + pixel_format => unimplemented!("unsupported pixel format ({:?})", pixel_format), + }; - // https://html.spec.whatwg.org/multipage/#reset-the-rendering-context-to-its-default-state - fn reset_to_initial_state(&self) { - self.saved_states.borrow_mut().clear(); - *self.state.borrow_mut() = CanvasContextState::new(); + Some((image_data, image_size)) } - fn mark_as_dirty(&self) { - if let Some(ref canvas) = self.canvas { - canvas.upcast::().dirty(NodeDamage::OtherNodeDamage); + #[inline] + fn request_image_from_cache(&self, url: ServoUrl) -> ImageResponse { + let response = self.image_cache.find_image_or_metadata( + url.clone(), + UsePlaceholder::No, + CanRequestImages::No, + ); + match response { + Ok(ImageOrMetadataAvailable::ImageAvailable(image, url)) => { + ImageResponse::Loaded(image, url) + }, + Err(ImageState::Pending(_)) => ImageResponse::None, + _ => { + // Rather annoyingly, we get the same response back from + // A load which really failed and from a load which hasn't started yet. + self.missing_image_urls.borrow_mut().push(url); + ImageResponse::None + }, } } - fn update_transform(&self) { - self.send_canvas_2d_msg(Canvas2dMsg::SetTransform(self.state.borrow().transform)) - } - - // It is used by DrawImage to calculate the size of the source and destination rectangles based - // on the drawImage call arguments - // source rectangle = area of the original image to be copied - // destination rectangle = area of the destination canvas where the source image is going to be drawn - fn adjust_source_dest_rects( - &self, - image_size: Size2D, - sx: f64, - sy: f64, - sw: f64, - sh: f64, - dx: f64, - dy: f64, - dw: f64, - dh: f64, - ) -> (Rect, Rect) { - let image_rect = Rect::new( - Point2D::new(0f64, 0f64), - Size2D::new(image_size.width as f64, image_size.height as f64), - ); - - // The source rectangle is the rectangle whose corners are the four points (sx, sy), - // (sx+sw, sy), (sx+sw, sy+sh), (sx, sy+sh). - let source_rect = Rect::new( - Point2D::new(sx.min(sx + sw), sy.min(sy + sh)), - Size2D::new(sw.abs(), sh.abs()), - ); + fn parse_color(&self, canvas: Option<&HTMLCanvasElement>, string: &str) -> Result { + let mut input = ParserInput::new(string); + let mut parser = Parser::new(&mut input); + let color = CSSColor::parse(&mut parser); + if parser.is_exhausted() { + match color { + Ok(CSSColor::RGBA(rgba)) => Ok(rgba), + Ok(CSSColor::CurrentColor) => { + // TODO: https://github.com/whatwg/html/issues/1099 + // Reconsider how to calculate currentColor in a display:none canvas - // When the source rectangle is outside the source image, - // the source rectangle must be clipped to the source image - let source_rect_clipped = source_rect - .intersection(&image_rect) - .unwrap_or(Rect::zero()); + // TODO: will need to check that the context bitmap mode is fixed + // once we implement CanvasProxy + let canvas = match canvas { + // https://drafts.css-houdini.org/css-paint-api/#2d-rendering-context + // Whenever "currentColor" is used as a color in the PaintRenderingContext2D API, + // it is treated as opaque black. + None => return Ok(RGBA::new(0, 0, 0, 255)), + Some(ref canvas) => &**canvas, + }; - // Width and height ratios between the non clipped and clipped source rectangles - let width_ratio: f64 = source_rect_clipped.size.width / source_rect.size.width; - let height_ratio: f64 = source_rect_clipped.size.height / source_rect.size.height; + let canvas_element = canvas.upcast::(); - // When the source rectangle is outside the source image, - // the destination rectangle must be clipped in the same proportion. - let dest_rect_width_scaled: f64 = dw * width_ratio; - let dest_rect_height_scaled: f64 = dh * height_ratio; + match canvas_element.style() { + Some(ref s) if canvas_element.has_css_layout_box() => { + Ok(s.get_color().color) + }, + _ => Ok(RGBA::new(0, 0, 0, 255)), + } + }, + _ => Err(()), + } + } else { + Err(()) + } + } - // The destination rectangle is the rectangle whose corners are the four points (dx, dy), - // (dx+dw, dy), (dx+dw, dy+dh), (dx, dy+dh). - let dest_rect = Rect::new( - Point2D::new( - dx.min(dx + dest_rect_width_scaled), - dy.min(dy + dest_rect_height_scaled), - ), - Size2D::new(dest_rect_width_scaled.abs(), dest_rect_height_scaled.abs()), - ); + pub fn get_rect(&self, canvas: Option<&HTMLCanvasElement>, rect: Rect) -> Vec { + assert!(self.origin_is_clean()); - let source_rect = Rect::new( - Point2D::new(source_rect_clipped.origin.x, source_rect_clipped.origin.y), - Size2D::new( - source_rect_clipped.size.width, - source_rect_clipped.size.height, - ), - ); + // FIXME(nox): This is probably wrong when this is a context for an + // offscreen canvas. + let canvas_size = canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()); + assert!(Rect::from_size(canvas_size).contains_rect(&rect)); - (source_rect, dest_rect) - } + let (sender, receiver) = ipc::bytes_channel().unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::GetImageData(rect, canvas_size, sender)); + let mut pixels = receiver.recv().unwrap().to_vec(); - // https://html.spec.whatwg.org/multipage/#the-image-argument-is-not-origin-clean - fn is_origin_clean(&self, image: CanvasImageSource) -> bool { - match image { - CanvasImageSource::HTMLCanvasElement(canvas) => canvas.origin_is_clean(), - CanvasImageSource::HTMLImageElement(image) => { - image.same_origin(GlobalScope::entry().origin()) - }, - CanvasImageSource::CSSStyleValue(_) => true, + for chunk in pixels.chunks_mut(4) { + let b = chunk[0]; + chunk[0] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + chunk[2] as usize]; + chunk[1] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + chunk[1] as usize]; + chunk[2] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + b as usize]; } + + pixels } // @@ -360,6 +317,7 @@ impl CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage fn draw_image( &self, + htmlcanvas: Option<&HTMLCanvasElement>, image: CanvasImageSource, sx: f64, sy: f64, @@ -372,20 +330,20 @@ impl CanvasRenderingContext2D { ) -> ErrorResult { let result = match image { CanvasImageSource::HTMLCanvasElement(ref canvas) => { - self.draw_html_canvas_element(&canvas, sx, sy, sw, sh, dx, dy, dw, dh) + self.draw_html_canvas_element(&canvas, htmlcanvas, sx, sy, sw, sh, dx, dy, dw, dh) }, CanvasImageSource::HTMLImageElement(ref image) => { // https://html.spec.whatwg.org/multipage/#img-error // If the image argument is an HTMLImageElement object that is in the broken state, // then throw an InvalidStateError exception let url = image.get_url().ok_or(Error::InvalidState)?; - self.fetch_and_draw_image_data(url, sx, sy, sw, sh, dx, dy, dw, dh) + self.fetch_and_draw_image_data(htmlcanvas, url, sx, sy, sw, sh, dx, dy, dw, dh) }, CanvasImageSource::CSSStyleValue(ref value) => { let url = value .get_url(self.base_url.clone()) .ok_or(Error::InvalidState)?; - self.fetch_and_draw_image_data(url, sx, sy, sw, sh, dx, dy, dw, dh) + self.fetch_and_draw_image_data(htmlcanvas, url, sx, sy, sw, sh, dx, dy, dw, dh) }, }; @@ -398,6 +356,7 @@ impl CanvasRenderingContext2D { fn draw_html_canvas_element( &self, canvas: &HTMLCanvasElement, + htmlcanvas: Option<&HTMLCanvasElement>, sx: f64, sy: f64, sw: Option, @@ -433,7 +392,7 @@ impl CanvasRenderingContext2D { match *context { CanvasContext::Context2d(ref context) => { context.send_canvas_2d_msg(Canvas2dMsg::DrawImageInOther( - self.canvas_state.borrow().get_canvas_id(), + self.get_canvas_id(), image_size, dest_rect, source_rect, @@ -452,12 +411,13 @@ impl CanvasRenderingContext2D { )); } - self.mark_as_dirty(); + self.mark_as_dirty(htmlcanvas); Ok(()) } fn fetch_and_draw_image_data( &self, + canvas: Option<&HTMLCanvasElement>, url: ServoUrl, sx: f64, sy: f64, @@ -494,91 +454,1033 @@ impl CanvasRenderingContext2D { source_rect, smoothing_enabled, )); - self.mark_as_dirty(); + self.mark_as_dirty(canvas); Ok(()) } - fn fetch_image_data(&self, url: ServoUrl) -> Option<(Vec, Size2D)> { - let img = match self.request_image_from_cache(url) { - ImageResponse::Loaded(img, _) => img, - ImageResponse::PlaceholderLoaded(_, _) | - ImageResponse::None | - ImageResponse::MetadataLoaded(_) => { - return None; - }, - }; + fn mark_as_dirty(&self, canvas: Option<&HTMLCanvasElement>) { + if let Some(ref canvas) = canvas { + canvas.upcast::().dirty(NodeDamage::OtherNodeDamage); + } + } + + // It is used by DrawImage to calculate the size of the source and destination rectangles based + // on the drawImage call arguments + // source rectangle = area of the original image to be copied + // destination rectangle = area of the destination canvas where the source image is going to be drawn + fn adjust_source_dest_rects( + &self, + image_size: Size2D, + sx: f64, + sy: f64, + sw: f64, + sh: f64, + dx: f64, + dy: f64, + dw: f64, + dh: f64, + ) -> (Rect, Rect) { + let image_rect = Rect::new( + Point2D::new(0f64, 0f64), + Size2D::new(image_size.width as f64, image_size.height as f64), + ); + + // The source rectangle is the rectangle whose corners are the four points (sx, sy), + // (sx+sw, sy), (sx+sw, sy+sh), (sx, sy+sh). + let source_rect = Rect::new( + Point2D::new(sx.min(sx + sw), sy.min(sy + sh)), + Size2D::new(sw.abs(), sh.abs()), + ); + + // When the source rectangle is outside the source image, + // the source rectangle must be clipped to the source image + let source_rect_clipped = source_rect + .intersection(&image_rect) + .unwrap_or(Rect::zero()); + + // Width and height ratios between the non clipped and clipped source rectangles + let width_ratio: f64 = source_rect_clipped.size.width / source_rect.size.width; + let height_ratio: f64 = source_rect_clipped.size.height / source_rect.size.height; + + // When the source rectangle is outside the source image, + // the destination rectangle must be clipped in the same proportion. + let dest_rect_width_scaled: f64 = dw * width_ratio; + let dest_rect_height_scaled: f64 = dh * height_ratio; + + // The destination rectangle is the rectangle whose corners are the four points (dx, dy), + // (dx+dw, dy), (dx+dw, dy+dh), (dx, dy+dh). + let dest_rect = Rect::new( + Point2D::new( + dx.min(dx + dest_rect_width_scaled), + dy.min(dy + dest_rect_height_scaled), + ), + Size2D::new(dest_rect_width_scaled.abs(), dest_rect_height_scaled.abs()), + ); + + let source_rect = Rect::new( + Point2D::new(source_rect_clipped.origin.x, source_rect_clipped.origin.y), + Size2D::new( + source_rect_clipped.size.width, + source_rect_clipped.size.height, + ), + ); + + (source_rect, dest_rect) + } + + fn update_transform(&self) { + self.send_canvas_2d_msg(Canvas2dMsg::SetTransform(self.state.borrow().transform)) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect + pub fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) { + if let Some(rect) = self.create_drawable_rect(x, y, width, height) { + self.send_canvas_2d_msg(Canvas2dMsg::FillRect(rect)); + } + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-clearrect + pub fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) { + if let Some(rect) = self.create_drawable_rect(x, y, width, height) { + self.send_canvas_2d_msg(Canvas2dMsg::ClearRect(rect)); + } + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokerect + pub fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) { + if let Some(rect) = self.create_drawable_rect(x, y, width, height) { + self.send_canvas_2d_msg(Canvas2dMsg::StrokeRect(rect)); + } + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx + pub fn ShadowOffsetX(&self) -> f64 { + self.state.borrow().shadow_offset_x + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx + pub fn SetShadowOffsetX(&self, value: f64) { + if !value.is_finite() || value == self.state.borrow().shadow_offset_x { + return; + } + self.state.borrow_mut().shadow_offset_x = value; + self.send_canvas_2d_msg(Canvas2dMsg::SetShadowOffsetX(value)) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety + pub fn ShadowOffsetY(&self) -> f64 { + self.state.borrow().shadow_offset_y + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety + pub fn SetShadowOffsetY(&self, value: f64) { + if !value.is_finite() || value == self.state.borrow().shadow_offset_y { + return; + } + self.state.borrow_mut().shadow_offset_y = value; + self.send_canvas_2d_msg(Canvas2dMsg::SetShadowOffsetY(value)) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur + pub fn ShadowBlur(&self) -> f64 { + self.state.borrow().shadow_blur + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur + pub fn SetShadowBlur(&self, value: f64) { + if !value.is_finite() || value < 0f64 || value == self.state.borrow().shadow_blur { + return; + } + self.state.borrow_mut().shadow_blur = value; + self.send_canvas_2d_msg(Canvas2dMsg::SetShadowBlur(value)) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor + pub fn ShadowColor(&self) -> DOMString { + let mut result = String::new(); + serialize(&self.state.borrow().shadow_color, &mut result).unwrap(); + DOMString::from(result) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor + pub fn SetShadowColor(&self, value: DOMString) { + if let Ok(color) = parse_color(&value) { + self.state.borrow_mut().shadow_color = color; + self.send_canvas_2d_msg(Canvas2dMsg::SetShadowColor(color)) + } + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle + pub fn StrokeStyle(&self) -> StringOrCanvasGradientOrCanvasPattern { + match self.state.borrow().stroke_style { + CanvasFillOrStrokeStyle::Color(ref rgba) => { + let mut result = String::new(); + serialize(rgba, &mut result).unwrap(); + StringOrCanvasGradientOrCanvasPattern::String(DOMString::from(result)) + }, + CanvasFillOrStrokeStyle::Gradient(ref gradient) => { + StringOrCanvasGradientOrCanvasPattern::CanvasGradient(DomRoot::from_ref(&*gradient)) + }, + CanvasFillOrStrokeStyle::Pattern(ref pattern) => { + StringOrCanvasGradientOrCanvasPattern::CanvasPattern(DomRoot::from_ref(&*pattern)) + }, + } + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle + pub fn SetStrokeStyle( + &self, + canvas: Option<&HTMLCanvasElement>, + value: StringOrCanvasGradientOrCanvasPattern, + ) { + match value { + StringOrCanvasGradientOrCanvasPattern::String(string) => { + if let Ok(rgba) = self.parse_color(canvas, &string) { + self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Color(rgba); + self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(FillOrStrokeStyle::Color( + rgba, + ))); + } + }, + StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => { + self.state.borrow_mut().stroke_style = + CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient)); + self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle( + gradient.to_fill_or_stroke_style(), + )); + }, + StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => { + self.state.borrow_mut().stroke_style = + CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern)); + self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle( + pattern.to_fill_or_stroke_style(), + )); + if !pattern.origin_is_clean() { + self.set_origin_unclean(); + } + }, + } + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle + pub fn FillStyle(&self) -> StringOrCanvasGradientOrCanvasPattern { + match self.state.borrow().fill_style { + CanvasFillOrStrokeStyle::Color(ref rgba) => { + let mut result = String::new(); + serialize(rgba, &mut result).unwrap(); + StringOrCanvasGradientOrCanvasPattern::String(DOMString::from(result)) + }, + CanvasFillOrStrokeStyle::Gradient(ref gradient) => { + StringOrCanvasGradientOrCanvasPattern::CanvasGradient(DomRoot::from_ref(&*gradient)) + }, + CanvasFillOrStrokeStyle::Pattern(ref pattern) => { + StringOrCanvasGradientOrCanvasPattern::CanvasPattern(DomRoot::from_ref(&*pattern)) + }, + } + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle + pub fn SetFillStyle( + &self, + canvas: Option<&HTMLCanvasElement>, + value: StringOrCanvasGradientOrCanvasPattern, + ) { + match value { + StringOrCanvasGradientOrCanvasPattern::String(string) => { + if let Ok(rgba) = self.parse_color(canvas, &string) { + self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Color(rgba); + self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(FillOrStrokeStyle::Color( + rgba, + ))) + } + }, + StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => { + self.state.borrow_mut().fill_style = + CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient)); + self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle( + gradient.to_fill_or_stroke_style(), + )); + }, + StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => { + self.state.borrow_mut().fill_style = + CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern)); + self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle( + pattern.to_fill_or_stroke_style(), + )); + if !pattern.origin_is_clean() { + self.set_origin_unclean(); + } + }, + } + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-createlineargradient + pub fn CreateLinearGradient( + &self, + global: &GlobalScope, + x0: Finite, + y0: Finite, + x1: Finite, + y1: Finite, + ) -> DomRoot { + CanvasGradient::new( + global, + CanvasGradientStyle::Linear(LinearGradientStyle::new(*x0, *y0, *x1, *y1, Vec::new())), + ) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-createradialgradient + pub fn CreateRadialGradient( + &self, + global: &GlobalScope, + x0: Finite, + y0: Finite, + r0: Finite, + x1: Finite, + y1: Finite, + r1: Finite, + ) -> Fallible> { + if *r0 < 0. || *r1 < 0. { + return Err(Error::IndexSize); + } + + Ok(CanvasGradient::new( + global, + CanvasGradientStyle::Radial(RadialGradientStyle::new( + *x0, + *y0, + *r0, + *x1, + *y1, + *r1, + Vec::new(), + )), + )) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern + pub fn CreatePattern( + &self, + global: &GlobalScope, + image: CanvasImageSource, + mut repetition: DOMString, + ) -> Fallible> { + let (image_data, image_size) = match image { + CanvasImageSource::HTMLImageElement(ref image) => { + // https://html.spec.whatwg.org/multipage/#img-error + // If the image argument is an HTMLImageElement object that is in the broken state, + // then throw an InvalidStateError exception + image + .get_url() + .and_then(|url| self.fetch_image_data(url)) + .ok_or(Error::InvalidState)? + }, + CanvasImageSource::HTMLCanvasElement(ref canvas) => { + let (data, size) = canvas.fetch_all_data().ok_or(Error::InvalidState)?; + let data = data + .map(|data| data.to_vec()) + .unwrap_or_else(|| vec![0; size.area() as usize * 4]); + (data, size) + }, + CanvasImageSource::CSSStyleValue(ref value) => value + .get_url(self.base_url.clone()) + .and_then(|url| self.fetch_image_data(url)) + .ok_or(Error::InvalidState)?, + }; + + if repetition.is_empty() { + repetition.push_str("repeat"); + } + + if let Ok(rep) = RepetitionStyle::from_str(&repetition) { + Ok(CanvasPattern::new( + global, + image_data, + image_size, + rep, + self.is_origin_clean(image), + )) + } else { + Err(Error::Syntax) + } + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-save + pub fn Save(&self) { + self.saved_states + .borrow_mut() + .push(self.state.borrow().clone()); + self.send_canvas_2d_msg(Canvas2dMsg::SaveContext); + } + + #[allow(unrooted_must_root)] + // https://html.spec.whatwg.org/multipage/#dom-context-2d-restore + pub fn Restore(&self) { + let mut saved_states = self.saved_states.borrow_mut(); + if let Some(state) = saved_states.pop() { + self.state.borrow_mut().clone_from(&state); + self.send_canvas_2d_msg(Canvas2dMsg::RestoreContext); + } + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha + pub fn GlobalAlpha(&self) -> f64 { + self.state.borrow().global_alpha + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha + pub fn SetGlobalAlpha(&self, alpha: f64) { + if !alpha.is_finite() || alpha > 1.0 || alpha < 0.0 { + return; + } + + self.state.borrow_mut().global_alpha = alpha; + self.send_canvas_2d_msg(Canvas2dMsg::SetGlobalAlpha(alpha as f32)) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation + pub fn GlobalCompositeOperation(&self) -> DOMString { + match self.state.borrow().global_composition { + CompositionOrBlending::Composition(op) => DOMString::from(op.to_str()), + CompositionOrBlending::Blending(op) => DOMString::from(op.to_str()), + } + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation + pub fn SetGlobalCompositeOperation(&self, op_str: DOMString) { + if let Ok(op) = CompositionOrBlending::from_str(&op_str) { + self.state.borrow_mut().global_composition = op; + self.send_canvas_2d_msg(Canvas2dMsg::SetGlobalComposition(op)) + } + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-imagesmoothingenabled + pub fn ImageSmoothingEnabled(&self) -> bool { + self.state.borrow().image_smoothing_enabled + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-imagesmoothingenabled + pub fn SetImageSmoothingEnabled(&self, value: bool) { + self.state.borrow_mut().image_smoothing_enabled = value; + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-filltext + pub fn FillText(&self, text: DOMString, x: f64, y: f64, max_width: Option) { + let parsed_text: String = text.into(); + self.send_canvas_2d_msg(Canvas2dMsg::FillText(parsed_text, x, y, max_width)); + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth + pub fn LineWidth(&self) -> f64 { + self.state.borrow().line_width + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth + pub fn SetLineWidth(&self, width: f64) { + if !width.is_finite() || width <= 0.0 { + return; + } + + self.state.borrow_mut().line_width = width; + self.send_canvas_2d_msg(Canvas2dMsg::SetLineWidth(width as f32)) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap + pub fn LineCap(&self) -> CanvasLineCap { + match self.state.borrow().line_cap { + LineCapStyle::Butt => CanvasLineCap::Butt, + LineCapStyle::Round => CanvasLineCap::Round, + LineCapStyle::Square => CanvasLineCap::Square, + } + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap + pub fn SetLineCap(&self, cap: CanvasLineCap) { + let line_cap = match cap { + CanvasLineCap::Butt => LineCapStyle::Butt, + CanvasLineCap::Round => LineCapStyle::Round, + CanvasLineCap::Square => LineCapStyle::Square, + }; + self.state.borrow_mut().line_cap = line_cap; + self.send_canvas_2d_msg(Canvas2dMsg::SetLineCap(line_cap)); + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin + pub fn LineJoin(&self) -> CanvasLineJoin { + match self.state.borrow().line_join { + LineJoinStyle::Round => CanvasLineJoin::Round, + LineJoinStyle::Bevel => CanvasLineJoin::Bevel, + LineJoinStyle::Miter => CanvasLineJoin::Miter, + } + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin + pub fn SetLineJoin(&self, join: CanvasLineJoin) { + let line_join = match join { + CanvasLineJoin::Round => LineJoinStyle::Round, + CanvasLineJoin::Bevel => LineJoinStyle::Bevel, + CanvasLineJoin::Miter => LineJoinStyle::Miter, + }; + self.state.borrow_mut().line_join = line_join; + self.send_canvas_2d_msg(Canvas2dMsg::SetLineJoin(line_join)); + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit + pub fn MiterLimit(&self) -> f64 { + self.state.borrow().miter_limit + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit + pub fn SetMiterLimit(&self, limit: f64) { + if !limit.is_finite() || limit <= 0.0 { + return; + } + + self.state.borrow_mut().miter_limit = limit; + self.send_canvas_2d_msg(Canvas2dMsg::SetMiterLimit(limit as f32)) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata + pub fn CreateImageData( + &self, + global: &GlobalScope, + sw: i32, + sh: i32, + ) -> Fallible> { + if sw == 0 || sh == 0 { + return Err(Error::IndexSize); + } + ImageData::new(global, sw.abs() as u32, sh.abs() as u32, None) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata + pub fn CreateImageData_( + &self, + global: &GlobalScope, + imagedata: &ImageData, + ) -> Fallible> { + ImageData::new(global, imagedata.Width(), imagedata.Height(), None) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata + pub fn GetImageData( + &self, + canvas: Option<&HTMLCanvasElement>, + global: &GlobalScope, + sx: i32, + sy: i32, + sw: i32, + sh: i32, + ) -> Fallible> { + // FIXME(nox): There are many arithmetic operations here that can + // overflow or underflow, this should probably be audited. + + if sw == 0 || sh == 0 { + return Err(Error::IndexSize); + } + + if !self.origin_is_clean() { + return Err(Error::Security); + } + + let (origin, size) = adjust_size_sign(Point2D::new(sx, sy), Size2D::new(sw, sh)); + // FIXME(nox): This is probably wrong when this is a context for an + // offscreen canvas. + let canvas_size = canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()); + let read_rect = match pixels::clip(origin, size, canvas_size) { + Some(rect) => rect, + None => { + // All the pixels are outside the canvas surface. + return ImageData::new(global, size.width, size.height, None); + }, + }; + + ImageData::new( + global, + size.width, + size.height, + Some(self.get_rect(canvas, read_rect)), + ) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata + pub fn PutImageData( + &self, + canvas: Option<&HTMLCanvasElement>, + imagedata: &ImageData, + dx: i32, + dy: i32, + ) { + self.PutImageData_( + canvas, + imagedata, + dx, + dy, + 0, + 0, + imagedata.Width() as i32, + imagedata.Height() as i32, + ) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata + #[allow(unsafe_code)] + pub fn PutImageData_( + &self, + canvas: Option<&HTMLCanvasElement>, + imagedata: &ImageData, + dx: i32, + dy: i32, + dirty_x: i32, + dirty_y: i32, + dirty_width: i32, + dirty_height: i32, + ) { + // FIXME(nox): There are many arithmetic operations here that can + // overflow or underflow, this should probably be audited. + + let imagedata_size = Size2D::new(imagedata.Width(), imagedata.Height()); + if imagedata_size.area() == 0 { + return; + } + + // Step 1. + // Done later. + + // Step 2. + // TODO: throw InvalidState if buffer is detached. + + // FIXME(nox): This is probably wrong when this is a context for an + // offscreen canvas. + let canvas_size = canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()); + + // Steps 3-6. + let (src_origin, src_size) = adjust_size_sign( + Point2D::new(dirty_x, dirty_y), + Size2D::new(dirty_width, dirty_height), + ); + let src_rect = match pixels::clip(src_origin, src_size, imagedata_size) { + Some(rect) => rect, + None => return, + }; + let (dst_origin, _) = adjust_size_sign( + Point2D::new(dirty_x.saturating_add(dx), dirty_y.saturating_add(dy)), + Size2D::new(dirty_width, dirty_height), + ); + // By clipping to the canvas surface, we avoid sending any pixel + // that would fall outside it. + let dst_rect = match pixels::clip(dst_origin, src_rect.size, canvas_size) { + Some(rect) => rect, + None => return, + }; + + // Step 7. + let (sender, receiver) = ipc::bytes_channel().unwrap(); + let pixels = unsafe { &imagedata.get_rect(Rect::new(src_rect.origin, dst_rect.size)) }; + self.send_canvas_2d_msg(Canvas2dMsg::PutImageData(dst_rect, receiver)); + sender.send(pixels).unwrap(); + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage + pub fn DrawImage( + &self, + canvas: Option<&HTMLCanvasElement>, + image: CanvasImageSource, + dx: f64, + dy: f64, + ) -> ErrorResult { + if !(dx.is_finite() && dy.is_finite()) { + return Ok(()); + } + + self.draw_image(canvas, image, 0f64, 0f64, None, None, dx, dy, None, None) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage + pub fn DrawImage_( + &self, + canvas: Option<&HTMLCanvasElement>, + image: CanvasImageSource, + dx: f64, + dy: f64, + dw: f64, + dh: f64, + ) -> ErrorResult { + if !(dx.is_finite() && dy.is_finite() && dw.is_finite() && dh.is_finite()) { + return Ok(()); + } + + self.draw_image( + canvas, + image, + 0f64, + 0f64, + None, + None, + dx, + dy, + Some(dw), + Some(dh), + ) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage + pub fn DrawImage__( + &self, + canvas: Option<&HTMLCanvasElement>, + image: CanvasImageSource, + sx: f64, + sy: f64, + sw: f64, + sh: f64, + dx: f64, + dy: f64, + dw: f64, + dh: f64, + ) -> ErrorResult { + if !(sx.is_finite() && + sy.is_finite() && + sw.is_finite() && + sh.is_finite() && + dx.is_finite() && + dy.is_finite() && + dw.is_finite() && + dh.is_finite()) + { + return Ok(()); + } + + self.draw_image( + canvas, + image, + sx, + sy, + Some(sw), + Some(sh), + dx, + dy, + Some(dw), + Some(dh), + ) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-beginpath + pub fn BeginPath(&self) { + self.send_canvas_2d_msg(Canvas2dMsg::BeginPath); + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-fill + pub fn Fill(&self, _fill_rule: CanvasFillRule) { + // TODO: Process fill rule + self.send_canvas_2d_msg(Canvas2dMsg::Fill); + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-stroke + pub fn Stroke(&self) { + self.send_canvas_2d_msg(Canvas2dMsg::Stroke); + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-clip + pub fn Clip(&self, _fill_rule: CanvasFillRule) { + // TODO: Process fill rule + self.send_canvas_2d_msg(Canvas2dMsg::Clip); + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-ispointinpath + pub fn IsPointInPath( + &self, + global: &GlobalScope, + x: f64, + y: f64, + fill_rule: CanvasFillRule, + ) -> bool { + let fill_rule = match fill_rule { + CanvasFillRule::Nonzero => FillRule::Nonzero, + CanvasFillRule::Evenodd => FillRule::Evenodd, + }; + let (sender, receiver) = + profiled_ipc::channel::(global.time_profiler_chan().clone()).unwrap(); + self.send_canvas_2d_msg(Canvas2dMsg::IsPointInPath(x, y, fill_rule, sender)); + receiver.recv().unwrap() + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-scale + pub fn Scale(&self, x: f64, y: f64) { + if !(x.is_finite() && y.is_finite()) { + return; + } + + let transform = self.state.borrow().transform; + self.state.borrow_mut().transform = transform.pre_scale(x as f32, y as f32); + self.update_transform() + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-rotate + pub fn Rotate(&self, angle: f64) { + if angle == 0.0 || !angle.is_finite() { + return; + } + + let (sin, cos) = (angle.sin(), angle.cos()); + let transform = self.state.borrow().transform; + self.state.borrow_mut().transform = transform.pre_mul(&Transform2D::row_major( + cos as f32, + sin as f32, + -sin as f32, + cos as f32, + 0.0, + 0.0, + )); + self.update_transform() + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-translate + pub fn Translate(&self, x: f64, y: f64) { + if !(x.is_finite() && y.is_finite()) { + return; + } + + let transform = self.state.borrow().transform; + self.state.borrow_mut().transform = transform.pre_translate(vec2(x as f32, y as f32)); + self.update_transform() + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-transform + pub fn Transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) { + if !(a.is_finite() && + b.is_finite() && + c.is_finite() && + d.is_finite() && + e.is_finite() && + f.is_finite()) + { + return; + } + + let transform = self.state.borrow().transform; + self.state.borrow_mut().transform = transform.pre_mul(&Transform2D::row_major( + a as f32, b as f32, c as f32, d as f32, e as f32, f as f32, + )); + self.update_transform() + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-settransform + pub fn SetTransform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) { + if !(a.is_finite() && + b.is_finite() && + c.is_finite() && + d.is_finite() && + e.is_finite() && + f.is_finite()) + { + return; + } + + self.state.borrow_mut().transform = + Transform2D::row_major(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32); + self.update_transform() + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-resettransform + pub fn ResetTransform(&self) { + self.state.borrow_mut().transform = Transform2D::identity(); + self.update_transform() + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-closepath + pub fn ClosePath(&self) { + self.send_canvas_2d_msg(Canvas2dMsg::ClosePath); + } - let image_size = Size2D::new(img.width, img.height); - let image_data = match img.format { - PixelFormat::BGRA8 => img.bytes.to_vec(), - pixel_format => unimplemented!("unsupported pixel format ({:?})", pixel_format), - }; + // https://html.spec.whatwg.org/multipage/#dom-context-2d-moveto + pub fn MoveTo(&self, x: f64, y: f64) { + if !(x.is_finite() && y.is_finite()) { + return; + } + self.send_canvas_2d_msg(Canvas2dMsg::MoveTo(Point2D::new(x as f32, y as f32))); + } - Some((image_data, image_size)) + // https://html.spec.whatwg.org/multipage/#dom-context-2d-lineto + pub fn LineTo(&self, x: f64, y: f64) { + if !(x.is_finite() && y.is_finite()) { + return; + } + self.send_canvas_2d_msg(Canvas2dMsg::LineTo(Point2D::new(x as f32, y as f32))); } - #[inline] - fn request_image_from_cache(&self, url: ServoUrl) -> ImageResponse { - let response = self.image_cache.find_image_or_metadata( - url.clone(), - UsePlaceholder::No, - CanRequestImages::No, - ); - match response { - Ok(ImageOrMetadataAvailable::ImageAvailable(image, url)) => { - ImageResponse::Loaded(image, url) - }, - Err(ImageState::Pending(_)) => ImageResponse::None, - _ => { - // Rather annoyingly, we get the same response back from - // A load which really failed and from a load which hasn't started yet. - self.missing_image_urls.borrow_mut().push(url); - ImageResponse::None - }, + // https://html.spec.whatwg.org/multipage/#dom-context-2d-rect + pub fn Rect(&self, x: f64, y: f64, width: f64, height: f64) { + if [x, y, width, height].iter().all(|val| val.is_finite()) { + let rect = Rect::new( + Point2D::new(x as f32, y as f32), + Size2D::new(width as f32, height as f32), + ); + self.send_canvas_2d_msg(Canvas2dMsg::Rect(rect)); } } - pub fn take_missing_image_urls(&self) -> Vec { - mem::replace(&mut self.missing_image_urls.borrow_mut(), vec![]) + // https://html.spec.whatwg.org/multipage/#dom-context-2d-quadraticcurveto + pub fn QuadraticCurveTo(&self, cpx: f64, cpy: f64, x: f64, y: f64) { + if !(cpx.is_finite() && cpy.is_finite() && x.is_finite() && y.is_finite()) { + return; + } + self.send_canvas_2d_msg(Canvas2dMsg::QuadraticCurveTo( + Point2D::new(cpx as f32, cpy as f32), + Point2D::new(x as f32, y as f32), + )); } - fn parse_color(&self, string: &str) -> Result { - let mut input = ParserInput::new(string); - let mut parser = Parser::new(&mut input); - let color = CSSColor::parse(&mut parser); - if parser.is_exhausted() { - match color { - Ok(CSSColor::RGBA(rgba)) => Ok(rgba), - Ok(CSSColor::CurrentColor) => { - // TODO: https://github.com/whatwg/html/issues/1099 - // Reconsider how to calculate currentColor in a display:none canvas + // https://html.spec.whatwg.org/multipage/#dom-context-2d-beziercurveto + pub fn BezierCurveTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) { + if !(cp1x.is_finite() && + cp1y.is_finite() && + cp2x.is_finite() && + cp2y.is_finite() && + x.is_finite() && + y.is_finite()) + { + return; + } + self.send_canvas_2d_msg(Canvas2dMsg::BezierCurveTo( + Point2D::new(cp1x as f32, cp1y as f32), + Point2D::new(cp2x as f32, cp2y as f32), + Point2D::new(x as f32, y as f32), + )); + } - // TODO: will need to check that the context bitmap mode is fixed - // once we implement CanvasProxy - let canvas = match self.canvas { - // https://drafts.css-houdini.org/css-paint-api/#2d-rendering-context - // Whenever "currentColor" is used as a color in the PaintRenderingContext2D API, - // it is treated as opaque black. - None => return Ok(RGBA::new(0, 0, 0, 255)), - Some(ref canvas) => &**canvas, - }; + // https://html.spec.whatwg.org/multipage/#dom-context-2d-arc + pub fn Arc(&self, x: f64, y: f64, r: f64, start: f64, end: f64, ccw: bool) -> ErrorResult { + if !([x, y, r, start, end].iter().all(|x| x.is_finite())) { + return Ok(()); + } - let canvas_element = canvas.upcast::(); + if r < 0.0 { + return Err(Error::IndexSize); + } - match canvas_element.style() { - Some(ref s) if canvas_element.has_css_layout_box() => { - Ok(s.get_color().color) - }, - _ => Ok(RGBA::new(0, 0, 0, 255)), - } - }, - _ => Err(()), - } - } else { - Err(()) + self.send_canvas_2d_msg(Canvas2dMsg::Arc( + Point2D::new(x as f32, y as f32), + r as f32, + start as f32, + end as f32, + ccw, + )); + Ok(()) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-arcto + pub fn ArcTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, r: f64) -> ErrorResult { + if !([cp1x, cp1y, cp2x, cp2y, r].iter().all(|x| x.is_finite())) { + return Ok(()); + } + if r < 0.0 { + return Err(Error::IndexSize); + } + + self.send_canvas_2d_msg(Canvas2dMsg::ArcTo( + Point2D::new(cp1x as f32, cp1y as f32), + Point2D::new(cp2x as f32, cp2y as f32), + r as f32, + )); + Ok(()) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-ellipse + pub fn Ellipse( + &self, + x: f64, + y: f64, + rx: f64, + ry: f64, + rotation: f64, + start: f64, + end: f64, + ccw: bool, + ) -> ErrorResult { + if !([x, y, rx, ry, rotation, start, end] + .iter() + .all(|x| x.is_finite())) + { + return Ok(()); + } + if rx < 0.0 || ry < 0.0 { + return Err(Error::IndexSize); + } + + self.send_canvas_2d_msg(Canvas2dMsg::Ellipse( + Point2D::new(x as f32, y as f32), + rx as f32, + ry as f32, + rotation as f32, + start as f32, + end as f32, + ccw, + )); + Ok(()) + } +} + +impl CanvasRenderingContext2D { + pub fn new_inherited( + global: &GlobalScope, + canvas: Option<&HTMLCanvasElement>, + size: Size2D, + ) -> CanvasRenderingContext2D { + CanvasRenderingContext2D { + reflector_: Reflector::new(), + canvas: canvas.map(Dom::from_ref), + canvas_state: DomRefCell::new(CanvasState::new( + global, + Size2D::new(size.width as u64, size.height as u64), + )), } } + pub fn new( + global: &GlobalScope, + canvas: &HTMLCanvasElement, + size: Size2D, + ) -> DomRoot { + let boxed = Box::new(CanvasRenderingContext2D::new_inherited( + global, + Some(canvas), + size, + )); + reflect_dom_object(boxed, global, CanvasRenderingContext2DBinding::Wrap) + } + + // https://html.spec.whatwg.org/multipage/#concept-canvas-set-bitmap-dimensions + pub fn set_bitmap_dimensions(&self, size: Size2D) { + self.reset_to_initial_state(); + self.canvas_state + .borrow() + .ipc_renderer + .send(CanvasMsg::Recreate( + size, + self.canvas_state.borrow().get_canvas_id(), + )) + .unwrap(); + } + + // https://html.spec.whatwg.org/multipage/#reset-the-rendering-context-to-its-default-state + fn reset_to_initial_state(&self) { + self.canvas_state.borrow().saved_states.borrow_mut().clear(); + *self.canvas_state.borrow().state.borrow_mut() = CanvasContextState::new(); + } + + fn mark_as_dirty(&self) { + self.canvas_state + .borrow() + .mark_as_dirty(self.canvas.as_ref().map(|c| &**c)) + } + + pub fn take_missing_image_urls(&self) -> Vec { + mem::replace( + &mut self.canvas_state.borrow().missing_image_urls.borrow_mut(), + vec![], + ) + } + pub fn get_canvas_id(&self) -> CanvasId { self.canvas_state.borrow().get_canvas_id() } @@ -592,36 +1494,13 @@ impl CanvasRenderingContext2D { } pub fn origin_is_clean(&self) -> bool { - self.origin_clean.get() - } - - fn set_origin_unclean(&self) { - self.origin_clean.set(false) + self.canvas_state.borrow().origin_is_clean() } pub fn get_rect(&self, rect: Rect) -> Vec { - assert!(self.origin_is_clean()); - - // FIXME(nox): This is probably wrong when this is a context for an - // offscreen canvas. - let canvas_size = self - .canvas - .as_ref() - .map_or(Size2D::zero(), |c| c.get_size()); - assert!(Rect::from_size(canvas_size).contains_rect(&rect)); - - let (sender, receiver) = ipc::bytes_channel().unwrap(); - self.send_canvas_2d_msg(Canvas2dMsg::GetImageData(rect, canvas_size, sender)); - let mut pixels = receiver.recv().unwrap().to_vec(); - - for chunk in pixels.chunks_mut(4) { - let b = chunk[0]; - chunk[0] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + chunk[2] as usize]; - chunk[1] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + chunk[1] as usize]; - chunk[2] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + b as usize]; - } - - pixels + self.canvas_state + .borrow() + .get_rect(self.canvas.as_ref().map(|c| &**c), rect) } } @@ -670,136 +1549,65 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-save fn Save(&self) { - self.saved_states - .borrow_mut() - .push(self.state.borrow().clone()); - self.send_canvas_2d_msg(Canvas2dMsg::SaveContext); + self.canvas_state.borrow().Save() } #[allow(unrooted_must_root)] // https://html.spec.whatwg.org/multipage/#dom-context-2d-restore fn Restore(&self) { - let mut saved_states = self.saved_states.borrow_mut(); - if let Some(state) = saved_states.pop() { - self.state.borrow_mut().clone_from(&state); - self.send_canvas_2d_msg(Canvas2dMsg::RestoreContext); - } + self.canvas_state.borrow().Restore() } - // https://html.spec.whatwg.org/multipage/#dom-context-2d-scale - fn Scale(&self, x: f64, y: f64) { - if !(x.is_finite() && y.is_finite()) { - return; - } - - let transform = self.state.borrow().transform; - self.state.borrow_mut().transform = transform.pre_scale(x as f32, y as f32); - self.update_transform() + // https://html.spec.whatwg.org/multipage/#dom-context-2d-scale + fn Scale(&self, x: f64, y: f64) { + self.canvas_state.borrow().Scale(x, y) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-rotate fn Rotate(&self, angle: f64) { - if angle == 0.0 || !angle.is_finite() { - return; - } - - let (sin, cos) = (angle.sin(), angle.cos()); - let transform = self.state.borrow().transform; - self.state.borrow_mut().transform = transform.pre_mul(&Transform2D::row_major( - cos as f32, - sin as f32, - -sin as f32, - cos as f32, - 0.0, - 0.0, - )); - self.update_transform() + self.canvas_state.borrow().Rotate(angle) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-translate fn Translate(&self, x: f64, y: f64) { - if !(x.is_finite() && y.is_finite()) { - return; - } - - let transform = self.state.borrow().transform; - self.state.borrow_mut().transform = transform.pre_translate(vec2(x as f32, y as f32)); - self.update_transform() + self.canvas_state.borrow().Translate(x, y) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-transform fn Transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) { - if !(a.is_finite() && - b.is_finite() && - c.is_finite() && - d.is_finite() && - e.is_finite() && - f.is_finite()) - { - return; - } - - let transform = self.state.borrow().transform; - self.state.borrow_mut().transform = transform.pre_mul(&Transform2D::row_major( - a as f32, b as f32, c as f32, d as f32, e as f32, f as f32, - )); - self.update_transform() + self.canvas_state.borrow().Transform(a, b, c, d, e, f) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-settransform fn SetTransform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) { - if !(a.is_finite() && - b.is_finite() && - c.is_finite() && - d.is_finite() && - e.is_finite() && - f.is_finite()) - { - return; - } - - self.state.borrow_mut().transform = - Transform2D::row_major(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32); - self.update_transform() + self.canvas_state.borrow().SetTransform(a, b, c, d, e, f) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-resettransform fn ResetTransform(&self) { - self.state.borrow_mut().transform = Transform2D::identity(); - self.update_transform() + self.canvas_state.borrow().ResetTransform() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha fn GlobalAlpha(&self) -> f64 { - let state = self.state.borrow(); - state.global_alpha + self.canvas_state.borrow().GlobalAlpha() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha fn SetGlobalAlpha(&self, alpha: f64) { - if !alpha.is_finite() || alpha > 1.0 || alpha < 0.0 { - return; - } - - self.state.borrow_mut().global_alpha = alpha; - self.send_canvas_2d_msg(Canvas2dMsg::SetGlobalAlpha(alpha as f32)) + self.canvas_state.borrow().SetGlobalAlpha(alpha) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation fn GlobalCompositeOperation(&self) -> DOMString { - let state = self.state.borrow(); - match state.global_composition { - CompositionOrBlending::Composition(op) => DOMString::from(op.to_str()), - CompositionOrBlending::Blending(op) => DOMString::from(op.to_str()), - } + self.canvas_state.borrow().GlobalCompositeOperation() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation fn SetGlobalCompositeOperation(&self, op_str: DOMString) { - if let Ok(op) = CompositionOrBlending::from_str(&op_str) { - self.state.borrow_mut().global_composition = op; - self.send_canvas_2d_msg(Canvas2dMsg::SetGlobalComposition(op)) - } + self.canvas_state + .borrow() + .SetGlobalCompositeOperation(op_str) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect @@ -822,59 +1630,49 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-beginpath fn BeginPath(&self) { - self.send_canvas_2d_msg(Canvas2dMsg::BeginPath); + self.canvas_state.borrow().BeginPath() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-closepath fn ClosePath(&self) { - self.send_canvas_2d_msg(Canvas2dMsg::ClosePath); + self.canvas_state.borrow().ClosePath() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-fill - fn Fill(&self, _: CanvasFillRule) { - // TODO: Process fill rule - self.send_canvas_2d_msg(Canvas2dMsg::Fill); + fn Fill(&self, fill_rule: CanvasFillRule) { + self.canvas_state.borrow().Fill(fill_rule); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-stroke fn Stroke(&self) { - self.send_canvas_2d_msg(Canvas2dMsg::Stroke); + self.canvas_state.borrow().Stroke(); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-clip - fn Clip(&self, _: CanvasFillRule) { - // TODO: Process fill rule - self.send_canvas_2d_msg(Canvas2dMsg::Clip); + fn Clip(&self, fill_rule: CanvasFillRule) { + self.canvas_state.borrow().Clip(fill_rule) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-ispointinpath fn IsPointInPath(&self, x: f64, y: f64, fill_rule: CanvasFillRule) -> bool { - let fill_rule = match fill_rule { - CanvasFillRule::Nonzero => FillRule::Nonzero, - CanvasFillRule::Evenodd => FillRule::Evenodd, - }; - let (sender, receiver) = - profiled_ipc::channel::(self.global().time_profiler_chan().clone()).unwrap(); - self.send_canvas_2d_msg(Canvas2dMsg::IsPointInPath(x, y, fill_rule, sender)); - receiver.recv().unwrap() + self.canvas_state + .borrow() + .IsPointInPath(&self.global(), x, y, fill_rule) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-filltext fn FillText(&self, text: DOMString, x: f64, y: f64, max_width: Option) { - let parsed_text: String = text.into(); - self.send_canvas_2d_msg(Canvas2dMsg::FillText(parsed_text, x, y, max_width)); + self.canvas_state.borrow().FillText(text, x, y, max_width); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage fn DrawImage(&self, image: CanvasImageSource, dx: f64, dy: f64) -> ErrorResult { - if !(dx.is_finite() && dy.is_finite()) { - return Ok(()); - } - - self.draw_image(image, 0f64, 0f64, None, None, dx, dy, None, None) + self.canvas_state + .borrow() + .DrawImage(self.canvas.as_ref().map(|c| &**c), image, dx, dy) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage @@ -886,11 +1684,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { dw: f64, dh: f64, ) -> ErrorResult { - if !(dx.is_finite() && dy.is_finite() && dw.is_finite() && dh.is_finite()) { - return Ok(()); - } - - self.draw_image(image, 0f64, 0f64, None, None, dx, dy, Some(dw), Some(dh)) + self.canvas_state.borrow().DrawImage_( + self.canvas.as_ref().map(|c| &**c), + image, + dx, + dy, + dw, + dh, + ) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage @@ -906,122 +1707,55 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { dw: f64, dh: f64, ) -> ErrorResult { - if !(sx.is_finite() && - sy.is_finite() && - sw.is_finite() && - sh.is_finite() && - dx.is_finite() && - dy.is_finite() && - dw.is_finite() && - dh.is_finite()) - { - return Ok(()); - } - - self.draw_image( + self.canvas_state.borrow().DrawImage__( + self.canvas.as_ref().map(|c| &**c), image, sx, sy, - Some(sw), - Some(sh), + sw, + sh, dx, dy, - Some(dw), - Some(dh), + dw, + dh, ) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-moveto fn MoveTo(&self, x: f64, y: f64) { - if !(x.is_finite() && y.is_finite()) { - return; - } - self.send_canvas_2d_msg(Canvas2dMsg::MoveTo(Point2D::new(x as f32, y as f32))); + self.canvas_state.borrow().MoveTo(x, y) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-lineto fn LineTo(&self, x: f64, y: f64) { - if !(x.is_finite() && y.is_finite()) { - return; - } - self.send_canvas_2d_msg(Canvas2dMsg::LineTo(Point2D::new(x as f32, y as f32))); + self.canvas_state.borrow().LineTo(x, y) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-rect fn Rect(&self, x: f64, y: f64, width: f64, height: f64) { - if [x, y, width, height].iter().all(|val| val.is_finite()) { - let rect = Rect::new( - Point2D::new(x as f32, y as f32), - Size2D::new(width as f32, height as f32), - ); - self.send_canvas_2d_msg(Canvas2dMsg::Rect(rect)); - } + self.canvas_state.borrow().Rect(x, y, width, height) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-quadraticcurveto fn QuadraticCurveTo(&self, cpx: f64, cpy: f64, x: f64, y: f64) { - if !(cpx.is_finite() && cpy.is_finite() && x.is_finite() && y.is_finite()) { - return; - } - self.send_canvas_2d_msg(Canvas2dMsg::QuadraticCurveTo( - Point2D::new(cpx as f32, cpy as f32), - Point2D::new(x as f32, y as f32), - )); + self.canvas_state.borrow().QuadraticCurveTo(cpx, cpy, x, y) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-beziercurveto fn BezierCurveTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) { - if !(cp1x.is_finite() && - cp1y.is_finite() && - cp2x.is_finite() && - cp2y.is_finite() && - x.is_finite() && - y.is_finite()) - { - return; - } - self.send_canvas_2d_msg(Canvas2dMsg::BezierCurveTo( - Point2D::new(cp1x as f32, cp1y as f32), - Point2D::new(cp2x as f32, cp2y as f32), - Point2D::new(x as f32, y as f32), - )); + self.canvas_state + .borrow() + .BezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-arc fn Arc(&self, x: f64, y: f64, r: f64, start: f64, end: f64, ccw: bool) -> ErrorResult { - if !([x, y, r, start, end].iter().all(|x| x.is_finite())) { - return Ok(()); - } - - if r < 0.0 { - return Err(Error::IndexSize); - } - - self.send_canvas_2d_msg(Canvas2dMsg::Arc( - Point2D::new(x as f32, y as f32), - r as f32, - start as f32, - end as f32, - ccw, - )); - Ok(()) + self.canvas_state.borrow().Arc(x, y, r, start, end, ccw) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-arcto fn ArcTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, r: f64) -> ErrorResult { - if !([cp1x, cp1y, cp2x, cp2y, r].iter().all(|x| x.is_finite())) { - return Ok(()); - } - if r < 0.0 { - return Err(Error::IndexSize); - } - - self.send_canvas_2d_msg(Canvas2dMsg::ArcTo( - Point2D::new(cp1x as f32, cp1y as f32), - Point2D::new(cp2x as f32, cp2y as f32), - r as f32, - )); - Ok(()) + self.canvas_state.borrow().ArcTo(cp1x, cp1y, cp2x, cp2y, r) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-ellipse @@ -1036,194 +1770,78 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { end: f64, ccw: bool, ) -> ErrorResult { - if !([x, y, rx, ry, rotation, start, end] - .iter() - .all(|x| x.is_finite())) - { - return Ok(()); - } - if rx < 0.0 || ry < 0.0 { - return Err(Error::IndexSize); - } - - self.send_canvas_2d_msg(Canvas2dMsg::Ellipse( - Point2D::new(x as f32, y as f32), - rx as f32, - ry as f32, - rotation as f32, - start as f32, - end as f32, - ccw, - )); - Ok(()) + self.canvas_state + .borrow() + .Ellipse(x, y, rx, ry, rotation, start, end, ccw) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-imagesmoothingenabled fn ImageSmoothingEnabled(&self) -> bool { - let state = self.state.borrow(); - state.image_smoothing_enabled + self.canvas_state.borrow().ImageSmoothingEnabled() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-imagesmoothingenabled fn SetImageSmoothingEnabled(&self, value: bool) { - self.state.borrow_mut().image_smoothing_enabled = value; - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle - fn StrokeStyle(&self) -> StringOrCanvasGradientOrCanvasPattern { - match self.state.borrow().stroke_style { - CanvasFillOrStrokeStyle::Color(ref rgba) => { - let mut result = String::new(); - serialize(rgba, &mut result).unwrap(); - StringOrCanvasGradientOrCanvasPattern::String(DOMString::from(result)) - }, - CanvasFillOrStrokeStyle::Gradient(ref gradient) => { - StringOrCanvasGradientOrCanvasPattern::CanvasGradient(DomRoot::from_ref(&*gradient)) - }, - CanvasFillOrStrokeStyle::Pattern(ref pattern) => { - StringOrCanvasGradientOrCanvasPattern::CanvasPattern(DomRoot::from_ref(&*pattern)) - }, - } + self.canvas_state.borrow().SetImageSmoothingEnabled(value) } - // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle - fn SetStrokeStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) { - match value { - StringOrCanvasGradientOrCanvasPattern::String(string) => { - if let Ok(rgba) = self.parse_color(&string) { - self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Color(rgba); - self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(FillOrStrokeStyle::Color( - rgba, - ))); - } - }, - StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => { - self.state.borrow_mut().stroke_style = - CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient)); - self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle( - gradient.to_fill_or_stroke_style(), - )); - }, - StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => { - self.state.borrow_mut().stroke_style = - CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern)); - self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle( - pattern.to_fill_or_stroke_style(), - )); - if !pattern.origin_is_clean() { - self.set_origin_unclean(); - } - }, - } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle + fn StrokeStyle(&self) -> StringOrCanvasGradientOrCanvasPattern { + self.canvas_state.borrow().StrokeStyle() + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle + fn SetStrokeStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) { + self.canvas_state + .borrow() + .SetStrokeStyle(self.canvas.as_ref().map(|c| &**c), value) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle fn FillStyle(&self) -> StringOrCanvasGradientOrCanvasPattern { - match self.state.borrow().fill_style { - CanvasFillOrStrokeStyle::Color(ref rgba) => { - let mut result = String::new(); - serialize(rgba, &mut result).unwrap(); - StringOrCanvasGradientOrCanvasPattern::String(DOMString::from(result)) - }, - CanvasFillOrStrokeStyle::Gradient(ref gradient) => { - StringOrCanvasGradientOrCanvasPattern::CanvasGradient(DomRoot::from_ref(&*gradient)) - }, - CanvasFillOrStrokeStyle::Pattern(ref pattern) => { - StringOrCanvasGradientOrCanvasPattern::CanvasPattern(DomRoot::from_ref(&*pattern)) - }, - } + self.canvas_state.borrow().FillStyle() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle fn SetFillStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) { - match value { - StringOrCanvasGradientOrCanvasPattern::String(string) => { - if let Ok(rgba) = self.parse_color(&string) { - self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Color(rgba); - self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(FillOrStrokeStyle::Color( - rgba, - ))) - } - }, - StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => { - self.state.borrow_mut().fill_style = - CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient)); - self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle( - gradient.to_fill_or_stroke_style(), - )); - }, - StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => { - self.state.borrow_mut().fill_style = - CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern)); - self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle( - pattern.to_fill_or_stroke_style(), - )); - if !pattern.origin_is_clean() { - self.set_origin_unclean(); - } - }, - } + self.canvas_state + .borrow() + .SetFillStyle(self.canvas.as_ref().map(|c| &**c), value) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata fn CreateImageData(&self, sw: i32, sh: i32) -> Fallible> { - if sw == 0 || sh == 0 { - return Err(Error::IndexSize); - } - ImageData::new(&self.global(), sw.abs() as u32, sh.abs() as u32, None) + self.canvas_state + .borrow() + .CreateImageData(&self.global(), sw, sh) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata fn CreateImageData_(&self, imagedata: &ImageData) -> Fallible> { - ImageData::new(&self.global(), imagedata.Width(), imagedata.Height(), None) + self.canvas_state + .borrow() + .CreateImageData_(&self.global(), imagedata) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata fn GetImageData(&self, sx: i32, sy: i32, sw: i32, sh: i32) -> Fallible> { - // FIXME(nox): There are many arithmetic operations here that can - // overflow or underflow, this should probably be audited. - - if sw == 0 || sh == 0 { - return Err(Error::IndexSize); - } - - if !self.origin_is_clean() { - return Err(Error::Security); - } - - let (origin, size) = adjust_size_sign(Point2D::new(sx, sy), Size2D::new(sw, sh)); - // FIXME(nox): This is probably wrong when this is a context for an - // offscreen canvas. - let canvas_size = self - .canvas - .as_ref() - .map_or(Size2D::zero(), |c| c.get_size()); - let read_rect = match pixels::clip(origin, size, canvas_size) { - Some(rect) => rect, - None => { - // All the pixels are outside the canvas surface. - return ImageData::new(&self.global(), size.width, size.height, None); - }, - }; - - ImageData::new( + self.canvas_state.borrow().GetImageData( + self.canvas.as_ref().map(|c| &**c), &self.global(), - size.width, - size.height, - Some(self.get_rect(read_rect)), + sx, + sy, + sw, + sh, ) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata fn PutImageData(&self, imagedata: &ImageData, dx: i32, dy: i32) { - self.PutImageData_( + self.canvas_state.borrow().PutImageData( + self.canvas.as_ref().map(|c| &**c), imagedata, dx, dy, - 0, - 0, - imagedata.Width() as i32, - imagedata.Height() as i32, ) } @@ -1239,52 +1857,16 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { dirty_width: i32, dirty_height: i32, ) { - // FIXME(nox): There are many arithmetic operations here that can - // overflow or underflow, this should probably be audited. - - let imagedata_size = Size2D::new(imagedata.Width(), imagedata.Height()); - if imagedata_size.area() == 0 { - return; - } - - // Step 1. - // Done later. - - // Step 2. - // TODO: throw InvalidState if buffer is detached. - - // FIXME(nox): This is probably wrong when this is a context for an - // offscreen canvas. - let canvas_size = self - .canvas - .as_ref() - .map_or(Size2D::zero(), |c| c.get_size()); - - // Steps 3-6. - let (src_origin, src_size) = adjust_size_sign( - Point2D::new(dirty_x, dirty_y), - Size2D::new(dirty_width, dirty_height), - ); - let src_rect = match pixels::clip(src_origin, src_size, imagedata_size) { - Some(rect) => rect, - None => return, - }; - let (dst_origin, _) = adjust_size_sign( - Point2D::new(dirty_x.saturating_add(dx), dirty_y.saturating_add(dy)), - Size2D::new(dirty_width, dirty_height), + self.canvas_state.borrow().PutImageData_( + self.canvas.as_ref().map(|c| &**c), + imagedata, + dx, + dy, + dirty_x, + dirty_y, + dirty_width, + dirty_height, ); - // By clipping to the canvas surface, we avoid sending any pixel - // that would fall outside it. - let dst_rect = match pixels::clip(dst_origin, src_rect.size, canvas_size) { - Some(rect) => rect, - None => return, - }; - - // Step 7. - let (sender, receiver) = ipc::bytes_channel().unwrap(); - let pixels = unsafe { &imagedata.get_rect(Rect::new(src_rect.origin, dst_rect.size)) }; - self.send_canvas_2d_msg(Canvas2dMsg::PutImageData(dst_rect, receiver)); - sender.send(pixels).unwrap(); self.mark_as_dirty(); } @@ -1296,10 +1878,9 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { x1: Finite, y1: Finite, ) -> DomRoot { - CanvasGradient::new( - &self.global(), - CanvasGradientStyle::Linear(LinearGradientStyle::new(*x0, *y0, *x1, *y1, Vec::new())), - ) + self.canvas_state + .borrow() + .CreateLinearGradient(&self.global(), x0, y0, x1, y1) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createradialgradient @@ -1312,197 +1893,100 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { y1: Finite, r1: Finite, ) -> Fallible> { - if *r0 < 0. || *r1 < 0. { - return Err(Error::IndexSize); - } - - Ok(CanvasGradient::new( - &self.global(), - CanvasGradientStyle::Radial(RadialGradientStyle::new( - *x0, - *y0, - *r0, - *x1, - *y1, - *r1, - Vec::new(), - )), - )) + self.canvas_state + .borrow() + .CreateRadialGradient(&self.global(), x0, y0, r0, x1, y1, r1) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern fn CreatePattern( &self, image: CanvasImageSource, - mut repetition: DOMString, + repetition: DOMString, ) -> Fallible> { - let (image_data, image_size) = match image { - CanvasImageSource::HTMLImageElement(ref image) => { - // https://html.spec.whatwg.org/multipage/#img-error - // If the image argument is an HTMLImageElement object that is in the broken state, - // then throw an InvalidStateError exception - image - .get_url() - .and_then(|url| self.fetch_image_data(url)) - .ok_or(Error::InvalidState)? - }, - CanvasImageSource::HTMLCanvasElement(ref canvas) => { - let (data, size) = canvas.fetch_all_data().ok_or(Error::InvalidState)?; - let data = data - .map(|data| data.to_vec()) - .unwrap_or_else(|| vec![0; size.area() as usize * 4]); - (data, size) - }, - CanvasImageSource::CSSStyleValue(ref value) => value - .get_url(self.base_url.clone()) - .and_then(|url| self.fetch_image_data(url)) - .ok_or(Error::InvalidState)?, - }; - - if repetition.is_empty() { - repetition.push_str("repeat"); - } - - if let Ok(rep) = RepetitionStyle::from_str(&repetition) { - Ok(CanvasPattern::new( - &self.global(), - image_data, - image_size, - rep, - self.is_origin_clean(image), - )) - } else { - Err(Error::Syntax) - } + self.canvas_state + .borrow() + .CreatePattern(&self.global(), image, repetition) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth fn LineWidth(&self) -> f64 { - let state = self.state.borrow(); - state.line_width + self.canvas_state.borrow().LineWidth() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth fn SetLineWidth(&self, width: f64) { - if !width.is_finite() || width <= 0.0 { - return; - } - - self.state.borrow_mut().line_width = width; - self.send_canvas_2d_msg(Canvas2dMsg::SetLineWidth(width as f32)) + self.canvas_state.borrow().SetLineWidth(width) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap fn LineCap(&self) -> CanvasLineCap { - match self.state.borrow().line_cap { - LineCapStyle::Butt => CanvasLineCap::Butt, - LineCapStyle::Round => CanvasLineCap::Round, - LineCapStyle::Square => CanvasLineCap::Square, - } + self.canvas_state.borrow().LineCap() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap fn SetLineCap(&self, cap: CanvasLineCap) { - let line_cap = match cap { - CanvasLineCap::Butt => LineCapStyle::Butt, - CanvasLineCap::Round => LineCapStyle::Round, - CanvasLineCap::Square => LineCapStyle::Square, - }; - self.state.borrow_mut().line_cap = line_cap; - self.send_canvas_2d_msg(Canvas2dMsg::SetLineCap(line_cap)); + self.canvas_state.borrow().SetLineCap(cap) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin fn LineJoin(&self) -> CanvasLineJoin { - match self.state.borrow().line_join { - LineJoinStyle::Round => CanvasLineJoin::Round, - LineJoinStyle::Bevel => CanvasLineJoin::Bevel, - LineJoinStyle::Miter => CanvasLineJoin::Miter, - } + self.canvas_state.borrow().LineJoin() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin fn SetLineJoin(&self, join: CanvasLineJoin) { - let line_join = match join { - CanvasLineJoin::Round => LineJoinStyle::Round, - CanvasLineJoin::Bevel => LineJoinStyle::Bevel, - CanvasLineJoin::Miter => LineJoinStyle::Miter, - }; - self.state.borrow_mut().line_join = line_join; - self.send_canvas_2d_msg(Canvas2dMsg::SetLineJoin(line_join)); + self.canvas_state.borrow().SetLineJoin(join) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit fn MiterLimit(&self) -> f64 { - let state = self.state.borrow(); - state.miter_limit + self.canvas_state.borrow().MiterLimit() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit fn SetMiterLimit(&self, limit: f64) { - if !limit.is_finite() || limit <= 0.0 { - return; - } - - self.state.borrow_mut().miter_limit = limit; - self.send_canvas_2d_msg(Canvas2dMsg::SetMiterLimit(limit as f32)) + self.canvas_state.borrow().SetMiterLimit(limit) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx fn ShadowOffsetX(&self) -> f64 { - self.state.borrow().shadow_offset_x + self.canvas_state.borrow().ShadowOffsetX() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx fn SetShadowOffsetX(&self, value: f64) { - if !value.is_finite() || value == self.state.borrow().shadow_offset_x { - return; - } - self.state.borrow_mut().shadow_offset_x = value; - self.send_canvas_2d_msg(Canvas2dMsg::SetShadowOffsetX(value)) + self.canvas_state.borrow().SetShadowOffsetX(value) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety fn ShadowOffsetY(&self) -> f64 { - self.state.borrow().shadow_offset_y + self.canvas_state.borrow().ShadowOffsetY() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety fn SetShadowOffsetY(&self, value: f64) { - if !value.is_finite() || value == self.state.borrow().shadow_offset_y { - return; - } - self.state.borrow_mut().shadow_offset_y = value; - self.send_canvas_2d_msg(Canvas2dMsg::SetShadowOffsetY(value)) + self.canvas_state.borrow().SetShadowOffsetY(value) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur fn ShadowBlur(&self) -> f64 { - self.state.borrow().shadow_blur + self.canvas_state.borrow().ShadowBlur() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur fn SetShadowBlur(&self, value: f64) { - if !value.is_finite() || value < 0f64 || value == self.state.borrow().shadow_blur { - return; - } - self.state.borrow_mut().shadow_blur = value; - self.send_canvas_2d_msg(Canvas2dMsg::SetShadowBlur(value)) + self.canvas_state.borrow().SetShadowBlur(value) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor fn ShadowColor(&self) -> DOMString { - let mut result = String::new(); - serialize(&self.state.borrow().shadow_color, &mut result).unwrap(); - DOMString::from(result) + self.canvas_state.borrow().ShadowColor() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor fn SetShadowColor(&self, value: DOMString) { - if let Ok(color) = parse_color(&value) { - self.state.borrow_mut().shadow_color = color; - self.send_canvas_2d_msg(Canvas2dMsg::SetShadowColor(color)) - } + self.canvas_state.borrow().SetShadowColor(value) } } -- cgit v1.2.3 From 2e5078e9c50b58873b199297be5ccae672c14c6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 3 Jun 2019 08:44:57 -0400 Subject: layout: Fix servo build. --- components/script/dom/canvasrenderingcontext2d.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 2a26a1c5752..039ff1039f9 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -260,7 +260,7 @@ impl CanvasState { match canvas_element.style() { Some(ref s) if canvas_element.has_css_layout_box() => { - Ok(s.get_color().color) + Ok(s.get_inherited_text().color) }, _ => Ok(RGBA::new(0, 0, 0, 255)), } -- cgit v1.2.3 From 3d57c22e9cda982923dd184152d3f187910d7b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 Jul 2019 12:49:39 +0200 Subject: Update euclid. There are a few canvas2d-related dependencies that haven't updated, but they only use euclid internally so that's not blocking landing the rest of the changes. Given the size of this patch, I think it's useful to get this landed as-is. --- components/script/dom/canvasrenderingcontext2d.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 039ff1039f9..2a8f14295c0 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -32,7 +32,10 @@ use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle}; use cssparser::Color as CSSColor; use cssparser::{Parser, ParserInput, RGBA}; use dom_struct::dom_struct; -use euclid::{vec2, Point2D, Rect, Size2D, Transform2D}; +use euclid::{ + default::{Point2D, Rect, Size2D, Transform2D}, + vec2, +}; use ipc_channel::ipc::{self, IpcSender}; use net_traits::image_cache::CanRequestImages; use net_traits::image_cache::ImageCache; @@ -1223,7 +1226,7 @@ impl CanvasState { let (sin, cos) = (angle.sin(), angle.cos()); let transform = self.state.borrow().transform; - self.state.borrow_mut().transform = transform.pre_mul(&Transform2D::row_major( + self.state.borrow_mut().transform = transform.pre_transform(&Transform2D::row_major( cos as f32, sin as f32, -sin as f32, @@ -1258,7 +1261,7 @@ impl CanvasState { } let transform = self.state.borrow().transform; - self.state.borrow_mut().transform = transform.pre_mul(&Transform2D::row_major( + self.state.borrow_mut().transform = transform.pre_transform(&Transform2D::row_major( a as f32, b as f32, c as f32, d as f32, e as f32, f as f32, )); self.update_transform() -- cgit v1.2.3 From 3695fb1eb4182b47b80ed31983a5651c8148aef6 Mon Sep 17 00:00:00 2001 From: Paul Rouget Date: Sat, 21 Sep 2019 09:36:53 +0200 Subject: Temporary implementation of Canvas.MeasureText --- components/script/dom/canvasrenderingcontext2d.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 2a8f14295c0..1faf9878b53 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -24,6 +24,7 @@ use crate::dom::globalscope::GlobalScope; use crate::dom::htmlcanvaselement::{CanvasContext, HTMLCanvasElement}; use crate::dom::imagedata::ImageData; use crate::dom::node::{Node, NodeDamage}; +use crate::dom::textmetrics::TextMetrics; use crate::unpremultiplytable::UNPREMULTIPLY_TABLE; use canvas_traits::canvas::{Canvas2dMsg, CanvasId, CanvasMsg}; use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; @@ -873,6 +874,15 @@ impl CanvasState { self.send_canvas_2d_msg(Canvas2dMsg::FillText(parsed_text, x, y, max_width)); } + // https://html.spec.whatwg.org/multipage/#textmetrics + pub fn MeasureText(&self, global: &GlobalScope, _text: DOMString) -> DomRoot { + // FIXME: for now faking the implementation of MeasureText(). + // See https://github.com/servo/servo/issues/5411#issuecomment-533776291 + TextMetrics::new( + global, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + ) + } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth pub fn LineWidth(&self) -> f64 { self.state.borrow().line_width @@ -1671,6 +1681,11 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { self.mark_as_dirty(); } + // https://html.spec.whatwg.org/multipage/#textmetrics + fn MeasureText(&self, text: DOMString) -> DomRoot { + self.canvas_state.borrow().MeasureText(&self.global(), text) + } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage fn DrawImage(&self, image: CanvasImageSource, dx: f64, dy: f64) -> ErrorResult { self.canvas_state -- cgit v1.2.3 From 81a67aed9e0cc866f4689e8d7a5541198d75e445 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Tue, 1 Oct 2019 13:11:50 -0400 Subject: Double key image cache by requesting origin, and store CORS status with cached images. --- components/script/dom/canvasrenderingcontext2d.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 1faf9878b53..e2495816408 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -47,7 +47,7 @@ use net_traits::image_cache::UsePlaceholder; use pixels::PixelFormat; use profile_traits::ipc as profiled_ipc; use script_traits::ScriptMsg; -use servo_url::ServoUrl; +use servo_url::{ImmutableOrigin, ServoUrl}; use std::cell::Cell; use std::str::FromStr; use std::sync::Arc; @@ -126,6 +126,7 @@ pub struct CanvasState { /// The base URL for resolving CSS image URL values. /// Needed because of https://github.com/servo/servo/issues/17625 base_url: ServoUrl, + origin: ImmutableOrigin, /// Any missing image URLs. missing_image_urls: DomRefCell>, saved_states: DomRefCell>, @@ -152,6 +153,7 @@ impl CanvasState { base_url: global.api_base_url(), missing_image_urls: DomRefCell::new(Vec::new()), saved_states: DomRefCell::new(Vec::new()), + origin: global.origin().immutable().clone(), } } @@ -222,6 +224,7 @@ impl CanvasState { fn request_image_from_cache(&self, url: ServoUrl) -> ImageResponse { let response = self.image_cache.find_image_or_metadata( url.clone(), + self.origin.clone(), UsePlaceholder::No, CanRequestImages::No, ); -- cgit v1.2.3 From 583536c9406e685405d5b28da99dd8cab94c7d66 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Tue, 1 Oct 2019 17:54:43 -0400 Subject: Use the paint worklet's base URL for the 2d canvas' origin checks. --- components/script/dom/canvasrenderingcontext2d.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index e2495816408..380b9a8312a 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -24,6 +24,7 @@ use crate::dom::globalscope::GlobalScope; use crate::dom::htmlcanvaselement::{CanvasContext, HTMLCanvasElement}; use crate::dom::imagedata::ImageData; use crate::dom::node::{Node, NodeDamage}; +use crate::dom::paintworkletglobalscope::PaintWorkletGlobalScope; use crate::dom::textmetrics::TextMetrics; use crate::unpremultiplytable::UNPREMULTIPLY_TABLE; use canvas_traits::canvas::{Canvas2dMsg, CanvasId, CanvasMsg}; @@ -144,6 +145,14 @@ impl CanvasState { .unwrap(); let (ipc_renderer, canvas_id) = receiver.recv().unwrap(); debug!("Done."); + // Worklets always receive a unique origin. This messes with fetching + // cached images in the case of paint worklets, since the image cache + // is keyed on the origin requesting the image data. + let origin = if global.is::() { + global.api_base_url().origin() + } else { + global.origin().immutable().clone() + }; CanvasState { ipc_renderer: ipc_renderer, canvas_id: canvas_id, @@ -153,7 +162,7 @@ impl CanvasState { base_url: global.api_base_url(), missing_image_urls: DomRefCell::new(Vec::new()), saved_states: DomRefCell::new(Vec::new()), - origin: global.origin().immutable().clone(), + origin, } } -- cgit v1.2.3 From 1df8d57dc6adcf56c22b45053b3d2eca904d17d3 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Thu, 3 Oct 2019 17:36:02 -0400 Subject: Support CORS attributes for image elements. --- components/script/dom/canvasrenderingcontext2d.rs | 48 ++++++++++++++++++----- 1 file changed, 39 insertions(+), 9 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 380b9a8312a..c964422c27c 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -19,6 +19,7 @@ use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom}; use crate::dom::bindings::str::DOMString; use crate::dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle}; use crate::dom::canvaspattern::CanvasPattern; +use crate::dom::element::cors_setting_for_element; use crate::dom::element::Element; use crate::dom::globalscope::GlobalScope; use crate::dom::htmlcanvaselement::{CanvasContext, HTMLCanvasElement}; @@ -45,6 +46,7 @@ use net_traits::image_cache::ImageOrMetadataAvailable; use net_traits::image_cache::ImageResponse; use net_traits::image_cache::ImageState; use net_traits::image_cache::UsePlaceholder; +use net_traits::request::CorsSettings; use pixels::PixelFormat; use profile_traits::ipc as profiled_ipc; use script_traits::ScriptMsg; @@ -210,8 +212,12 @@ impl CanvasState { } } - fn fetch_image_data(&self, url: ServoUrl) -> Option<(Vec, Size2D)> { - let img = match self.request_image_from_cache(url) { + fn fetch_image_data( + &self, + url: ServoUrl, + cors_setting: Option, + ) -> Option<(Vec, Size2D)> { + let img = match self.request_image_from_cache(url, cors_setting) { ImageResponse::Loaded(img, _) => img, ImageResponse::PlaceholderLoaded(_, _) | ImageResponse::None | @@ -229,11 +235,15 @@ impl CanvasState { Some((image_data, image_size)) } - #[inline] - fn request_image_from_cache(&self, url: ServoUrl) -> ImageResponse { + fn request_image_from_cache( + &self, + url: ServoUrl, + cors_setting: Option, + ) -> ImageResponse { let response = self.image_cache.find_image_or_metadata( url.clone(), self.origin.clone(), + cors_setting, UsePlaceholder::No, CanRequestImages::No, ); @@ -353,13 +363,28 @@ impl CanvasState { // If the image argument is an HTMLImageElement object that is in the broken state, // then throw an InvalidStateError exception let url = image.get_url().ok_or(Error::InvalidState)?; - self.fetch_and_draw_image_data(htmlcanvas, url, sx, sy, sw, sh, dx, dy, dw, dh) + let cors_setting = cors_setting_for_element(image.upcast()); + self.fetch_and_draw_image_data( + htmlcanvas, + url, + cors_setting, + sx, + sy, + sw, + sh, + dx, + dy, + dw, + dh, + ) }, CanvasImageSource::CSSStyleValue(ref value) => { let url = value .get_url(self.base_url.clone()) .ok_or(Error::InvalidState)?; - self.fetch_and_draw_image_data(htmlcanvas, url, sx, sy, sw, sh, dx, dy, dw, dh) + self.fetch_and_draw_image_data( + htmlcanvas, url, None, sx, sy, sw, sh, dx, dy, dw, dh, + ) }, }; @@ -435,6 +460,7 @@ impl CanvasState { &self, canvas: Option<&HTMLCanvasElement>, url: ServoUrl, + cors_setting: Option, sx: f64, sy: f64, sw: Option, @@ -445,7 +471,9 @@ impl CanvasState { dh: Option, ) -> ErrorResult { debug!("Fetching image {}.", url); - let (mut image_data, image_size) = self.fetch_image_data(url).ok_or(Error::InvalidState)?; + let (mut image_data, image_size) = self + .fetch_image_data(url, cors_setting) + .ok_or(Error::InvalidState)?; pixels::rgba8_premultiply_inplace(&mut image_data); let image_size = image_size.to_f64(); @@ -788,7 +816,9 @@ impl CanvasState { // then throw an InvalidStateError exception image .get_url() - .and_then(|url| self.fetch_image_data(url)) + .and_then(|url| { + self.fetch_image_data(url, cors_setting_for_element(image.upcast())) + }) .ok_or(Error::InvalidState)? }, CanvasImageSource::HTMLCanvasElement(ref canvas) => { @@ -800,7 +830,7 @@ impl CanvasState { }, CanvasImageSource::CSSStyleValue(ref value) => value .get_url(self.base_url.clone()) - .and_then(|url| self.fetch_image_data(url)) + .and_then(|url| self.fetch_image_data(url, None)) .ok_or(Error::InvalidState)?, }; -- cgit v1.2.3 From 328809aebef8ee2d9346159c365d7ae0d46db644 Mon Sep 17 00:00:00 2001 From: Rasmus Viitanen Date: Wed, 16 Oct 2019 20:18:14 +0200 Subject: fix getimagedata returns empty pixels --- components/script/dom/canvasrenderingcontext2d.rs | 49 ++++++++++------------- 1 file changed, 21 insertions(+), 28 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index c964422c27c..999aab5320c 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -298,12 +298,9 @@ impl CanvasState { } } - pub fn get_rect(&self, canvas: Option<&HTMLCanvasElement>, rect: Rect) -> Vec { + pub fn get_rect(&self, canvas_size: Size2D, rect: Rect) -> Vec { assert!(self.origin_is_clean()); - // FIXME(nox): This is probably wrong when this is a context for an - // offscreen canvas. - let canvas_size = canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()); assert!(Rect::from_size(canvas_size).contains_rect(&rect)); let (sender, receiver) = ipc::bytes_channel().unwrap(); @@ -1020,7 +1017,7 @@ impl CanvasState { // https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata pub fn GetImageData( &self, - canvas: Option<&HTMLCanvasElement>, + canvas_size: Size2D, global: &GlobalScope, sx: i32, sy: i32, @@ -1039,9 +1036,6 @@ impl CanvasState { } let (origin, size) = adjust_size_sign(Point2D::new(sx, sy), Size2D::new(sw, sh)); - // FIXME(nox): This is probably wrong when this is a context for an - // offscreen canvas. - let canvas_size = canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()); let read_rect = match pixels::clip(origin, size, canvas_size) { Some(rect) => rect, None => { @@ -1054,20 +1048,14 @@ impl CanvasState { global, size.width, size.height, - Some(self.get_rect(canvas, read_rect)), + Some(self.get_rect(canvas_size, read_rect)), ) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata - pub fn PutImageData( - &self, - canvas: Option<&HTMLCanvasElement>, - imagedata: &ImageData, - dx: i32, - dy: i32, - ) { + pub fn PutImageData(&self, canvas_size: Size2D, imagedata: &ImageData, dx: i32, dy: i32) { self.PutImageData_( - canvas, + canvas_size, imagedata, dx, dy, @@ -1082,7 +1070,7 @@ impl CanvasState { #[allow(unsafe_code)] pub fn PutImageData_( &self, - canvas: Option<&HTMLCanvasElement>, + canvas_size: Size2D, imagedata: &ImageData, dx: i32, dy: i32, @@ -1105,10 +1093,6 @@ impl CanvasState { // Step 2. // TODO: throw InvalidState if buffer is detached. - // FIXME(nox): This is probably wrong when this is a context for an - // offscreen canvas. - let canvas_size = canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()); - // Steps 3-6. let (src_origin, src_size) = adjust_size_sign( Point2D::new(dirty_x, dirty_y), @@ -1553,9 +1537,12 @@ impl CanvasRenderingContext2D { } pub fn get_rect(&self, rect: Rect) -> Vec { - self.canvas_state - .borrow() - .get_rect(self.canvas.as_ref().map(|c| &**c), rect) + self.canvas_state.borrow().get_rect( + self.canvas + .as_ref() + .map_or(Size2D::zero(), |c| c.get_size()), + rect, + ) } } @@ -1886,7 +1873,9 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata fn GetImageData(&self, sx: i32, sy: i32, sw: i32, sh: i32) -> Fallible> { self.canvas_state.borrow().GetImageData( - self.canvas.as_ref().map(|c| &**c), + self.canvas + .as_ref() + .map_or(Size2D::zero(), |c| c.get_size()), &self.global(), sx, sy, @@ -1898,7 +1887,9 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata fn PutImageData(&self, imagedata: &ImageData, dx: i32, dy: i32) { self.canvas_state.borrow().PutImageData( - self.canvas.as_ref().map(|c| &**c), + self.canvas + .as_ref() + .map_or(Size2D::zero(), |c| c.get_size()), imagedata, dx, dy, @@ -1918,7 +1909,9 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { dirty_height: i32, ) { self.canvas_state.borrow().PutImageData_( - self.canvas.as_ref().map(|c| &**c), + self.canvas + .as_ref() + .map_or(Size2D::zero(), |c| c.get_size()), imagedata, dx, dy, -- cgit v1.2.3 From 31ff2d43ccc835bffc99aac596dabae1d23cc5f7 Mon Sep 17 00:00:00 2001 From: Hanif Bin Ariffin Date: Mon, 21 Oct 2019 05:24:49 -0400 Subject: Moved CanvasState out of canvasrenderingcontext Cleaned up imports... Applied clang-tidy Moved CanvasState and some other files Next commit should remove pub modifier from members of CanvasState and use getters/setters instead. Members of CanvasState are now private and applied test-tidy Now have getters that return an immutable reference. Also, I have no idea what to name some_func.rs Removed need for some_func and made pub(crate) --- components/script/dom/canvasrenderingcontext2d.rs | 1678 ++------------------- 1 file changed, 102 insertions(+), 1576 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 999aab5320c..9f6403bec5c 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -2,6 +2,7 @@ * 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 crate::canvas_state::{CanvasContextState, CanvasState}; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasFillRule; @@ -9,1454 +10,33 @@ use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::Ca use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineCap; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineJoin; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods; -use crate::dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods; use crate::dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern; -use crate::dom::bindings::error::{Error, ErrorResult, Fallible}; -use crate::dom::bindings::inheritance::Castable; +use crate::dom::bindings::error::{ErrorResult, Fallible}; use crate::dom::bindings::num::Finite; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom}; use crate::dom::bindings::str::DOMString; -use crate::dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle}; +use crate::dom::canvasgradient::CanvasGradient; use crate::dom::canvaspattern::CanvasPattern; -use crate::dom::element::cors_setting_for_element; -use crate::dom::element::Element; use crate::dom::globalscope::GlobalScope; -use crate::dom::htmlcanvaselement::{CanvasContext, HTMLCanvasElement}; +use crate::dom::htmlcanvaselement::HTMLCanvasElement; use crate::dom::imagedata::ImageData; -use crate::dom::node::{Node, NodeDamage}; -use crate::dom::paintworkletglobalscope::PaintWorkletGlobalScope; use crate::dom::textmetrics::TextMetrics; -use crate::unpremultiplytable::UNPREMULTIPLY_TABLE; use canvas_traits::canvas::{Canvas2dMsg, CanvasId, CanvasMsg}; -use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; -use canvas_traits::canvas::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; -use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle}; -use cssparser::Color as CSSColor; -use cssparser::{Parser, ParserInput, RGBA}; use dom_struct::dom_struct; -use euclid::{ - default::{Point2D, Rect, Size2D, Transform2D}, - vec2, -}; -use ipc_channel::ipc::{self, IpcSender}; -use net_traits::image_cache::CanRequestImages; -use net_traits::image_cache::ImageCache; -use net_traits::image_cache::ImageOrMetadataAvailable; -use net_traits::image_cache::ImageResponse; -use net_traits::image_cache::ImageState; -use net_traits::image_cache::UsePlaceholder; -use net_traits::request::CorsSettings; -use pixels::PixelFormat; -use profile_traits::ipc as profiled_ipc; -use script_traits::ScriptMsg; -use servo_url::{ImmutableOrigin, ServoUrl}; -use std::cell::Cell; -use std::str::FromStr; -use std::sync::Arc; -use std::{fmt, mem}; - -#[must_root] -#[derive(Clone, JSTraceable, MallocSizeOf)] -#[allow(dead_code)] -enum CanvasFillOrStrokeStyle { - Color(RGBA), - Gradient(Dom), - Pattern(Dom), -} - -// https://html.spec.whatwg.org/multipage/#canvasrenderingcontext2d -#[dom_struct] -pub struct CanvasRenderingContext2D { - reflector_: Reflector, - /// For rendering contexts created by an HTML canvas element, this is Some, - /// for ones created by a paint worklet, this is None. - canvas: Option>, - canvas_state: DomRefCell, -} - -#[must_root] -#[derive(Clone, JSTraceable, MallocSizeOf)] -struct CanvasContextState { - global_alpha: f64, - global_composition: CompositionOrBlending, - image_smoothing_enabled: bool, - fill_style: CanvasFillOrStrokeStyle, - stroke_style: CanvasFillOrStrokeStyle, - line_width: f64, - line_cap: LineCapStyle, - line_join: LineJoinStyle, - miter_limit: f64, - transform: Transform2D, - shadow_offset_x: f64, - shadow_offset_y: f64, - shadow_blur: f64, - shadow_color: RGBA, -} - -impl CanvasContextState { - fn new() -> CanvasContextState { - let black = RGBA::new(0, 0, 0, 255); - CanvasContextState { - global_alpha: 1.0, - global_composition: CompositionOrBlending::default(), - image_smoothing_enabled: true, - fill_style: CanvasFillOrStrokeStyle::Color(black), - stroke_style: CanvasFillOrStrokeStyle::Color(black), - line_width: 1.0, - line_cap: LineCapStyle::Butt, - line_join: LineJoinStyle::Miter, - miter_limit: 10.0, - transform: Transform2D::identity(), - shadow_offset_x: 0.0, - shadow_offset_y: 0.0, - shadow_blur: 0.0, - shadow_color: RGBA::transparent(), - } - } -} - -#[must_root] -#[derive(JSTraceable, MallocSizeOf)] -pub struct CanvasState { - #[ignore_malloc_size_of = "Defined in ipc-channel"] - ipc_renderer: IpcSender, - canvas_id: CanvasId, - state: DomRefCell, - origin_clean: Cell, - #[ignore_malloc_size_of = "Arc"] - image_cache: Arc, - /// The base URL for resolving CSS image URL values. - /// Needed because of https://github.com/servo/servo/issues/17625 - base_url: ServoUrl, - origin: ImmutableOrigin, - /// Any missing image URLs. - missing_image_urls: DomRefCell>, - saved_states: DomRefCell>, -} - -impl CanvasState { - pub fn new(global: &GlobalScope, size: Size2D) -> CanvasState { - debug!("Creating new canvas rendering context."); - let (sender, receiver) = - profiled_ipc::channel(global.time_profiler_chan().clone()).unwrap(); - let script_to_constellation_chan = global.script_to_constellation_chan(); - debug!("Asking constellation to create new canvas thread."); - script_to_constellation_chan - .send(ScriptMsg::CreateCanvasPaintThread(size, sender)) - .unwrap(); - let (ipc_renderer, canvas_id) = receiver.recv().unwrap(); - debug!("Done."); - // Worklets always receive a unique origin. This messes with fetching - // cached images in the case of paint worklets, since the image cache - // is keyed on the origin requesting the image data. - let origin = if global.is::() { - global.api_base_url().origin() - } else { - global.origin().immutable().clone() - }; - CanvasState { - ipc_renderer: ipc_renderer, - canvas_id: canvas_id, - state: DomRefCell::new(CanvasContextState::new()), - origin_clean: Cell::new(true), - image_cache: global.image_cache(), - base_url: global.api_base_url(), - missing_image_urls: DomRefCell::new(Vec::new()), - saved_states: DomRefCell::new(Vec::new()), - origin, - } - } - - pub fn get_canvas_id(&self) -> CanvasId { - self.canvas_id.clone() - } - - pub fn send_canvas_2d_msg(&self, msg: Canvas2dMsg) { - self.ipc_renderer - .send(CanvasMsg::Canvas2d(msg, self.get_canvas_id())) - .unwrap() - } - - fn create_drawable_rect(&self, x: f64, y: f64, w: f64, h: f64) -> Option> { - if !([x, y, w, h].iter().all(|val| val.is_finite())) { - return None; - } - - if w == 0.0 && h == 0.0 { - return None; - } - - Some(Rect::new( - Point2D::new(x as f32, y as f32), - Size2D::new(w as f32, h as f32), - )) - } - - fn origin_is_clean(&self) -> bool { - self.origin_clean.get() - } - - fn set_origin_unclean(&self) { - self.origin_clean.set(false) - } - - // https://html.spec.whatwg.org/multipage/#the-image-argument-is-not-origin-clean - fn is_origin_clean(&self, image: CanvasImageSource) -> bool { - match image { - CanvasImageSource::HTMLCanvasElement(canvas) => canvas.origin_is_clean(), - CanvasImageSource::HTMLImageElement(image) => { - image.same_origin(GlobalScope::entry().origin()) - }, - CanvasImageSource::CSSStyleValue(_) => true, - } - } - - fn fetch_image_data( - &self, - url: ServoUrl, - cors_setting: Option, - ) -> Option<(Vec, Size2D)> { - let img = match self.request_image_from_cache(url, cors_setting) { - ImageResponse::Loaded(img, _) => img, - ImageResponse::PlaceholderLoaded(_, _) | - ImageResponse::None | - ImageResponse::MetadataLoaded(_) => { - return None; - }, - }; - - let image_size = Size2D::new(img.width, img.height); - let image_data = match img.format { - PixelFormat::BGRA8 => img.bytes.to_vec(), - pixel_format => unimplemented!("unsupported pixel format ({:?})", pixel_format), - }; - - Some((image_data, image_size)) - } - - fn request_image_from_cache( - &self, - url: ServoUrl, - cors_setting: Option, - ) -> ImageResponse { - let response = self.image_cache.find_image_or_metadata( - url.clone(), - self.origin.clone(), - cors_setting, - UsePlaceholder::No, - CanRequestImages::No, - ); - match response { - Ok(ImageOrMetadataAvailable::ImageAvailable(image, url)) => { - ImageResponse::Loaded(image, url) - }, - Err(ImageState::Pending(_)) => ImageResponse::None, - _ => { - // Rather annoyingly, we get the same response back from - // A load which really failed and from a load which hasn't started yet. - self.missing_image_urls.borrow_mut().push(url); - ImageResponse::None - }, - } - } - - fn parse_color(&self, canvas: Option<&HTMLCanvasElement>, string: &str) -> Result { - let mut input = ParserInput::new(string); - let mut parser = Parser::new(&mut input); - let color = CSSColor::parse(&mut parser); - if parser.is_exhausted() { - match color { - Ok(CSSColor::RGBA(rgba)) => Ok(rgba), - Ok(CSSColor::CurrentColor) => { - // TODO: https://github.com/whatwg/html/issues/1099 - // Reconsider how to calculate currentColor in a display:none canvas - - // TODO: will need to check that the context bitmap mode is fixed - // once we implement CanvasProxy - let canvas = match canvas { - // https://drafts.css-houdini.org/css-paint-api/#2d-rendering-context - // Whenever "currentColor" is used as a color in the PaintRenderingContext2D API, - // it is treated as opaque black. - None => return Ok(RGBA::new(0, 0, 0, 255)), - Some(ref canvas) => &**canvas, - }; - - let canvas_element = canvas.upcast::(); - - match canvas_element.style() { - Some(ref s) if canvas_element.has_css_layout_box() => { - Ok(s.get_inherited_text().color) - }, - _ => Ok(RGBA::new(0, 0, 0, 255)), - } - }, - _ => Err(()), - } - } else { - Err(()) - } - } - - pub fn get_rect(&self, canvas_size: Size2D, rect: Rect) -> Vec { - assert!(self.origin_is_clean()); - - assert!(Rect::from_size(canvas_size).contains_rect(&rect)); - - let (sender, receiver) = ipc::bytes_channel().unwrap(); - self.send_canvas_2d_msg(Canvas2dMsg::GetImageData(rect, canvas_size, sender)); - let mut pixels = receiver.recv().unwrap().to_vec(); - - for chunk in pixels.chunks_mut(4) { - let b = chunk[0]; - chunk[0] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + chunk[2] as usize]; - chunk[1] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + chunk[1] as usize]; - chunk[2] = UNPREMULTIPLY_TABLE[256 * (chunk[3] as usize) + b as usize]; - } - - pixels - } - - // - // drawImage coordinates explained - // - // Source Image Destination Canvas - // +-------------+ +-------------+ - // | | | | - // |(sx,sy) | |(dx,dy) | - // | +----+ | | +----+ | - // | | | | | | | | - // | | |sh |---->| | |dh | - // | | | | | | | | - // | +----+ | | +----+ | - // | sw | | dw | - // | | | | - // +-------------+ +-------------+ - // - // - // The rectangle (sx, sy, sw, sh) from the source image - // is copied on the rectangle (dx, dy, dh, dw) of the destination canvas - // - // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage - fn draw_image( - &self, - htmlcanvas: Option<&HTMLCanvasElement>, - image: CanvasImageSource, - sx: f64, - sy: f64, - sw: Option, - sh: Option, - dx: f64, - dy: f64, - dw: Option, - dh: Option, - ) -> ErrorResult { - let result = match image { - CanvasImageSource::HTMLCanvasElement(ref canvas) => { - self.draw_html_canvas_element(&canvas, htmlcanvas, sx, sy, sw, sh, dx, dy, dw, dh) - }, - CanvasImageSource::HTMLImageElement(ref image) => { - // https://html.spec.whatwg.org/multipage/#img-error - // If the image argument is an HTMLImageElement object that is in the broken state, - // then throw an InvalidStateError exception - let url = image.get_url().ok_or(Error::InvalidState)?; - let cors_setting = cors_setting_for_element(image.upcast()); - self.fetch_and_draw_image_data( - htmlcanvas, - url, - cors_setting, - sx, - sy, - sw, - sh, - dx, - dy, - dw, - dh, - ) - }, - CanvasImageSource::CSSStyleValue(ref value) => { - let url = value - .get_url(self.base_url.clone()) - .ok_or(Error::InvalidState)?; - self.fetch_and_draw_image_data( - htmlcanvas, url, None, sx, sy, sw, sh, dx, dy, dw, dh, - ) - }, - }; - - if result.is_ok() && !self.is_origin_clean(image) { - self.set_origin_unclean() - } - result - } - - fn draw_html_canvas_element( - &self, - canvas: &HTMLCanvasElement, - htmlcanvas: Option<&HTMLCanvasElement>, - sx: f64, - sy: f64, - sw: Option, - sh: Option, - dx: f64, - dy: f64, - dw: Option, - dh: Option, - ) -> ErrorResult { - // 1. Check the usability of the image argument - if !canvas.is_valid() { - return Err(Error::InvalidState); - } - - let canvas_size = canvas.get_size(); - let dw = dw.unwrap_or(canvas_size.width as f64); - let dh = dh.unwrap_or(canvas_size.height as f64); - let sw = sw.unwrap_or(canvas_size.width as f64); - let sh = sh.unwrap_or(canvas_size.height as f64); - - let image_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64); - // 2. Establish the source and destination rectangles - let (source_rect, dest_rect) = - self.adjust_source_dest_rects(image_size, sx, sy, sw, sh, dx, dy, dw, dh); - - if !is_rect_valid(source_rect) || !is_rect_valid(dest_rect) { - return Ok(()); - } - - let smoothing_enabled = self.state.borrow().image_smoothing_enabled; - - if let Some(context) = canvas.context() { - match *context { - CanvasContext::Context2d(ref context) => { - context.send_canvas_2d_msg(Canvas2dMsg::DrawImageInOther( - self.get_canvas_id(), - image_size, - dest_rect, - source_rect, - smoothing_enabled, - )); - }, - _ => return Err(Error::InvalidState), - } - } else { - self.send_canvas_2d_msg(Canvas2dMsg::DrawImage( - None, - image_size, - dest_rect, - source_rect, - smoothing_enabled, - )); - } - - self.mark_as_dirty(htmlcanvas); - Ok(()) - } - - fn fetch_and_draw_image_data( - &self, - canvas: Option<&HTMLCanvasElement>, - url: ServoUrl, - cors_setting: Option, - sx: f64, - sy: f64, - sw: Option, - sh: Option, - dx: f64, - dy: f64, - dw: Option, - dh: Option, - ) -> ErrorResult { - debug!("Fetching image {}.", url); - let (mut image_data, image_size) = self - .fetch_image_data(url, cors_setting) - .ok_or(Error::InvalidState)?; - pixels::rgba8_premultiply_inplace(&mut image_data); - let image_size = image_size.to_f64(); - - let dw = dw.unwrap_or(image_size.width); - let dh = dh.unwrap_or(image_size.height); - let sw = sw.unwrap_or(image_size.width); - let sh = sh.unwrap_or(image_size.height); - - // Establish the source and destination rectangles - let (source_rect, dest_rect) = - self.adjust_source_dest_rects(image_size, sx, sy, sw, sh, dx, dy, dw, dh); - - if !is_rect_valid(source_rect) || !is_rect_valid(dest_rect) { - return Ok(()); - } - - let smoothing_enabled = self.state.borrow().image_smoothing_enabled; - self.send_canvas_2d_msg(Canvas2dMsg::DrawImage( - Some(image_data.into()), - image_size, - dest_rect, - source_rect, - smoothing_enabled, - )); - self.mark_as_dirty(canvas); - Ok(()) - } - - fn mark_as_dirty(&self, canvas: Option<&HTMLCanvasElement>) { - if let Some(ref canvas) = canvas { - canvas.upcast::().dirty(NodeDamage::OtherNodeDamage); - } - } - - // It is used by DrawImage to calculate the size of the source and destination rectangles based - // on the drawImage call arguments - // source rectangle = area of the original image to be copied - // destination rectangle = area of the destination canvas where the source image is going to be drawn - fn adjust_source_dest_rects( - &self, - image_size: Size2D, - sx: f64, - sy: f64, - sw: f64, - sh: f64, - dx: f64, - dy: f64, - dw: f64, - dh: f64, - ) -> (Rect, Rect) { - let image_rect = Rect::new( - Point2D::new(0f64, 0f64), - Size2D::new(image_size.width as f64, image_size.height as f64), - ); - - // The source rectangle is the rectangle whose corners are the four points (sx, sy), - // (sx+sw, sy), (sx+sw, sy+sh), (sx, sy+sh). - let source_rect = Rect::new( - Point2D::new(sx.min(sx + sw), sy.min(sy + sh)), - Size2D::new(sw.abs(), sh.abs()), - ); - - // When the source rectangle is outside the source image, - // the source rectangle must be clipped to the source image - let source_rect_clipped = source_rect - .intersection(&image_rect) - .unwrap_or(Rect::zero()); - - // Width and height ratios between the non clipped and clipped source rectangles - let width_ratio: f64 = source_rect_clipped.size.width / source_rect.size.width; - let height_ratio: f64 = source_rect_clipped.size.height / source_rect.size.height; - - // When the source rectangle is outside the source image, - // the destination rectangle must be clipped in the same proportion. - let dest_rect_width_scaled: f64 = dw * width_ratio; - let dest_rect_height_scaled: f64 = dh * height_ratio; - - // The destination rectangle is the rectangle whose corners are the four points (dx, dy), - // (dx+dw, dy), (dx+dw, dy+dh), (dx, dy+dh). - let dest_rect = Rect::new( - Point2D::new( - dx.min(dx + dest_rect_width_scaled), - dy.min(dy + dest_rect_height_scaled), - ), - Size2D::new(dest_rect_width_scaled.abs(), dest_rect_height_scaled.abs()), - ); - - let source_rect = Rect::new( - Point2D::new(source_rect_clipped.origin.x, source_rect_clipped.origin.y), - Size2D::new( - source_rect_clipped.size.width, - source_rect_clipped.size.height, - ), - ); - - (source_rect, dest_rect) - } - - fn update_transform(&self) { - self.send_canvas_2d_msg(Canvas2dMsg::SetTransform(self.state.borrow().transform)) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect - pub fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) { - if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.send_canvas_2d_msg(Canvas2dMsg::FillRect(rect)); - } - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-clearrect - pub fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) { - if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.send_canvas_2d_msg(Canvas2dMsg::ClearRect(rect)); - } - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokerect - pub fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) { - if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.send_canvas_2d_msg(Canvas2dMsg::StrokeRect(rect)); - } - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx - pub fn ShadowOffsetX(&self) -> f64 { - self.state.borrow().shadow_offset_x - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx - pub fn SetShadowOffsetX(&self, value: f64) { - if !value.is_finite() || value == self.state.borrow().shadow_offset_x { - return; - } - self.state.borrow_mut().shadow_offset_x = value; - self.send_canvas_2d_msg(Canvas2dMsg::SetShadowOffsetX(value)) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety - pub fn ShadowOffsetY(&self) -> f64 { - self.state.borrow().shadow_offset_y - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety - pub fn SetShadowOffsetY(&self, value: f64) { - if !value.is_finite() || value == self.state.borrow().shadow_offset_y { - return; - } - self.state.borrow_mut().shadow_offset_y = value; - self.send_canvas_2d_msg(Canvas2dMsg::SetShadowOffsetY(value)) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur - pub fn ShadowBlur(&self) -> f64 { - self.state.borrow().shadow_blur - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur - pub fn SetShadowBlur(&self, value: f64) { - if !value.is_finite() || value < 0f64 || value == self.state.borrow().shadow_blur { - return; - } - self.state.borrow_mut().shadow_blur = value; - self.send_canvas_2d_msg(Canvas2dMsg::SetShadowBlur(value)) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor - pub fn ShadowColor(&self) -> DOMString { - let mut result = String::new(); - serialize(&self.state.borrow().shadow_color, &mut result).unwrap(); - DOMString::from(result) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor - pub fn SetShadowColor(&self, value: DOMString) { - if let Ok(color) = parse_color(&value) { - self.state.borrow_mut().shadow_color = color; - self.send_canvas_2d_msg(Canvas2dMsg::SetShadowColor(color)) - } - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle - pub fn StrokeStyle(&self) -> StringOrCanvasGradientOrCanvasPattern { - match self.state.borrow().stroke_style { - CanvasFillOrStrokeStyle::Color(ref rgba) => { - let mut result = String::new(); - serialize(rgba, &mut result).unwrap(); - StringOrCanvasGradientOrCanvasPattern::String(DOMString::from(result)) - }, - CanvasFillOrStrokeStyle::Gradient(ref gradient) => { - StringOrCanvasGradientOrCanvasPattern::CanvasGradient(DomRoot::from_ref(&*gradient)) - }, - CanvasFillOrStrokeStyle::Pattern(ref pattern) => { - StringOrCanvasGradientOrCanvasPattern::CanvasPattern(DomRoot::from_ref(&*pattern)) - }, - } - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle - pub fn SetStrokeStyle( - &self, - canvas: Option<&HTMLCanvasElement>, - value: StringOrCanvasGradientOrCanvasPattern, - ) { - match value { - StringOrCanvasGradientOrCanvasPattern::String(string) => { - if let Ok(rgba) = self.parse_color(canvas, &string) { - self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Color(rgba); - self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle(FillOrStrokeStyle::Color( - rgba, - ))); - } - }, - StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => { - self.state.borrow_mut().stroke_style = - CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient)); - self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle( - gradient.to_fill_or_stroke_style(), - )); - }, - StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => { - self.state.borrow_mut().stroke_style = - CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern)); - self.send_canvas_2d_msg(Canvas2dMsg::SetStrokeStyle( - pattern.to_fill_or_stroke_style(), - )); - if !pattern.origin_is_clean() { - self.set_origin_unclean(); - } - }, - } - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle - pub fn FillStyle(&self) -> StringOrCanvasGradientOrCanvasPattern { - match self.state.borrow().fill_style { - CanvasFillOrStrokeStyle::Color(ref rgba) => { - let mut result = String::new(); - serialize(rgba, &mut result).unwrap(); - StringOrCanvasGradientOrCanvasPattern::String(DOMString::from(result)) - }, - CanvasFillOrStrokeStyle::Gradient(ref gradient) => { - StringOrCanvasGradientOrCanvasPattern::CanvasGradient(DomRoot::from_ref(&*gradient)) - }, - CanvasFillOrStrokeStyle::Pattern(ref pattern) => { - StringOrCanvasGradientOrCanvasPattern::CanvasPattern(DomRoot::from_ref(&*pattern)) - }, - } - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle - pub fn SetFillStyle( - &self, - canvas: Option<&HTMLCanvasElement>, - value: StringOrCanvasGradientOrCanvasPattern, - ) { - match value { - StringOrCanvasGradientOrCanvasPattern::String(string) => { - if let Ok(rgba) = self.parse_color(canvas, &string) { - self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Color(rgba); - self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle(FillOrStrokeStyle::Color( - rgba, - ))) - } - }, - StringOrCanvasGradientOrCanvasPattern::CanvasGradient(gradient) => { - self.state.borrow_mut().fill_style = - CanvasFillOrStrokeStyle::Gradient(Dom::from_ref(&*gradient)); - self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle( - gradient.to_fill_or_stroke_style(), - )); - }, - StringOrCanvasGradientOrCanvasPattern::CanvasPattern(pattern) => { - self.state.borrow_mut().fill_style = - CanvasFillOrStrokeStyle::Pattern(Dom::from_ref(&*pattern)); - self.send_canvas_2d_msg(Canvas2dMsg::SetFillStyle( - pattern.to_fill_or_stroke_style(), - )); - if !pattern.origin_is_clean() { - self.set_origin_unclean(); - } - }, - } - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-createlineargradient - pub fn CreateLinearGradient( - &self, - global: &GlobalScope, - x0: Finite, - y0: Finite, - x1: Finite, - y1: Finite, - ) -> DomRoot { - CanvasGradient::new( - global, - CanvasGradientStyle::Linear(LinearGradientStyle::new(*x0, *y0, *x1, *y1, Vec::new())), - ) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-createradialgradient - pub fn CreateRadialGradient( - &self, - global: &GlobalScope, - x0: Finite, - y0: Finite, - r0: Finite, - x1: Finite, - y1: Finite, - r1: Finite, - ) -> Fallible> { - if *r0 < 0. || *r1 < 0. { - return Err(Error::IndexSize); - } - - Ok(CanvasGradient::new( - global, - CanvasGradientStyle::Radial(RadialGradientStyle::new( - *x0, - *y0, - *r0, - *x1, - *y1, - *r1, - Vec::new(), - )), - )) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern - pub fn CreatePattern( - &self, - global: &GlobalScope, - image: CanvasImageSource, - mut repetition: DOMString, - ) -> Fallible> { - let (image_data, image_size) = match image { - CanvasImageSource::HTMLImageElement(ref image) => { - // https://html.spec.whatwg.org/multipage/#img-error - // If the image argument is an HTMLImageElement object that is in the broken state, - // then throw an InvalidStateError exception - image - .get_url() - .and_then(|url| { - self.fetch_image_data(url, cors_setting_for_element(image.upcast())) - }) - .ok_or(Error::InvalidState)? - }, - CanvasImageSource::HTMLCanvasElement(ref canvas) => { - let (data, size) = canvas.fetch_all_data().ok_or(Error::InvalidState)?; - let data = data - .map(|data| data.to_vec()) - .unwrap_or_else(|| vec![0; size.area() as usize * 4]); - (data, size) - }, - CanvasImageSource::CSSStyleValue(ref value) => value - .get_url(self.base_url.clone()) - .and_then(|url| self.fetch_image_data(url, None)) - .ok_or(Error::InvalidState)?, - }; - - if repetition.is_empty() { - repetition.push_str("repeat"); - } - - if let Ok(rep) = RepetitionStyle::from_str(&repetition) { - Ok(CanvasPattern::new( - global, - image_data, - image_size, - rep, - self.is_origin_clean(image), - )) - } else { - Err(Error::Syntax) - } - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-save - pub fn Save(&self) { - self.saved_states - .borrow_mut() - .push(self.state.borrow().clone()); - self.send_canvas_2d_msg(Canvas2dMsg::SaveContext); - } - - #[allow(unrooted_must_root)] - // https://html.spec.whatwg.org/multipage/#dom-context-2d-restore - pub fn Restore(&self) { - let mut saved_states = self.saved_states.borrow_mut(); - if let Some(state) = saved_states.pop() { - self.state.borrow_mut().clone_from(&state); - self.send_canvas_2d_msg(Canvas2dMsg::RestoreContext); - } - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha - pub fn GlobalAlpha(&self) -> f64 { - self.state.borrow().global_alpha - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha - pub fn SetGlobalAlpha(&self, alpha: f64) { - if !alpha.is_finite() || alpha > 1.0 || alpha < 0.0 { - return; - } - - self.state.borrow_mut().global_alpha = alpha; - self.send_canvas_2d_msg(Canvas2dMsg::SetGlobalAlpha(alpha as f32)) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation - pub fn GlobalCompositeOperation(&self) -> DOMString { - match self.state.borrow().global_composition { - CompositionOrBlending::Composition(op) => DOMString::from(op.to_str()), - CompositionOrBlending::Blending(op) => DOMString::from(op.to_str()), - } - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation - pub fn SetGlobalCompositeOperation(&self, op_str: DOMString) { - if let Ok(op) = CompositionOrBlending::from_str(&op_str) { - self.state.borrow_mut().global_composition = op; - self.send_canvas_2d_msg(Canvas2dMsg::SetGlobalComposition(op)) - } - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-imagesmoothingenabled - pub fn ImageSmoothingEnabled(&self) -> bool { - self.state.borrow().image_smoothing_enabled - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-imagesmoothingenabled - pub fn SetImageSmoothingEnabled(&self, value: bool) { - self.state.borrow_mut().image_smoothing_enabled = value; - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-filltext - pub fn FillText(&self, text: DOMString, x: f64, y: f64, max_width: Option) { - let parsed_text: String = text.into(); - self.send_canvas_2d_msg(Canvas2dMsg::FillText(parsed_text, x, y, max_width)); - } - - // https://html.spec.whatwg.org/multipage/#textmetrics - pub fn MeasureText(&self, global: &GlobalScope, _text: DOMString) -> DomRoot { - // FIXME: for now faking the implementation of MeasureText(). - // See https://github.com/servo/servo/issues/5411#issuecomment-533776291 - TextMetrics::new( - global, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - ) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth - pub fn LineWidth(&self) -> f64 { - self.state.borrow().line_width - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth - pub fn SetLineWidth(&self, width: f64) { - if !width.is_finite() || width <= 0.0 { - return; - } - - self.state.borrow_mut().line_width = width; - self.send_canvas_2d_msg(Canvas2dMsg::SetLineWidth(width as f32)) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap - pub fn LineCap(&self) -> CanvasLineCap { - match self.state.borrow().line_cap { - LineCapStyle::Butt => CanvasLineCap::Butt, - LineCapStyle::Round => CanvasLineCap::Round, - LineCapStyle::Square => CanvasLineCap::Square, - } - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap - pub fn SetLineCap(&self, cap: CanvasLineCap) { - let line_cap = match cap { - CanvasLineCap::Butt => LineCapStyle::Butt, - CanvasLineCap::Round => LineCapStyle::Round, - CanvasLineCap::Square => LineCapStyle::Square, - }; - self.state.borrow_mut().line_cap = line_cap; - self.send_canvas_2d_msg(Canvas2dMsg::SetLineCap(line_cap)); - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin - pub fn LineJoin(&self) -> CanvasLineJoin { - match self.state.borrow().line_join { - LineJoinStyle::Round => CanvasLineJoin::Round, - LineJoinStyle::Bevel => CanvasLineJoin::Bevel, - LineJoinStyle::Miter => CanvasLineJoin::Miter, - } - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin - pub fn SetLineJoin(&self, join: CanvasLineJoin) { - let line_join = match join { - CanvasLineJoin::Round => LineJoinStyle::Round, - CanvasLineJoin::Bevel => LineJoinStyle::Bevel, - CanvasLineJoin::Miter => LineJoinStyle::Miter, - }; - self.state.borrow_mut().line_join = line_join; - self.send_canvas_2d_msg(Canvas2dMsg::SetLineJoin(line_join)); - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit - pub fn MiterLimit(&self) -> f64 { - self.state.borrow().miter_limit - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit - pub fn SetMiterLimit(&self, limit: f64) { - if !limit.is_finite() || limit <= 0.0 { - return; - } - - self.state.borrow_mut().miter_limit = limit; - self.send_canvas_2d_msg(Canvas2dMsg::SetMiterLimit(limit as f32)) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata - pub fn CreateImageData( - &self, - global: &GlobalScope, - sw: i32, - sh: i32, - ) -> Fallible> { - if sw == 0 || sh == 0 { - return Err(Error::IndexSize); - } - ImageData::new(global, sw.abs() as u32, sh.abs() as u32, None) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata - pub fn CreateImageData_( - &self, - global: &GlobalScope, - imagedata: &ImageData, - ) -> Fallible> { - ImageData::new(global, imagedata.Width(), imagedata.Height(), None) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata - pub fn GetImageData( - &self, - canvas_size: Size2D, - global: &GlobalScope, - sx: i32, - sy: i32, - sw: i32, - sh: i32, - ) -> Fallible> { - // FIXME(nox): There are many arithmetic operations here that can - // overflow or underflow, this should probably be audited. - - if sw == 0 || sh == 0 { - return Err(Error::IndexSize); - } - - if !self.origin_is_clean() { - return Err(Error::Security); - } - - let (origin, size) = adjust_size_sign(Point2D::new(sx, sy), Size2D::new(sw, sh)); - let read_rect = match pixels::clip(origin, size, canvas_size) { - Some(rect) => rect, - None => { - // All the pixels are outside the canvas surface. - return ImageData::new(global, size.width, size.height, None); - }, - }; - - ImageData::new( - global, - size.width, - size.height, - Some(self.get_rect(canvas_size, read_rect)), - ) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata - pub fn PutImageData(&self, canvas_size: Size2D, imagedata: &ImageData, dx: i32, dy: i32) { - self.PutImageData_( - canvas_size, - imagedata, - dx, - dy, - 0, - 0, - imagedata.Width() as i32, - imagedata.Height() as i32, - ) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata - #[allow(unsafe_code)] - pub fn PutImageData_( - &self, - canvas_size: Size2D, - imagedata: &ImageData, - dx: i32, - dy: i32, - dirty_x: i32, - dirty_y: i32, - dirty_width: i32, - dirty_height: i32, - ) { - // FIXME(nox): There are many arithmetic operations here that can - // overflow or underflow, this should probably be audited. - - let imagedata_size = Size2D::new(imagedata.Width(), imagedata.Height()); - if imagedata_size.area() == 0 { - return; - } - - // Step 1. - // Done later. - - // Step 2. - // TODO: throw InvalidState if buffer is detached. - - // Steps 3-6. - let (src_origin, src_size) = adjust_size_sign( - Point2D::new(dirty_x, dirty_y), - Size2D::new(dirty_width, dirty_height), - ); - let src_rect = match pixels::clip(src_origin, src_size, imagedata_size) { - Some(rect) => rect, - None => return, - }; - let (dst_origin, _) = adjust_size_sign( - Point2D::new(dirty_x.saturating_add(dx), dirty_y.saturating_add(dy)), - Size2D::new(dirty_width, dirty_height), - ); - // By clipping to the canvas surface, we avoid sending any pixel - // that would fall outside it. - let dst_rect = match pixels::clip(dst_origin, src_rect.size, canvas_size) { - Some(rect) => rect, - None => return, - }; - - // Step 7. - let (sender, receiver) = ipc::bytes_channel().unwrap(); - let pixels = unsafe { &imagedata.get_rect(Rect::new(src_rect.origin, dst_rect.size)) }; - self.send_canvas_2d_msg(Canvas2dMsg::PutImageData(dst_rect, receiver)); - sender.send(pixels).unwrap(); - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage - pub fn DrawImage( - &self, - canvas: Option<&HTMLCanvasElement>, - image: CanvasImageSource, - dx: f64, - dy: f64, - ) -> ErrorResult { - if !(dx.is_finite() && dy.is_finite()) { - return Ok(()); - } - - self.draw_image(canvas, image, 0f64, 0f64, None, None, dx, dy, None, None) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage - pub fn DrawImage_( - &self, - canvas: Option<&HTMLCanvasElement>, - image: CanvasImageSource, - dx: f64, - dy: f64, - dw: f64, - dh: f64, - ) -> ErrorResult { - if !(dx.is_finite() && dy.is_finite() && dw.is_finite() && dh.is_finite()) { - return Ok(()); - } - - self.draw_image( - canvas, - image, - 0f64, - 0f64, - None, - None, - dx, - dy, - Some(dw), - Some(dh), - ) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage - pub fn DrawImage__( - &self, - canvas: Option<&HTMLCanvasElement>, - image: CanvasImageSource, - sx: f64, - sy: f64, - sw: f64, - sh: f64, - dx: f64, - dy: f64, - dw: f64, - dh: f64, - ) -> ErrorResult { - if !(sx.is_finite() && - sy.is_finite() && - sw.is_finite() && - sh.is_finite() && - dx.is_finite() && - dy.is_finite() && - dw.is_finite() && - dh.is_finite()) - { - return Ok(()); - } - - self.draw_image( - canvas, - image, - sx, - sy, - Some(sw), - Some(sh), - dx, - dy, - Some(dw), - Some(dh), - ) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-beginpath - pub fn BeginPath(&self) { - self.send_canvas_2d_msg(Canvas2dMsg::BeginPath); - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-fill - pub fn Fill(&self, _fill_rule: CanvasFillRule) { - // TODO: Process fill rule - self.send_canvas_2d_msg(Canvas2dMsg::Fill); - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-stroke - pub fn Stroke(&self) { - self.send_canvas_2d_msg(Canvas2dMsg::Stroke); - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-clip - pub fn Clip(&self, _fill_rule: CanvasFillRule) { - // TODO: Process fill rule - self.send_canvas_2d_msg(Canvas2dMsg::Clip); - } +use euclid::default::{Rect, Size2D}; +use ipc_channel::ipc::IpcSender; +use servo_url::ServoUrl; +use std::mem; - // https://html.spec.whatwg.org/multipage/#dom-context-2d-ispointinpath - pub fn IsPointInPath( - &self, - global: &GlobalScope, - x: f64, - y: f64, - fill_rule: CanvasFillRule, - ) -> bool { - let fill_rule = match fill_rule { - CanvasFillRule::Nonzero => FillRule::Nonzero, - CanvasFillRule::Evenodd => FillRule::Evenodd, - }; - let (sender, receiver) = - profiled_ipc::channel::(global.time_profiler_chan().clone()).unwrap(); - self.send_canvas_2d_msg(Canvas2dMsg::IsPointInPath(x, y, fill_rule, sender)); - receiver.recv().unwrap() - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-scale - pub fn Scale(&self, x: f64, y: f64) { - if !(x.is_finite() && y.is_finite()) { - return; - } - - let transform = self.state.borrow().transform; - self.state.borrow_mut().transform = transform.pre_scale(x as f32, y as f32); - self.update_transform() - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-rotate - pub fn Rotate(&self, angle: f64) { - if angle == 0.0 || !angle.is_finite() { - return; - } - - let (sin, cos) = (angle.sin(), angle.cos()); - let transform = self.state.borrow().transform; - self.state.borrow_mut().transform = transform.pre_transform(&Transform2D::row_major( - cos as f32, - sin as f32, - -sin as f32, - cos as f32, - 0.0, - 0.0, - )); - self.update_transform() - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-translate - pub fn Translate(&self, x: f64, y: f64) { - if !(x.is_finite() && y.is_finite()) { - return; - } - - let transform = self.state.borrow().transform; - self.state.borrow_mut().transform = transform.pre_translate(vec2(x as f32, y as f32)); - self.update_transform() - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-transform - pub fn Transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) { - if !(a.is_finite() && - b.is_finite() && - c.is_finite() && - d.is_finite() && - e.is_finite() && - f.is_finite()) - { - return; - } - - let transform = self.state.borrow().transform; - self.state.borrow_mut().transform = transform.pre_transform(&Transform2D::row_major( - a as f32, b as f32, c as f32, d as f32, e as f32, f as f32, - )); - self.update_transform() - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-settransform - pub fn SetTransform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) { - if !(a.is_finite() && - b.is_finite() && - c.is_finite() && - d.is_finite() && - e.is_finite() && - f.is_finite()) - { - return; - } - - self.state.borrow_mut().transform = - Transform2D::row_major(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32); - self.update_transform() - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-resettransform - pub fn ResetTransform(&self) { - self.state.borrow_mut().transform = Transform2D::identity(); - self.update_transform() - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-closepath - pub fn ClosePath(&self) { - self.send_canvas_2d_msg(Canvas2dMsg::ClosePath); - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-moveto - pub fn MoveTo(&self, x: f64, y: f64) { - if !(x.is_finite() && y.is_finite()) { - return; - } - self.send_canvas_2d_msg(Canvas2dMsg::MoveTo(Point2D::new(x as f32, y as f32))); - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-lineto - pub fn LineTo(&self, x: f64, y: f64) { - if !(x.is_finite() && y.is_finite()) { - return; - } - self.send_canvas_2d_msg(Canvas2dMsg::LineTo(Point2D::new(x as f32, y as f32))); - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-rect - pub fn Rect(&self, x: f64, y: f64, width: f64, height: f64) { - if [x, y, width, height].iter().all(|val| val.is_finite()) { - let rect = Rect::new( - Point2D::new(x as f32, y as f32), - Size2D::new(width as f32, height as f32), - ); - self.send_canvas_2d_msg(Canvas2dMsg::Rect(rect)); - } - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-quadraticcurveto - pub fn QuadraticCurveTo(&self, cpx: f64, cpy: f64, x: f64, y: f64) { - if !(cpx.is_finite() && cpy.is_finite() && x.is_finite() && y.is_finite()) { - return; - } - self.send_canvas_2d_msg(Canvas2dMsg::QuadraticCurveTo( - Point2D::new(cpx as f32, cpy as f32), - Point2D::new(x as f32, y as f32), - )); - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-beziercurveto - pub fn BezierCurveTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) { - if !(cp1x.is_finite() && - cp1y.is_finite() && - cp2x.is_finite() && - cp2y.is_finite() && - x.is_finite() && - y.is_finite()) - { - return; - } - self.send_canvas_2d_msg(Canvas2dMsg::BezierCurveTo( - Point2D::new(cp1x as f32, cp1y as f32), - Point2D::new(cp2x as f32, cp2y as f32), - Point2D::new(x as f32, y as f32), - )); - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-arc - pub fn Arc(&self, x: f64, y: f64, r: f64, start: f64, end: f64, ccw: bool) -> ErrorResult { - if !([x, y, r, start, end].iter().all(|x| x.is_finite())) { - return Ok(()); - } - - if r < 0.0 { - return Err(Error::IndexSize); - } - - self.send_canvas_2d_msg(Canvas2dMsg::Arc( - Point2D::new(x as f32, y as f32), - r as f32, - start as f32, - end as f32, - ccw, - )); - Ok(()) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-arcto - pub fn ArcTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, r: f64) -> ErrorResult { - if !([cp1x, cp1y, cp2x, cp2y, r].iter().all(|x| x.is_finite())) { - return Ok(()); - } - if r < 0.0 { - return Err(Error::IndexSize); - } - - self.send_canvas_2d_msg(Canvas2dMsg::ArcTo( - Point2D::new(cp1x as f32, cp1y as f32), - Point2D::new(cp2x as f32, cp2y as f32), - r as f32, - )); - Ok(()) - } - - // https://html.spec.whatwg.org/multipage/#dom-context-2d-ellipse - pub fn Ellipse( - &self, - x: f64, - y: f64, - rx: f64, - ry: f64, - rotation: f64, - start: f64, - end: f64, - ccw: bool, - ) -> ErrorResult { - if !([x, y, rx, ry, rotation, start, end] - .iter() - .all(|x| x.is_finite())) - { - return Ok(()); - } - if rx < 0.0 || ry < 0.0 { - return Err(Error::IndexSize); - } - - self.send_canvas_2d_msg(Canvas2dMsg::Ellipse( - Point2D::new(x as f32, y as f32), - rx as f32, - ry as f32, - rotation as f32, - start as f32, - end as f32, - ccw, - )); - Ok(()) - } +// https://html.spec.whatwg.org/multipage/#canvasrenderingcontext2d +#[dom_struct] +pub struct CanvasRenderingContext2D { + reflector_: Reflector, + /// For rendering contexts created by an HTML canvas element, this is Some, + /// for ones created by a paint worklet, this is None. + canvas: Option>, + canvas_state: DomRefCell, } impl CanvasRenderingContext2D { @@ -1493,7 +73,7 @@ impl CanvasRenderingContext2D { self.reset_to_initial_state(); self.canvas_state .borrow() - .ipc_renderer + .get_ipc_renderer() .send(CanvasMsg::Recreate( size, self.canvas_state.borrow().get_canvas_id(), @@ -1503,11 +83,15 @@ impl CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#reset-the-rendering-context-to-its-default-state fn reset_to_initial_state(&self) { - self.canvas_state.borrow().saved_states.borrow_mut().clear(); - *self.canvas_state.borrow().state.borrow_mut() = CanvasContextState::new(); + self.canvas_state + .borrow() + .get_saved_state() + .borrow_mut() + .clear(); + *self.canvas_state.borrow().get_state().borrow_mut() = CanvasContextState::new(); } - fn mark_as_dirty(&self) { + pub fn mark_as_dirty(&self) { self.canvas_state .borrow() .mark_as_dirty(self.canvas.as_ref().map(|c| &**c)) @@ -1515,7 +99,11 @@ impl CanvasRenderingContext2D { pub fn take_missing_image_urls(&self) -> Vec { mem::replace( - &mut self.canvas_state.borrow().missing_image_urls.borrow_mut(), + &mut self + .canvas_state + .borrow() + .get_missing_image_urls() + .borrow_mut(), vec![], ) } @@ -1529,7 +117,7 @@ impl CanvasRenderingContext2D { } pub fn get_ipc_renderer(&self) -> IpcSender { - self.canvas_state.borrow().ipc_renderer.clone() + self.canvas_state.borrow().get_ipc_renderer().clone() } pub fn origin_is_clean(&self) -> bool { @@ -1559,7 +147,7 @@ impl LayoutCanvasRenderingContext2DHelpers for LayoutDom f64 { - self.canvas_state.borrow().GlobalAlpha() + self.canvas_state.borrow().global_alpha() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha fn SetGlobalAlpha(&self, alpha: f64) { - self.canvas_state.borrow().SetGlobalAlpha(alpha) + self.canvas_state.borrow().set_global_alpha(alpha) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation fn GlobalCompositeOperation(&self) -> DOMString { - self.canvas_state.borrow().GlobalCompositeOperation() + self.canvas_state.borrow().global_composite_operation() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation fn SetGlobalCompositeOperation(&self, op_str: DOMString) { self.canvas_state .borrow() - .SetGlobalCompositeOperation(op_str) + .set_global_composite_operation(op_str) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) { - self.canvas_state.borrow().FillRect(x, y, width, height); + self.canvas_state.borrow().fill_rect(x, y, width, height); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-clearrect fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) { - self.canvas_state.borrow().ClearRect(x, y, width, height); + self.canvas_state.borrow().clear_rect(x, y, width, height); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokerect fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) { - self.canvas_state.borrow().StrokeRect(x, y, width, height); + self.canvas_state.borrow().stroke_rect(x, y, width, height); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-beginpath fn BeginPath(&self) { - self.canvas_state.borrow().BeginPath() + self.canvas_state.borrow().begin_path() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-closepath fn ClosePath(&self) { - self.canvas_state.borrow().ClosePath() + self.canvas_state.borrow().close_path() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-fill fn Fill(&self, fill_rule: CanvasFillRule) { - self.canvas_state.borrow().Fill(fill_rule); + self.canvas_state.borrow().fill(fill_rule); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-stroke fn Stroke(&self) { - self.canvas_state.borrow().Stroke(); + self.canvas_state.borrow().stroke(); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-clip fn Clip(&self, fill_rule: CanvasFillRule) { - self.canvas_state.borrow().Clip(fill_rule) + self.canvas_state.borrow().clip(fill_rule) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-ispointinpath fn IsPointInPath(&self, x: f64, y: f64, fill_rule: CanvasFillRule) -> bool { self.canvas_state .borrow() - .IsPointInPath(&self.global(), x, y, fill_rule) + .is_point_in_path(&self.global(), x, y, fill_rule) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-filltext fn FillText(&self, text: DOMString, x: f64, y: f64, max_width: Option) { - self.canvas_state.borrow().FillText(text, x, y, max_width); + self.canvas_state.borrow().fill_text(text, x, y, max_width); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#textmetrics fn MeasureText(&self, text: DOMString) -> DomRoot { - self.canvas_state.borrow().MeasureText(&self.global(), text) + self.canvas_state + .borrow() + .measure_text(&self.global(), text) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage fn DrawImage(&self, image: CanvasImageSource, dx: f64, dy: f64) -> ErrorResult { self.canvas_state .borrow() - .DrawImage(self.canvas.as_ref().map(|c| &**c), image, dx, dy) + .draw_image(self.canvas.as_ref().map(|c| &**c), image, dx, dy) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage @@ -1731,7 +321,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { dw: f64, dh: f64, ) -> ErrorResult { - self.canvas_state.borrow().DrawImage_( + self.canvas_state.borrow().draw_image_( self.canvas.as_ref().map(|c| &**c), image, dx, @@ -1754,7 +344,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { dw: f64, dh: f64, ) -> ErrorResult { - self.canvas_state.borrow().DrawImage__( + self.canvas_state.borrow().draw_image__( self.canvas.as_ref().map(|c| &**c), image, sx, @@ -1770,39 +360,41 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-moveto fn MoveTo(&self, x: f64, y: f64) { - self.canvas_state.borrow().MoveTo(x, y) + self.canvas_state.borrow().move_to(x, y) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-lineto fn LineTo(&self, x: f64, y: f64) { - self.canvas_state.borrow().LineTo(x, y) + self.canvas_state.borrow().line_to(x, y) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-rect fn Rect(&self, x: f64, y: f64, width: f64, height: f64) { - self.canvas_state.borrow().Rect(x, y, width, height) + self.canvas_state.borrow().rect(x, y, width, height) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-quadraticcurveto fn QuadraticCurveTo(&self, cpx: f64, cpy: f64, x: f64, y: f64) { - self.canvas_state.borrow().QuadraticCurveTo(cpx, cpy, x, y) + self.canvas_state + .borrow() + .quadratic_curve_to(cpx, cpy, x, y) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-beziercurveto fn BezierCurveTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) { self.canvas_state .borrow() - .BezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) + .bezier_curve_to(cp1x, cp1y, cp2x, cp2y, x, y) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-arc fn Arc(&self, x: f64, y: f64, r: f64, start: f64, end: f64, ccw: bool) -> ErrorResult { - self.canvas_state.borrow().Arc(x, y, r, start, end, ccw) + self.canvas_state.borrow().arc(x, y, r, start, end, ccw) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-arcto fn ArcTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, r: f64) -> ErrorResult { - self.canvas_state.borrow().ArcTo(cp1x, cp1y, cp2x, cp2y, r) + self.canvas_state.borrow().arc_to(cp1x, cp1y, cp2x, cp2y, r) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-ellipse @@ -1819,60 +411,62 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { ) -> ErrorResult { self.canvas_state .borrow() - .Ellipse(x, y, rx, ry, rotation, start, end, ccw) + .ellipse(x, y, rx, ry, rotation, start, end, ccw) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-imagesmoothingenabled fn ImageSmoothingEnabled(&self) -> bool { - self.canvas_state.borrow().ImageSmoothingEnabled() + self.canvas_state.borrow().image_smoothing_enabled() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-imagesmoothingenabled fn SetImageSmoothingEnabled(&self, value: bool) { - self.canvas_state.borrow().SetImageSmoothingEnabled(value) + self.canvas_state + .borrow() + .set_image_smoothing_enabled(value) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle fn StrokeStyle(&self) -> StringOrCanvasGradientOrCanvasPattern { - self.canvas_state.borrow().StrokeStyle() + self.canvas_state.borrow().stroke_style() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle fn SetStrokeStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) { self.canvas_state .borrow() - .SetStrokeStyle(self.canvas.as_ref().map(|c| &**c), value) + .set_stroke_style(self.canvas.as_ref().map(|c| &**c), value) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle fn FillStyle(&self) -> StringOrCanvasGradientOrCanvasPattern { - self.canvas_state.borrow().FillStyle() + self.canvas_state.borrow().fill_style() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle fn SetFillStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) { self.canvas_state .borrow() - .SetFillStyle(self.canvas.as_ref().map(|c| &**c), value) + .set_fill_style(self.canvas.as_ref().map(|c| &**c), value) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata fn CreateImageData(&self, sw: i32, sh: i32) -> Fallible> { self.canvas_state .borrow() - .CreateImageData(&self.global(), sw, sh) + .create_image_data(&self.global(), sw, sh) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata fn CreateImageData_(&self, imagedata: &ImageData) -> Fallible> { self.canvas_state .borrow() - .CreateImageData_(&self.global(), imagedata) + .create_image_data_(&self.global(), imagedata) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata fn GetImageData(&self, sx: i32, sy: i32, sw: i32, sh: i32) -> Fallible> { - self.canvas_state.borrow().GetImageData( + self.canvas_state.borrow().get_image_data( self.canvas .as_ref() .map_or(Size2D::zero(), |c| c.get_size()), @@ -1886,7 +480,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata fn PutImageData(&self, imagedata: &ImageData, dx: i32, dy: i32) { - self.canvas_state.borrow().PutImageData( + self.canvas_state.borrow().put_image_data( self.canvas .as_ref() .map_or(Size2D::zero(), |c| c.get_size()), @@ -1908,7 +502,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { dirty_width: i32, dirty_height: i32, ) { - self.canvas_state.borrow().PutImageData_( + self.canvas_state.borrow().put_image_data_( self.canvas .as_ref() .map_or(Size2D::zero(), |c| c.get_size()), @@ -1933,7 +527,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { ) -> DomRoot { self.canvas_state .borrow() - .CreateLinearGradient(&self.global(), x0, y0, x1, y1) + .create_linear_gradient(&self.global(), x0, y0, x1, y1) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createradialgradient @@ -1948,7 +542,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { ) -> Fallible> { self.canvas_state .borrow() - .CreateRadialGradient(&self.global(), x0, y0, r0, x1, y1, r1) + .create_radial_gradient(&self.global(), x0, y0, r0, x1, y1, r1) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern @@ -1959,87 +553,87 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { ) -> Fallible> { self.canvas_state .borrow() - .CreatePattern(&self.global(), image, repetition) + .create_pattern(&self.global(), image, repetition) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth fn LineWidth(&self) -> f64 { - self.canvas_state.borrow().LineWidth() + self.canvas_state.borrow().line_width() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth fn SetLineWidth(&self, width: f64) { - self.canvas_state.borrow().SetLineWidth(width) + self.canvas_state.borrow().set_line_width(width) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap fn LineCap(&self) -> CanvasLineCap { - self.canvas_state.borrow().LineCap() + self.canvas_state.borrow().line_cap() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap fn SetLineCap(&self, cap: CanvasLineCap) { - self.canvas_state.borrow().SetLineCap(cap) + self.canvas_state.borrow().set_line_cap(cap) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin fn LineJoin(&self) -> CanvasLineJoin { - self.canvas_state.borrow().LineJoin() + self.canvas_state.borrow().line_join() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin fn SetLineJoin(&self, join: CanvasLineJoin) { - self.canvas_state.borrow().SetLineJoin(join) + self.canvas_state.borrow().set_line_join(join) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit fn MiterLimit(&self) -> f64 { - self.canvas_state.borrow().MiterLimit() + self.canvas_state.borrow().miter_limit() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit fn SetMiterLimit(&self, limit: f64) { - self.canvas_state.borrow().SetMiterLimit(limit) + self.canvas_state.borrow().set_miter_limit(limit) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx fn ShadowOffsetX(&self) -> f64 { - self.canvas_state.borrow().ShadowOffsetX() + self.canvas_state.borrow().shadow_offset_x() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx fn SetShadowOffsetX(&self, value: f64) { - self.canvas_state.borrow().SetShadowOffsetX(value) + self.canvas_state.borrow().set_shadow_offset_x(value) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety fn ShadowOffsetY(&self) -> f64 { - self.canvas_state.borrow().ShadowOffsetY() + self.canvas_state.borrow().shadow_offset_y() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety fn SetShadowOffsetY(&self, value: f64) { - self.canvas_state.borrow().SetShadowOffsetY(value) + self.canvas_state.borrow().set_shadow_offset_y(value) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur fn ShadowBlur(&self) -> f64 { - self.canvas_state.borrow().ShadowBlur() + self.canvas_state.borrow().shadow_blur() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur fn SetShadowBlur(&self, value: f64) { - self.canvas_state.borrow().SetShadowBlur(value) + self.canvas_state.borrow().set_shadow_blur(value) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor fn ShadowColor(&self) -> DOMString { - self.canvas_state.borrow().ShadowColor() + self.canvas_state.borrow().shadow_color() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor fn SetShadowColor(&self, value: DOMString) { - self.canvas_state.borrow().SetShadowColor(value) + self.canvas_state.borrow().set_shadow_color(value) } } @@ -2048,78 +642,10 @@ impl Drop for CanvasRenderingContext2D { if let Err(err) = self .canvas_state .borrow() - .ipc_renderer + .get_ipc_renderer() .send(CanvasMsg::Close(self.canvas_state.borrow().get_canvas_id())) { warn!("Could not close canvas: {}", err) } } } - -pub fn parse_color(string: &str) -> Result { - let mut input = ParserInput::new(string); - let mut parser = Parser::new(&mut input); - match CSSColor::parse(&mut parser) { - Ok(CSSColor::RGBA(rgba)) => { - if parser.is_exhausted() { - Ok(rgba) - } else { - Err(()) - } - }, - _ => Err(()), - } -} - -// Used by drawImage to determine if a source or destination rectangle is valid -// Origin coordinates and size cannot be negative. Size has to be greater than zero -fn is_rect_valid(rect: Rect) -> bool { - rect.size.width > 0.0 && rect.size.height > 0.0 -} - -// https://html.spec.whatwg.org/multipage/#serialisation-of-a-color -fn serialize(color: &RGBA, dest: &mut W) -> fmt::Result -where - W: fmt::Write, -{ - let red = color.red; - let green = color.green; - let blue = color.blue; - - if color.alpha == 255 { - write!( - dest, - "#{:x}{:x}{:x}{:x}{:x}{:x}", - red >> 4, - red & 0xF, - green >> 4, - green & 0xF, - blue >> 4, - blue & 0xF - ) - } else { - write!( - dest, - "rgba({}, {}, {}, {})", - red, - green, - blue, - color.alpha_f32() - ) - } -} - -fn adjust_size_sign( - mut origin: Point2D, - mut size: Size2D, -) -> (Point2D, Size2D) { - if size.width < 0 { - size.width = -size.width; - origin.x = origin.x.saturating_sub(size.width); - } - if size.height < 0 { - size.height = -size.height; - origin.y = origin.y.saturating_sub(size.height); - } - (origin, size.to_u32()) -} -- cgit v1.2.3 From ec2961920b74fbe0345f72e6007c6d42ae852019 Mon Sep 17 00:00:00 2001 From: Bailey Blankenship Date: Wed, 16 Oct 2019 18:18:27 -0400 Subject: Addresses issues raised in #24465; removes redundancy in set_bitmap_dimensions Removed passing test .ini files and moved euclid extensions to euclidext.rs to factor out redundant code --- components/script/dom/canvasrenderingcontext2d.rs | 28 ++++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 9f6403bec5c..371b31bbdb0 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -22,9 +22,10 @@ use crate::dom::globalscope::GlobalScope; use crate::dom::htmlcanvaselement::HTMLCanvasElement; use crate::dom::imagedata::ImageData; use crate::dom::textmetrics::TextMetrics; +use crate::euclidext::Size2DExt; use canvas_traits::canvas::{Canvas2dMsg, CanvasId, CanvasMsg}; use dom_struct::dom_struct; -use euclid::default::{Rect, Size2D}; +use euclid::default::{Point2D, Rect, Size2D}; use ipc_channel::ipc::IpcSender; use servo_url::ServoUrl; use std::mem; @@ -75,12 +76,13 @@ impl CanvasRenderingContext2D { .borrow() .get_ipc_renderer() .send(CanvasMsg::Recreate( - size, + size.to_u64(), self.canvas_state.borrow().get_canvas_id(), )) .unwrap(); } + // TODO: This duplicates functionality in canvas state // https://html.spec.whatwg.org/multipage/#reset-the-rendering-context-to-its-default-state fn reset_to_initial_state(&self) { self.canvas_state @@ -90,6 +92,15 @@ impl CanvasRenderingContext2D { .clear(); *self.canvas_state.borrow().get_state().borrow_mut() = CanvasContextState::new(); } + /* + pub fn get_canvas_state(&self) -> Ref { + self.canvas_state.borrow() + } + */ + + pub fn set_canvas_bitmap_dimensions(&self, size: Size2D) { + self.canvas_state.borrow().set_bitmap_dimensions(size); + } pub fn mark_as_dirty(&self) { self.canvas_state @@ -116,6 +127,7 @@ impl CanvasRenderingContext2D { self.canvas_state.borrow().send_canvas_2d_msg(msg) } + // TODO: Remove this pub fn get_ipc_renderer(&self) -> IpcSender { self.canvas_state.borrow().get_ipc_renderer().clone() } @@ -125,10 +137,14 @@ impl CanvasRenderingContext2D { } pub fn get_rect(&self, rect: Rect) -> Vec { + let rect = Rect::new( + Point2D::new(rect.origin.x as u64, rect.origin.y as u64), + Size2D::new(rect.size.width as u64, rect.size.height as u64), + ); self.canvas_state.borrow().get_rect( self.canvas .as_ref() - .map_or(Size2D::zero(), |c| c.get_size()), + .map_or(Size2D::zero(), |c| c.get_size().to_u64()), rect, ) } @@ -469,7 +485,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { self.canvas_state.borrow().get_image_data( self.canvas .as_ref() - .map_or(Size2D::zero(), |c| c.get_size()), + .map_or(Size2D::zero(), |c| c.get_size().to_u64()), &self.global(), sx, sy, @@ -483,7 +499,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { self.canvas_state.borrow().put_image_data( self.canvas .as_ref() - .map_or(Size2D::zero(), |c| c.get_size()), + .map_or(Size2D::zero(), |c| c.get_size().to_u64()), imagedata, dx, dy, @@ -505,7 +521,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { self.canvas_state.borrow().put_image_data_( self.canvas .as_ref() - .map_or(Size2D::zero(), |c| c.get_size()), + .map_or(Size2D::zero(), |c| c.get_size().to_u64()), imagedata, dx, dy, -- cgit v1.2.3 From 481ef4616709840db0145f3bc4003f74f0ff126d Mon Sep 17 00:00:00 2001 From: pylbrecht Date: Fri, 7 Feb 2020 21:56:58 +0100 Subject: Make create_pattern() return None for incomplete images --- components/script/dom/canvasrenderingcontext2d.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 371b31bbdb0..4c36a22f717 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -566,7 +566,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { &self, image: CanvasImageSource, repetition: DOMString, - ) -> Fallible> { + ) -> Fallible>> { self.canvas_state .borrow() .create_pattern(&self.global(), image, repetition) -- cgit v1.2.3 From 588c09b5807bd9534aa63cbb11cff5c0227efdab Mon Sep 17 00:00:00 2001 From: pylbrecht Date: Tue, 11 Feb 2020 22:36:50 +0100 Subject: Implement CanvasRenderingContext2D.getTransform() --- components/script/dom/canvasrenderingcontext2d.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 4c36a22f717..5956827d654 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -18,6 +18,7 @@ use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom}; use crate::dom::bindings::str::DOMString; use crate::dom::canvasgradient::CanvasGradient; use crate::dom::canvaspattern::CanvasPattern; +use crate::dom::dommatrix::DOMMatrix; use crate::dom::globalscope::GlobalScope; use crate::dom::htmlcanvaselement::HTMLCanvasElement; use crate::dom::imagedata::ImageData; @@ -224,6 +225,11 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { self.canvas_state.borrow().transform(a, b, c, d, e, f) } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-gettransform + fn GetTransform(&self) -> DomRoot { + self.canvas_state.borrow().get_transform(&self.global()) + } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-settransform fn SetTransform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) { self.canvas_state.borrow().set_transform(a, b, c, d, e, f) -- cgit v1.2.3 From 3ea6d87bcc37167464e856949a4b9b77d0e9318a Mon Sep 17 00:00:00 2001 From: YUAN LYU Date: Fri, 20 Mar 2020 22:14:18 -0400 Subject: Add trait DomObjectWrap to provide WRAP function --- components/script/dom/canvasrenderingcontext2d.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 5956827d654..fc34cab49eb 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -4,7 +4,6 @@ use crate::canvas_state::{CanvasContextState, CanvasState}; use crate::dom::bindings::cell::DomRefCell; -use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasFillRule; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasImageSource; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineCap; @@ -67,7 +66,7 @@ impl CanvasRenderingContext2D { Some(canvas), size, )); - reflect_dom_object(boxed, global, CanvasRenderingContext2DBinding::Wrap) + reflect_dom_object(boxed, global) } // https://html.spec.whatwg.org/multipage/#concept-canvas-set-bitmap-dimensions -- cgit v1.2.3 From dba6a635e5df980b2837495aae59711739c23716 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Fri, 27 Mar 2020 17:37:56 +0100 Subject: Give a lifetime parameter to LayoutDom --- components/script/dom/canvasrenderingcontext2d.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index fc34cab49eb..d6c01c6a145 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -157,7 +157,7 @@ pub trait LayoutCanvasRenderingContext2DHelpers { unsafe fn get_canvas_id(&self) -> CanvasId; } -impl LayoutCanvasRenderingContext2DHelpers for LayoutDom { +impl LayoutCanvasRenderingContext2DHelpers for LayoutDom<'_, CanvasRenderingContext2D> { #[allow(unsafe_code)] unsafe fn get_ipc_renderer(&self) -> IpcSender { (*self.unsafe_get()) -- cgit v1.2.3 From 9d337ea013c0f3568e4bd3a23e746ae55922b937 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 29 Mar 2020 16:08:53 +0200 Subject: Make LayoutCanvasRenderingContext2DHelpers methods take self --- components/script/dom/canvasrenderingcontext2d.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index d6c01c6a145..f386cb64c2d 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -152,14 +152,14 @@ impl CanvasRenderingContext2D { pub trait LayoutCanvasRenderingContext2DHelpers { #[allow(unsafe_code)] - unsafe fn get_ipc_renderer(&self) -> IpcSender; + unsafe fn get_ipc_renderer(self) -> IpcSender; #[allow(unsafe_code)] - unsafe fn get_canvas_id(&self) -> CanvasId; + unsafe fn get_canvas_id(self) -> CanvasId; } impl LayoutCanvasRenderingContext2DHelpers for LayoutDom<'_, CanvasRenderingContext2D> { #[allow(unsafe_code)] - unsafe fn get_ipc_renderer(&self) -> IpcSender { + unsafe fn get_ipc_renderer(self) -> IpcSender { (*self.unsafe_get()) .canvas_state .borrow_for_layout() @@ -168,7 +168,7 @@ impl LayoutCanvasRenderingContext2DHelpers for LayoutDom<'_, CanvasRenderingCont } #[allow(unsafe_code)] - unsafe fn get_canvas_id(&self) -> CanvasId { + unsafe fn get_canvas_id(self) -> CanvasId { (*self.unsafe_get()) .canvas_state .borrow_for_layout() -- cgit v1.2.3 From e56191106693f5cbfd1978ead55d410cc43663a0 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 31 Mar 2020 20:58:20 +0200 Subject: Make LayoutCanvasRenderingContext2DHelpers::get_canvas_id be safe --- components/script/dom/canvasrenderingcontext2d.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index f386cb64c2d..bb60a591060 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -153,8 +153,7 @@ impl CanvasRenderingContext2D { pub trait LayoutCanvasRenderingContext2DHelpers { #[allow(unsafe_code)] unsafe fn get_ipc_renderer(self) -> IpcSender; - #[allow(unsafe_code)] - unsafe fn get_canvas_id(self) -> CanvasId; + fn get_canvas_id(self) -> CanvasId; } impl LayoutCanvasRenderingContext2DHelpers for LayoutDom<'_, CanvasRenderingContext2D> { @@ -168,11 +167,16 @@ impl LayoutCanvasRenderingContext2DHelpers for LayoutDom<'_, CanvasRenderingCont } #[allow(unsafe_code)] - unsafe fn get_canvas_id(self) -> CanvasId { - (*self.unsafe_get()) - .canvas_state - .borrow_for_layout() - .get_canvas_id() + fn get_canvas_id(self) -> CanvasId { + // FIXME(nox): This relies on the fact that CanvasState::get_canvas_id + // does nothing fancy but it would be easier to trust a + // LayoutDom<_>-like type that would wrap the &CanvasState. + unsafe { + self.unsafe_get() + .canvas_state + .borrow_for_layout() + .get_canvas_id() + } } } -- cgit v1.2.3 From fccfff11c521377c91a26729710d54920379a8eb Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 6 Apr 2020 17:41:55 -0700 Subject: Update euclid --- components/script/dom/canvasrenderingcontext2d.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index bb60a591060..3dff7403464 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -22,7 +22,6 @@ use crate::dom::globalscope::GlobalScope; use crate::dom::htmlcanvaselement::HTMLCanvasElement; use crate::dom::imagedata::ImageData; use crate::dom::textmetrics::TextMetrics; -use crate::euclidext::Size2DExt; use canvas_traits::canvas::{Canvas2dMsg, CanvasId, CanvasMsg}; use dom_struct::dom_struct; use euclid::default::{Point2D, Rect, Size2D}; -- cgit v1.2.3 From d98ade2a687324a700a30099b5bf02bb7fa84f12 Mon Sep 17 00:00:00 2001 From: Utsav Oza Date: Wed, 8 Apr 2020 19:55:05 +0530 Subject: Remove DomRefCell wrapper for canvas_state from CanvasRenderingContext2D --- components/script/dom/canvasrenderingcontext2d.rs | 190 ++++++++-------------- 1 file changed, 72 insertions(+), 118 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 3dff7403464..2270fdeb65a 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -36,7 +36,7 @@ pub struct CanvasRenderingContext2D { /// For rendering contexts created by an HTML canvas element, this is Some, /// for ones created by a paint worklet, this is None. canvas: Option>, - canvas_state: DomRefCell, + canvas_state: CanvasState, } impl CanvasRenderingContext2D { @@ -48,10 +48,10 @@ impl CanvasRenderingContext2D { CanvasRenderingContext2D { reflector_: Reflector::new(), canvas: canvas.map(Dom::from_ref), - canvas_state: DomRefCell::new(CanvasState::new( + canvas_state: CanvasState::new( global, Size2D::new(size.width as u64, size.height as u64), - )), + ), } } @@ -72,11 +72,10 @@ impl CanvasRenderingContext2D { pub fn set_bitmap_dimensions(&self, size: Size2D) { self.reset_to_initial_state(); self.canvas_state - .borrow() .get_ipc_renderer() .send(CanvasMsg::Recreate( size.to_u64(), - self.canvas_state.borrow().get_canvas_id(), + self.canvas_state.get_canvas_id(), )) .unwrap(); } @@ -84,12 +83,8 @@ impl CanvasRenderingContext2D { // TODO: This duplicates functionality in canvas state // https://html.spec.whatwg.org/multipage/#reset-the-rendering-context-to-its-default-state fn reset_to_initial_state(&self) { - self.canvas_state - .borrow() - .get_saved_state() - .borrow_mut() - .clear(); - *self.canvas_state.borrow().get_state().borrow_mut() = CanvasContextState::new(); + self.canvas_state.get_saved_state().borrow_mut().clear(); + *self.canvas_state.get_state().borrow_mut() = CanvasContextState::new(); } /* pub fn get_canvas_state(&self) -> Ref { @@ -98,41 +93,36 @@ impl CanvasRenderingContext2D { */ pub fn set_canvas_bitmap_dimensions(&self, size: Size2D) { - self.canvas_state.borrow().set_bitmap_dimensions(size); + self.canvas_state.set_bitmap_dimensions(size); } pub fn mark_as_dirty(&self) { self.canvas_state - .borrow() .mark_as_dirty(self.canvas.as_ref().map(|c| &**c)) } pub fn take_missing_image_urls(&self) -> Vec { mem::replace( - &mut self - .canvas_state - .borrow() - .get_missing_image_urls() - .borrow_mut(), + &mut self.canvas_state.get_missing_image_urls().borrow_mut(), vec![], ) } pub fn get_canvas_id(&self) -> CanvasId { - self.canvas_state.borrow().get_canvas_id() + self.canvas_state.get_canvas_id() } pub fn send_canvas_2d_msg(&self, msg: Canvas2dMsg) { - self.canvas_state.borrow().send_canvas_2d_msg(msg) + self.canvas_state.send_canvas_2d_msg(msg) } // TODO: Remove this pub fn get_ipc_renderer(&self) -> IpcSender { - self.canvas_state.borrow().get_ipc_renderer().clone() + self.canvas_state.get_ipc_renderer().clone() } pub fn origin_is_clean(&self) -> bool { - self.canvas_state.borrow().origin_is_clean() + self.canvas_state.origin_is_clean() } pub fn get_rect(&self, rect: Rect) -> Vec { @@ -140,7 +130,7 @@ impl CanvasRenderingContext2D { Point2D::new(rect.origin.x as u64, rect.origin.y as u64), Size2D::new(rect.size.width as u64, rect.size.height as u64), ); - self.canvas_state.borrow().get_rect( + self.canvas_state.get_rect( self.canvas .as_ref() .map_or(Size2D::zero(), |c| c.get_size().to_u64()), @@ -158,11 +148,7 @@ pub trait LayoutCanvasRenderingContext2DHelpers { impl LayoutCanvasRenderingContext2DHelpers for LayoutDom<'_, CanvasRenderingContext2D> { #[allow(unsafe_code)] unsafe fn get_ipc_renderer(self) -> IpcSender { - (*self.unsafe_get()) - .canvas_state - .borrow_for_layout() - .get_ipc_renderer() - .clone() + (*self.unsafe_get()).canvas_state.get_ipc_renderer().clone() } #[allow(unsafe_code)] @@ -170,12 +156,7 @@ impl LayoutCanvasRenderingContext2DHelpers for LayoutDom<'_, CanvasRenderingCont // FIXME(nox): This relies on the fact that CanvasState::get_canvas_id // does nothing fancy but it would be easier to trust a // LayoutDom<_>-like type that would wrap the &CanvasState. - unsafe { - self.unsafe_get() - .canvas_state - .borrow_for_layout() - .get_canvas_id() - } + unsafe { self.unsafe_get().canvas_state.get_canvas_id() } } } @@ -198,141 +179,135 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-save fn Save(&self) { - self.canvas_state.borrow().save() + self.canvas_state.save() } #[allow(unrooted_must_root)] // https://html.spec.whatwg.org/multipage/#dom-context-2d-restore fn Restore(&self) { - self.canvas_state.borrow().restore() + self.canvas_state.restore() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-scale fn Scale(&self, x: f64, y: f64) { - self.canvas_state.borrow().scale(x, y) + self.canvas_state.scale(x, y) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-rotate fn Rotate(&self, angle: f64) { - self.canvas_state.borrow().rotate(angle) + self.canvas_state.rotate(angle) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-translate fn Translate(&self, x: f64, y: f64) { - self.canvas_state.borrow().translate(x, y) + self.canvas_state.translate(x, y) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-transform fn Transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) { - self.canvas_state.borrow().transform(a, b, c, d, e, f) + self.canvas_state.transform(a, b, c, d, e, f) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-gettransform fn GetTransform(&self) -> DomRoot { - self.canvas_state.borrow().get_transform(&self.global()) + self.canvas_state.get_transform(&self.global()) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-settransform fn SetTransform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) { - self.canvas_state.borrow().set_transform(a, b, c, d, e, f) + self.canvas_state.set_transform(a, b, c, d, e, f) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-resettransform fn ResetTransform(&self) { - self.canvas_state.borrow().reset_transform() + self.canvas_state.reset_transform() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha fn GlobalAlpha(&self) -> f64 { - self.canvas_state.borrow().global_alpha() + self.canvas_state.global_alpha() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha fn SetGlobalAlpha(&self, alpha: f64) { - self.canvas_state.borrow().set_global_alpha(alpha) + self.canvas_state.set_global_alpha(alpha) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation fn GlobalCompositeOperation(&self) -> DOMString { - self.canvas_state.borrow().global_composite_operation() + self.canvas_state.global_composite_operation() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation fn SetGlobalCompositeOperation(&self, op_str: DOMString) { - self.canvas_state - .borrow() - .set_global_composite_operation(op_str) + self.canvas_state.set_global_composite_operation(op_str) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) { - self.canvas_state.borrow().fill_rect(x, y, width, height); + self.canvas_state.fill_rect(x, y, width, height); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-clearrect fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) { - self.canvas_state.borrow().clear_rect(x, y, width, height); + self.canvas_state.clear_rect(x, y, width, height); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokerect fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) { - self.canvas_state.borrow().stroke_rect(x, y, width, height); + self.canvas_state.stroke_rect(x, y, width, height); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-beginpath fn BeginPath(&self) { - self.canvas_state.borrow().begin_path() + self.canvas_state.begin_path() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-closepath fn ClosePath(&self) { - self.canvas_state.borrow().close_path() + self.canvas_state.close_path() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-fill fn Fill(&self, fill_rule: CanvasFillRule) { - self.canvas_state.borrow().fill(fill_rule); + self.canvas_state.fill(fill_rule); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-stroke fn Stroke(&self) { - self.canvas_state.borrow().stroke(); + self.canvas_state.stroke(); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-clip fn Clip(&self, fill_rule: CanvasFillRule) { - self.canvas_state.borrow().clip(fill_rule) + self.canvas_state.clip(fill_rule) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-ispointinpath fn IsPointInPath(&self, x: f64, y: f64, fill_rule: CanvasFillRule) -> bool { self.canvas_state - .borrow() .is_point_in_path(&self.global(), x, y, fill_rule) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-filltext fn FillText(&self, text: DOMString, x: f64, y: f64, max_width: Option) { - self.canvas_state.borrow().fill_text(text, x, y, max_width); + self.canvas_state.fill_text(text, x, y, max_width); self.mark_as_dirty(); } // https://html.spec.whatwg.org/multipage/#textmetrics fn MeasureText(&self, text: DOMString) -> DomRoot { - self.canvas_state - .borrow() - .measure_text(&self.global(), text) + self.canvas_state.measure_text(&self.global(), text) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage fn DrawImage(&self, image: CanvasImageSource, dx: f64, dy: f64) -> ErrorResult { self.canvas_state - .borrow() .draw_image(self.canvas.as_ref().map(|c| &**c), image, dx, dy) } @@ -345,14 +320,8 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { dw: f64, dh: f64, ) -> ErrorResult { - self.canvas_state.borrow().draw_image_( - self.canvas.as_ref().map(|c| &**c), - image, - dx, - dy, - dw, - dh, - ) + self.canvas_state + .draw_image_(self.canvas.as_ref().map(|c| &**c), image, dx, dy, dw, dh) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage @@ -368,7 +337,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { dw: f64, dh: f64, ) -> ErrorResult { - self.canvas_state.borrow().draw_image__( + self.canvas_state.draw_image__( self.canvas.as_ref().map(|c| &**c), image, sx, @@ -384,41 +353,38 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-moveto fn MoveTo(&self, x: f64, y: f64) { - self.canvas_state.borrow().move_to(x, y) + self.canvas_state.move_to(x, y) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-lineto fn LineTo(&self, x: f64, y: f64) { - self.canvas_state.borrow().line_to(x, y) + self.canvas_state.line_to(x, y) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-rect fn Rect(&self, x: f64, y: f64, width: f64, height: f64) { - self.canvas_state.borrow().rect(x, y, width, height) + self.canvas_state.rect(x, y, width, height) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-quadraticcurveto fn QuadraticCurveTo(&self, cpx: f64, cpy: f64, x: f64, y: f64) { - self.canvas_state - .borrow() - .quadratic_curve_to(cpx, cpy, x, y) + self.canvas_state.quadratic_curve_to(cpx, cpy, x, y) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-beziercurveto fn BezierCurveTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) { self.canvas_state - .borrow() .bezier_curve_to(cp1x, cp1y, cp2x, cp2y, x, y) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-arc fn Arc(&self, x: f64, y: f64, r: f64, start: f64, end: f64, ccw: bool) -> ErrorResult { - self.canvas_state.borrow().arc(x, y, r, start, end, ccw) + self.canvas_state.arc(x, y, r, start, end, ccw) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-arcto fn ArcTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, r: f64) -> ErrorResult { - self.canvas_state.borrow().arc_to(cp1x, cp1y, cp2x, cp2y, r) + self.canvas_state.arc_to(cp1x, cp1y, cp2x, cp2y, r) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-ellipse @@ -434,63 +400,55 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { ccw: bool, ) -> ErrorResult { self.canvas_state - .borrow() .ellipse(x, y, rx, ry, rotation, start, end, ccw) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-imagesmoothingenabled fn ImageSmoothingEnabled(&self) -> bool { - self.canvas_state.borrow().image_smoothing_enabled() + self.canvas_state.image_smoothing_enabled() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-imagesmoothingenabled fn SetImageSmoothingEnabled(&self, value: bool) { - self.canvas_state - .borrow() - .set_image_smoothing_enabled(value) + self.canvas_state.set_image_smoothing_enabled(value) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle fn StrokeStyle(&self) -> StringOrCanvasGradientOrCanvasPattern { - self.canvas_state.borrow().stroke_style() + self.canvas_state.stroke_style() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle fn SetStrokeStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) { self.canvas_state - .borrow() .set_stroke_style(self.canvas.as_ref().map(|c| &**c), value) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle fn FillStyle(&self) -> StringOrCanvasGradientOrCanvasPattern { - self.canvas_state.borrow().fill_style() + self.canvas_state.fill_style() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle fn SetFillStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) { self.canvas_state - .borrow() .set_fill_style(self.canvas.as_ref().map(|c| &**c), value) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata fn CreateImageData(&self, sw: i32, sh: i32) -> Fallible> { - self.canvas_state - .borrow() - .create_image_data(&self.global(), sw, sh) + self.canvas_state.create_image_data(&self.global(), sw, sh) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata fn CreateImageData_(&self, imagedata: &ImageData) -> Fallible> { self.canvas_state - .borrow() .create_image_data_(&self.global(), imagedata) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata fn GetImageData(&self, sx: i32, sy: i32, sw: i32, sh: i32) -> Fallible> { - self.canvas_state.borrow().get_image_data( + self.canvas_state.get_image_data( self.canvas .as_ref() .map_or(Size2D::zero(), |c| c.get_size().to_u64()), @@ -504,7 +462,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata fn PutImageData(&self, imagedata: &ImageData, dx: i32, dy: i32) { - self.canvas_state.borrow().put_image_data( + self.canvas_state.put_image_data( self.canvas .as_ref() .map_or(Size2D::zero(), |c| c.get_size().to_u64()), @@ -526,7 +484,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { dirty_width: i32, dirty_height: i32, ) { - self.canvas_state.borrow().put_image_data_( + self.canvas_state.put_image_data_( self.canvas .as_ref() .map_or(Size2D::zero(), |c| c.get_size().to_u64()), @@ -550,7 +508,6 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { y1: Finite, ) -> DomRoot { self.canvas_state - .borrow() .create_linear_gradient(&self.global(), x0, y0, x1, y1) } @@ -565,7 +522,6 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { r1: Finite, ) -> Fallible> { self.canvas_state - .borrow() .create_radial_gradient(&self.global(), x0, y0, r0, x1, y1, r1) } @@ -576,88 +532,87 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { repetition: DOMString, ) -> Fallible>> { self.canvas_state - .borrow() .create_pattern(&self.global(), image, repetition) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth fn LineWidth(&self) -> f64 { - self.canvas_state.borrow().line_width() + self.canvas_state.line_width() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth fn SetLineWidth(&self, width: f64) { - self.canvas_state.borrow().set_line_width(width) + self.canvas_state.set_line_width(width) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap fn LineCap(&self) -> CanvasLineCap { - self.canvas_state.borrow().line_cap() + self.canvas_state.line_cap() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap fn SetLineCap(&self, cap: CanvasLineCap) { - self.canvas_state.borrow().set_line_cap(cap) + self.canvas_state.set_line_cap(cap) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin fn LineJoin(&self) -> CanvasLineJoin { - self.canvas_state.borrow().line_join() + self.canvas_state.line_join() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin fn SetLineJoin(&self, join: CanvasLineJoin) { - self.canvas_state.borrow().set_line_join(join) + self.canvas_state.set_line_join(join) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit fn MiterLimit(&self) -> f64 { - self.canvas_state.borrow().miter_limit() + self.canvas_state.miter_limit() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit fn SetMiterLimit(&self, limit: f64) { - self.canvas_state.borrow().set_miter_limit(limit) + self.canvas_state.set_miter_limit(limit) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx fn ShadowOffsetX(&self) -> f64 { - self.canvas_state.borrow().shadow_offset_x() + self.canvas_state.shadow_offset_x() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx fn SetShadowOffsetX(&self, value: f64) { - self.canvas_state.borrow().set_shadow_offset_x(value) + self.canvas_state.set_shadow_offset_x(value) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety fn ShadowOffsetY(&self) -> f64 { - self.canvas_state.borrow().shadow_offset_y() + self.canvas_state.shadow_offset_y() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety fn SetShadowOffsetY(&self, value: f64) { - self.canvas_state.borrow().set_shadow_offset_y(value) + self.canvas_state.set_shadow_offset_y(value) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur fn ShadowBlur(&self) -> f64 { - self.canvas_state.borrow().shadow_blur() + self.canvas_state.shadow_blur() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur fn SetShadowBlur(&self, value: f64) { - self.canvas_state.borrow().set_shadow_blur(value) + self.canvas_state.set_shadow_blur(value) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor fn ShadowColor(&self) -> DOMString { - self.canvas_state.borrow().shadow_color() + self.canvas_state.shadow_color() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor fn SetShadowColor(&self, value: DOMString) { - self.canvas_state.borrow().set_shadow_color(value) + self.canvas_state.set_shadow_color(value) } } @@ -665,9 +620,8 @@ impl Drop for CanvasRenderingContext2D { fn drop(&mut self) { if let Err(err) = self .canvas_state - .borrow() .get_ipc_renderer() - .send(CanvasMsg::Close(self.canvas_state.borrow().get_canvas_id())) + .send(CanvasMsg::Close(self.canvas_state.get_canvas_id())) { warn!("Could not close canvas: {}", err) } -- cgit v1.2.3 From bd8fbee12c44e8360dead8b897aabe1b563700de Mon Sep 17 00:00:00 2001 From: Utsav Oza Date: Wed, 8 Apr 2020 21:38:50 +0530 Subject: Resolve mach build warnings --- components/script/dom/canvasrenderingcontext2d.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 2270fdeb65a..4820a3bbfd7 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -2,8 +2,7 @@ * 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 crate::canvas_state::{CanvasContextState, CanvasState}; -use crate::dom::bindings::cell::DomRefCell; +use crate::canvas_state::CanvasState; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasFillRule; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasImageSource; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineCap; @@ -80,17 +79,10 @@ impl CanvasRenderingContext2D { .unwrap(); } - // TODO: This duplicates functionality in canvas state // https://html.spec.whatwg.org/multipage/#reset-the-rendering-context-to-its-default-state fn reset_to_initial_state(&self) { - self.canvas_state.get_saved_state().borrow_mut().clear(); - *self.canvas_state.get_state().borrow_mut() = CanvasContextState::new(); + self.canvas_state.reset_to_initial_state(); } - /* - pub fn get_canvas_state(&self) -> Ref { - self.canvas_state.borrow() - } - */ pub fn set_canvas_bitmap_dimensions(&self, size: Size2D) { self.canvas_state.set_bitmap_dimensions(size); -- cgit v1.2.3 From 7883718c125f2580490254efdf0aac952b50ce3d Mon Sep 17 00:00:00 2001 From: Utsav Oza Date: Thu, 28 May 2020 00:28:42 +0530 Subject: Query layout to resolve canvas font property value --- components/script/dom/canvasrenderingcontext2d.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 4820a3bbfd7..3e0df6bb4b9 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -297,6 +297,17 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { self.canvas_state.measure_text(&self.global(), text) } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-font + fn Font(&self) -> DOMString { + self.canvas_state.font() + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-font + fn SetFont(&self, value: DOMString) { + self.canvas_state + .set_font(self.canvas.as_ref().map(|c| &**c), value) + } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage fn DrawImage(&self, image: CanvasImageSource, dx: f64, dy: f64) -> ErrorResult { self.canvas_state -- cgit v1.2.3 From 15fd256302cc4401e0c4e2d154d473bfaa16223d Mon Sep 17 00:00:00 2001 From: Utsav Oza Date: Wed, 3 Jun 2020 15:47:44 +0530 Subject: Store resolved font style in canvas context state --- components/script/dom/canvasrenderingcontext2d.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 3e0df6bb4b9..c8838fe283e 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -288,7 +288,8 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/#dom-context-2d-filltext fn FillText(&self, text: DOMString, x: f64, y: f64, max_width: Option) { - self.canvas_state.fill_text(text, x, y, max_width); + self.canvas_state + .fill_text(self.canvas.as_ref().map(|c| &**c), text, x, y, max_width); self.mark_as_dirty(); } -- cgit v1.2.3 From 34d0c313dccc7e12b4409e10ec1f7ffae63e4528 Mon Sep 17 00:00:00 2001 From: Utsav Oza Date: Sun, 7 Jun 2020 01:38:04 +0530 Subject: Enable textAlign, textBaseline and direction attributes for canvas --- components/script/dom/canvasrenderingcontext2d.rs | 33 +++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'components/script/dom/canvasrenderingcontext2d.rs') diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index c8838fe283e..3ebf8f130d9 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -3,11 +3,14 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::canvas_state::CanvasState; +use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasDirection; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasFillRule; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasImageSource; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineCap; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineJoin; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods; +use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasTextAlign; +use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasTextBaseline; use crate::dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern; use crate::dom::bindings::error::{ErrorResult, Fallible}; use crate::dom::bindings::num::Finite; @@ -309,6 +312,36 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { .set_font(self.canvas.as_ref().map(|c| &**c), value) } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-textalign + fn TextAlign(&self) -> CanvasTextAlign { + self.canvas_state.text_align() + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-textalign + fn SetTextAlign(&self, value: CanvasTextAlign) { + self.canvas_state.set_text_align(value) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-textbaseline + fn TextBaseline(&self) -> CanvasTextBaseline { + self.canvas_state.text_baseline() + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-textbaseline + fn SetTextBaseline(&self, value: CanvasTextBaseline) { + self.canvas_state.set_text_baseline(value) + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-direction + fn Direction(&self) -> CanvasDirection { + self.canvas_state.direction() + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-direction + fn SetDirection(&self, value: CanvasDirection) { + self.canvas_state.set_direction(value) + } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage fn DrawImage(&self, image: CanvasImageSource, dx: f64, dy: f64) -> ErrorResult { self.canvas_state -- cgit v1.2.3