diff options
author | Hanif Bin Ariffin <hanif.ariffin.4326@gmail.com> | 2019-10-21 05:24:49 -0400 |
---|---|---|
committer | Hanif Bin Ariffin <hanif.ariffin.4326@gmail.com> | 2019-10-25 02:27:57 -0400 |
commit | 31ff2d43ccc835bffc99aac596dabae1d23cc5f7 (patch) | |
tree | 6b088758d3f921822c3888f8d5433dea56e74218 /components/script/dom/canvasrenderingcontext2d.rs | |
parent | 08af89bd8205ac28c98b9a079216fca438a9ed66 (diff) | |
download | servo-31ff2d43ccc835bffc99aac596dabae1d23cc5f7.tar.gz servo-31ff2d43ccc835bffc99aac596dabae1d23cc5f7.zip |
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)
Diffstat (limited to 'components/script/dom/canvasrenderingcontext2d.rs')
-rw-r--r-- | components/script/dom/canvasrenderingcontext2d.rs | 1662 |
1 files changed, 94 insertions, 1568 deletions
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,61 +10,24 @@ 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<CanvasGradient>), - Pattern(Dom<CanvasPattern>), -} +use euclid::default::{Rect, Size2D}; +use ipc_channel::ipc::IpcSender; +use servo_url::ServoUrl; +use std::mem; // https://html.spec.whatwg.org/multipage/#canvasrenderingcontext2d #[dom_struct] @@ -75,1390 +39,6 @@ pub struct CanvasRenderingContext2D { canvas_state: DomRefCell<CanvasState>, } -#[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<f32>, - 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<CanvasMsg>, - canvas_id: CanvasId, - state: DomRefCell<CanvasContextState>, - origin_clean: Cell<bool>, - #[ignore_malloc_size_of = "Arc"] - image_cache: Arc<dyn ImageCache>, - /// 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<Vec<ServoUrl>>, - saved_states: DomRefCell<Vec<CanvasContextState>>, -} - -impl CanvasState { - pub fn new(global: &GlobalScope, size: Size2D<u64>) -> 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::<PaintWorkletGlobalScope>() { - 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<Rect<f32>> { - 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<CorsSettings>, - ) -> Option<(Vec<u8>, Size2D<u32>)> { - 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<CorsSettings>, - ) -> 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<RGBA, ()> { - 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::<Element>(); - - 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<u32>, rect: Rect<u32>) -> Vec<u8> { - 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<f64>, - sh: Option<f64>, - dx: f64, - dy: f64, - dw: Option<f64>, - dh: Option<f64>, - ) -> 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<f64>, - sh: Option<f64>, - dx: f64, - dy: f64, - dw: Option<f64>, - dh: Option<f64>, - ) -> 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<CorsSettings>, - sx: f64, - sy: f64, - sw: Option<f64>, - sh: Option<f64>, - dx: f64, - dy: f64, - dw: Option<f64>, - dh: Option<f64>, - ) -> 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::<Node>().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<f64>, - sx: f64, - sy: f64, - sw: f64, - sh: f64, - dx: f64, - dy: f64, - dw: f64, - dh: f64, - ) -> (Rect<f64>, Rect<f64>) { - 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<f64>, - y0: Finite<f64>, - x1: Finite<f64>, - y1: Finite<f64>, - ) -> DomRoot<CanvasGradient> { - 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<f64>, - y0: Finite<f64>, - r0: Finite<f64>, - x1: Finite<f64>, - y1: Finite<f64>, - r1: Finite<f64>, - ) -> Fallible<DomRoot<CanvasGradient>> { - 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<DomRoot<CanvasPattern>> { - 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<f64>) { - 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<TextMetrics> { - // 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<DomRoot<ImageData>> { - 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<DomRoot<ImageData>> { - 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<u32>, - global: &GlobalScope, - sx: i32, - sy: i32, - sw: i32, - sh: i32, - ) -> Fallible<DomRoot<ImageData>> { - // 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<u32>, 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<u32>, - 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); - } - - // 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::<bool>(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(()) - } -} - impl CanvasRenderingContext2D { pub fn new_inherited( global: &GlobalScope, @@ -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<ServoUrl> { 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<CanvasMsg> { - 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<CanvasRenderingContext2 (*self.unsafe_get()) .canvas_state .borrow_for_layout() - .ipc_renderer + .get_ipc_renderer() .clone() } @@ -1591,135 +179,137 @@ 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.borrow().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.borrow().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.borrow().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.borrow().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.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) { - self.canvas_state.borrow().Transform(a, b, c, d, e, f) + 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) { - self.canvas_state.borrow().SetTransform(a, b, c, d, e, f) + self.canvas_state.borrow().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().ResetTransform() + self.canvas_state.borrow().reset_transform() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha fn GlobalAlpha(&self) -> 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<f64>) { - 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<TextMetrics> { - 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<DomRoot<ImageData>> { 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<DomRoot<ImageData>> { 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<DomRoot<ImageData>> { - 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<CanvasGradient> { 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<DomRoot<CanvasGradient>> { 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<DomRoot<CanvasPattern>> { 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<RGBA, ()> { - 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<f64>) -> bool { - rect.size.width > 0.0 && rect.size.height > 0.0 -} - -// https://html.spec.whatwg.org/multipage/#serialisation-of-a-color -fn serialize<W>(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<i32>, - mut size: Size2D<i32>, -) -> (Point2D<i32>, Size2D<u32>) { - 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()) -} |