diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2019-11-11 14:47:56 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-11-11 14:47:56 -0500 |
commit | 905f714bb4b2959f1735cc7469969696eac56d47 (patch) | |
tree | 39073c7c0990269cd976fe0be6da6156b2992065 | |
parent | 06e58212cbca2ff6b24f0ad6e1e1c01237da480d (diff) | |
parent | ec2961920b74fbe0345f72e6007c6d42ae852019 (diff) | |
download | servo-905f714bb4b2959f1735cc7469969696eac56d47.tar.gz servo-905f714bb4b2959f1735cc7469969696eac56d47.zip |
Auto merge of #24524 - bblanke:consolidate-size-helpers, r=jdm
Make offscreen canvas rendering context use offscreen canvas' size; Consolidate size helpers
<!-- Please describe your changes on the following line: -->
Addresses issues raised in the review of PR #24518 and includes changes to 17 tests' metadata for those that now PASS.
Contains fixes in PR #24518:
Updated the offscreen canvas rendering context to use the offscreen canvas' size. This involved upgrading several methods to accept u64 sizes.
Additionally, the code in OffscreenCanvas::SetWidth() and OffscreenCanvas::SetHeight() was updated to send CanvasMsg::Recreate to the canvas paint thread.
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix #24465 and fix #24536
<!-- Either: -->
- [X] There are tests for these changes – 17 were updated to PASS
32 files changed, 211 insertions, 131 deletions
diff --git a/Cargo.lock b/Cargo.lock index 26c8c4db824..8a3b1ca0c36 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1307,9 +1307,9 @@ dependencies = [ [[package]] name = "euclid" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c879a4e57d6a2785d517b0771ea6857916173debef0102bf81142d36ca9254" +checksum = "f46a3516f04c5e05870f71ae6242a97e8f72ee12cfc2f7f5deb16111a98b0670" dependencies = [ "num-traits", "serde", diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index 78c32b4d813..29dd1743b46 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -13,7 +13,7 @@ use std::marker::PhantomData; use std::mem; use std::sync::Arc; use webrender::api::DirtyRect; -use webrender_api::units::RectExt; +use webrender_api::units::RectExt as RectExt_; /// The canvas data stores a state machine for the current status of /// the path data and any relevant transformations that are @@ -449,7 +449,7 @@ impl<'a> CanvasData<'a> { let source_rect = source_rect.ceil(); // It discards the extra pixels (if any) that won't be painted let image_data = if Rect::from_size(image_size).contains_rect(&source_rect) { - pixels::rgba8_get_rect(&image_data, image_size.to_u32(), source_rect.to_u32()).into() + pixels::rgba8_get_rect(&image_data, image_size.to_u64(), source_rect.to_u64()).into() } else { image_data.into() }; @@ -927,10 +927,10 @@ impl<'a> CanvasData<'a> { self.backend.set_global_composition(op, &mut self.state); } - pub fn recreate(&mut self, size: Size2D<u32>) { + pub fn recreate(&mut self, size: Size2D<u64>) { self.drawtarget = self .backend - .create_drawtarget(Size2D::new(size.width as u64, size.height as u64)); + .create_drawtarget(Size2D::new(size.width, size.height)); self.state = self.backend.recreate_paint_state(&self.state); self.saved_states.clear(); // Webrender doesn't let images change size, so we clear the webrender image key. @@ -997,7 +997,7 @@ impl<'a> CanvasData<'a> { } // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata - pub fn put_image_data(&mut self, mut imagedata: Vec<u8>, rect: Rect<u32>) { + pub fn put_image_data(&mut self, mut imagedata: Vec<u8>, rect: Rect<u64>) { assert_eq!(imagedata.len() % 4, 0); assert_eq!(rect.size.area() as usize, imagedata.len() / 4); pixels::rgba8_byte_swap_and_premultiply_inplace(&mut imagedata); @@ -1082,7 +1082,7 @@ impl<'a> CanvasData<'a> { /// canvas_size: The size of the canvas we're reading from /// read_rect: The area of the canvas we want to read from #[allow(unsafe_code)] - pub fn read_pixels(&self, read_rect: Rect<u32>, canvas_size: Size2D<u32>) -> Vec<u8> { + pub fn read_pixels(&self, read_rect: Rect<u64>, canvas_size: Size2D<u64>) -> Vec<u8> { let canvas_rect = Rect::from_size(canvas_size); if canvas_rect .intersection(&read_rect) @@ -1092,7 +1092,7 @@ impl<'a> CanvasData<'a> { } self.drawtarget.snapshot_data(&|bytes| { - pixels::rgba8_get_rect(bytes, canvas_size.to_u32(), read_rect.to_u32()).into_owned() + pixels::rgba8_get_rect(bytes, canvas_size, read_rect).into_owned() }) } } @@ -1189,3 +1189,35 @@ impl RectToi32 for Rect<f64> { ) } } + +pub trait Size2DExt { + fn to_u64(&self) -> Size2D<u64>; +} + +impl Size2DExt for Size2D<f64> { + fn to_u64(&self) -> Size2D<u64> { + self.cast() + } +} + +impl Size2DExt for Size2D<u32> { + fn to_u64(&self) -> Size2D<u64> { + self.cast() + } +} + +pub trait RectExt { + fn to_u64(&self) -> Rect<u64>; +} + +impl RectExt for Rect<f64> { + fn to_u64(&self) -> Rect<u64> { + self.cast() + } +} + +impl RectExt for Rect<u32> { + fn to_u64(&self) -> Rect<u64> { + self.cast() + } +} diff --git a/components/canvas/canvas_paint_thread.rs b/components/canvas/canvas_paint_thread.rs index e324c213d6e..a249080cdfd 100644 --- a/components/canvas/canvas_paint_thread.rs +++ b/components/canvas/canvas_paint_thread.rs @@ -144,7 +144,7 @@ impl<'a> CanvasPaintThread<'a> { ) => { let image_data = self .canvas(canvas_id) - .read_pixels(source_rect.to_u32(), image_size.to_u32()); + .read_pixels(source_rect.to_u64(), image_size.to_u64()); self.canvas(other_canvas_id).draw_image( image_data.into(), source_rect.size, diff --git a/components/canvas_traits/canvas.rs b/components/canvas_traits/canvas.rs index ff7e65722e3..db678b42572 100644 --- a/components/canvas_traits/canvas.rs +++ b/components/canvas_traits/canvas.rs @@ -29,7 +29,7 @@ pub enum CanvasMsg { ), FromLayout(FromLayoutMsg, CanvasId), FromScript(FromScriptMsg, CanvasId), - Recreate(Size2D<u32>, CanvasId), + Recreate(Size2D<u64>, CanvasId), Close(CanvasId), Exit, } @@ -54,11 +54,11 @@ pub enum Canvas2dMsg { Fill, FillText(String, f64, f64, Option<f64>), FillRect(Rect<f32>), - GetImageData(Rect<u32>, Size2D<u32>, IpcBytesSender), + GetImageData(Rect<u64>, Size2D<u64>, IpcBytesSender), IsPointInPath(f64, f64, FillRule, IpcSender<bool>), LineTo(Point2D<f32>), MoveTo(Point2D<f32>), - PutImageData(Rect<u32>, IpcBytesReceiver), + PutImageData(Rect<u64>, IpcBytesReceiver), QuadraticCurveTo(Point2D<f32>, Point2D<f32>), Rect(Rect<f32>), RestoreContext, diff --git a/components/pixels/lib.rs b/components/pixels/lib.rs index 68b22abb11d..88d845a3033 100644 --- a/components/pixels/lib.rs +++ b/components/pixels/lib.rs @@ -23,7 +23,7 @@ pub enum PixelFormat { BGRA8, } -pub fn rgba8_get_rect(pixels: &[u8], size: Size2D<u32>, rect: Rect<u32>) -> Cow<[u8]> { +pub fn rgba8_get_rect(pixels: &[u8], size: Size2D<u64>, rect: Rect<u64>) -> Cow<[u8]> { assert!(!rect.is_empty()); assert!(Rect::from_size(size).contains_rect(&rect)); assert_eq!(pixels.len() % 4, 0); @@ -85,18 +85,19 @@ pub fn multiply_u8_color(a: u8, b: u8) -> u8 { pub fn clip( mut origin: Point2D<i32>, - mut size: Size2D<u32>, - surface: Size2D<u32>, -) -> Option<Rect<u32>> { + mut size: Size2D<u64>, + surface: Size2D<u64>, +) -> Option<Rect<u64>> { if origin.x < 0 { - size.width = size.width.saturating_sub(-origin.x as u32); + size.width = size.width.saturating_sub(-origin.x as u64); origin.x = 0; } if origin.y < 0 { - size.height = size.height.saturating_sub(-origin.y as u32); + size.height = size.height.saturating_sub(-origin.y as u64); origin.y = 0; } - Rect::new(origin.to_u32(), size) + let origin = Point2D::new(origin.x as u64, origin.y as u64); + Rect::new(origin, size) .intersection(&Rect::from_size(surface)) .filter(|rect| !rect.is_empty()) } diff --git a/components/script/canvas_state.rs b/components/script/canvas_state.rs index 90630fb07c3..4b47308fa46 100644 --- a/components/script/canvas_state.rs +++ b/components/script/canvas_state.rs @@ -24,6 +24,7 @@ use crate::dom::imagedata::ImageData; use crate::dom::node::{Node, NodeDamage}; use crate::dom::paintworkletglobalscope::PaintWorkletGlobalScope; use crate::dom::textmetrics::TextMetrics; +use crate::euclidext::Size2DExt; use crate::unpremultiplytable::UNPREMULTIPLY_TABLE; use canvas_traits::canvas::{Canvas2dMsg, CanvasId, CanvasMsg}; use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; @@ -180,6 +181,19 @@ impl CanvasState { .unwrap() } + // https://html.spec.whatwg.org/multipage/#concept-canvas-set-bitmap-dimensions + pub fn set_bitmap_dimensions(&self, size: Size2D<u64>) { + self.reset_to_initial_state(); + self.ipc_renderer + .send(CanvasMsg::Recreate(size, self.get_canvas_id())) + .unwrap(); + } + + pub fn reset_to_initial_state(&self) { + self.saved_states.borrow_mut().clear(); + *self.state.borrow_mut() = CanvasContextState::new(); + } + 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; @@ -300,7 +314,7 @@ impl CanvasState { } } - pub fn get_rect(&self, canvas_size: Size2D<u32>, rect: Rect<u32>) -> Vec<u8> { + pub fn get_rect(&self, canvas_size: Size2D<u64>, rect: Rect<u64>) -> Vec<u8> { assert!(self.origin_is_clean()); assert!(Rect::from_size(canvas_size).contains_rect(&rect)); @@ -1019,7 +1033,7 @@ impl CanvasState { // https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata pub fn get_image_data( &self, - canvas_size: Size2D<u32>, + canvas_size: Size2D<u64>, global: &GlobalScope, sx: i32, sy: i32, @@ -1038,7 +1052,7 @@ impl CanvasState { } let (origin, size) = adjust_size_sign(Point2D::new(sx, sy), Size2D::new(sw, sh)); - let read_rect = match pixels::clip(origin, size, canvas_size) { + let read_rect = match pixels::clip(origin, size.to_u64(), canvas_size) { Some(rect) => rect, None => { // All the pixels are outside the canvas surface. @@ -1057,7 +1071,7 @@ impl CanvasState { // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata pub fn put_image_data( &self, - canvas_size: Size2D<u32>, + canvas_size: Size2D<u64>, imagedata: &ImageData, dx: i32, dy: i32, @@ -1078,7 +1092,7 @@ impl CanvasState { #[allow(unsafe_code)] pub fn put_image_data_( &self, - canvas_size: Size2D<u32>, + canvas_size: Size2D<u64>, imagedata: &ImageData, dx: i32, dy: i32, @@ -1106,7 +1120,7 @@ impl CanvasState { Point2D::new(dirty_x, dirty_y), Size2D::new(dirty_width, dirty_height), ); - let src_rect = match pixels::clip(src_origin, src_size, imagedata_size) { + let src_rect = match pixels::clip(src_origin, src_size.to_u64(), imagedata_size.to_u64()) { Some(rect) => rect, None => return, }; 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<CanvasState> { + self.canvas_state.borrow() + } + */ + + pub fn set_canvas_bitmap_dimensions(&self, size: Size2D<u64>) { + 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<CanvasMsg> { self.canvas_state.borrow().get_ipc_renderer().clone() } @@ -125,10 +137,14 @@ impl CanvasRenderingContext2D { } pub fn get_rect(&self, rect: Rect<u32>) -> Vec<u8> { + 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, diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 9e638539995..8924f8ddd1c 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -28,6 +28,7 @@ use crate::dom::webgl2renderingcontext::WebGL2RenderingContext; use crate::dom::webglrenderingcontext::{ LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext, }; +use crate::euclidext::Size2DExt; use crate::script_runtime::JSContext; use base64; use canvas_traits::canvas::{CanvasId, CanvasMsg, FromScriptMsg}; @@ -94,7 +95,9 @@ impl HTMLCanvasElement { let size = self.get_size(); if let Some(ref context) = *self.context.borrow() { match *context { - CanvasContext::Context2d(ref context) => context.set_bitmap_dimensions(size), + CanvasContext::Context2d(ref context) => { + context.set_canvas_bitmap_dimensions(size.to_u64()) + }, CanvasContext::WebGL(ref context) => context.recreate(size), CanvasContext::WebGL2(ref context) => context.recreate(size), } diff --git a/components/script/dom/imagedata.rs b/components/script/dom/imagedata.rs index d89e5e36d1b..b09984e267f 100644 --- a/components/script/dom/imagedata.rs +++ b/components/script/dom/imagedata.rs @@ -169,8 +169,8 @@ impl ImageData { } #[allow(unsafe_code)] - pub unsafe fn get_rect(&self, rect: Rect<u32>) -> Cow<[u8]> { - pixels::rgba8_get_rect(self.as_slice(), self.get_size(), rect) + pub unsafe fn get_rect(&self, rect: Rect<u64>) -> Cow<[u8]> { + pixels::rgba8_get_rect(self.as_slice(), self.get_size().to_u64(), rect) } pub fn get_size(&self) -> Size2D<u32> { @@ -194,3 +194,13 @@ impl ImageDataMethods for ImageData { NonNull::new(self.data.get()).expect("got a null pointer") } } + +pub trait Size2DExt { + fn to_u64(&self) -> Size2D<u64>; +} + +impl Size2DExt for Size2D<u32> { + fn to_u64(&self) -> Size2D<u64> { + return Size2D::new(self.width as u64, self.height as u64); + } +} diff --git a/components/script/dom/offscreencanvas.rs b/components/script/dom/offscreencanvas.rs index 142379519fb..69c1114768c 100644 --- a/components/script/dom/offscreencanvas.rs +++ b/components/script/dom/offscreencanvas.rs @@ -92,11 +92,9 @@ impl OffscreenCanvas { OffscreenCanvasContext::OffscreenContext2d(ref ctx) => Some(DomRoot::from_ref(ctx)), }; } - let size = self.get_size(); let context = OffscreenCanvasRenderingContext2D::new( &self.global(), self, - size, self.placeholder.as_ref().map(|c| &**c), ); *self.context.borrow_mut() = Some(OffscreenCanvasContext::OffscreenContext2d( @@ -136,6 +134,14 @@ impl OffscreenCanvasMethods for OffscreenCanvas { // https://html.spec.whatwg.org/multipage/#dom-offscreencanvas-width fn SetWidth(&self, value: u64) { self.width.set(value); + + if let Some(canvas_context) = self.context() { + match &*canvas_context { + OffscreenCanvasContext::OffscreenContext2d(rendering_context) => { + rendering_context.set_canvas_bitmap_dimensions(self.get_size()); + }, + } + } } // https://html.spec.whatwg.org/multipage/#dom-offscreencanvas-height @@ -146,5 +152,13 @@ impl OffscreenCanvasMethods for OffscreenCanvas { // https://html.spec.whatwg.org/multipage/#dom-offscreencanvas-height fn SetHeight(&self, value: u64) { self.height.set(value); + + if let Some(canvas_context) = self.context() { + match &*canvas_context { + OffscreenCanvasContext::OffscreenContext2d(rendering_context) => { + rendering_context.set_canvas_bitmap_dimensions(self.get_size()); + }, + } + } } } diff --git a/components/script/dom/offscreencanvasrenderingcontext2d.rs b/components/script/dom/offscreencanvasrenderingcontext2d.rs index 04e0a13032c..077752d9d6e 100644 --- a/components/script/dom/offscreencanvasrenderingcontext2d.rs +++ b/components/script/dom/offscreencanvasrenderingcontext2d.rs @@ -30,44 +30,32 @@ use euclid::default::Size2D; #[dom_struct] pub struct OffscreenCanvasRenderingContext2D { reflector_: Reflector, - canvas: Option<Dom<OffscreenCanvas>>, + canvas: Dom<OffscreenCanvas>, canvas_state: DomRefCell<CanvasState>, htmlcanvas: Option<Dom<HTMLCanvasElement>>, - width: u32, - height: u32, } impl OffscreenCanvasRenderingContext2D { fn new_inherited( global: &GlobalScope, - canvas: Option<&OffscreenCanvas>, - size: Size2D<u64>, + canvas: &OffscreenCanvas, htmlcanvas: Option<&HTMLCanvasElement>, ) -> OffscreenCanvasRenderingContext2D { OffscreenCanvasRenderingContext2D { reflector_: Reflector::new(), - canvas: canvas.map(Dom::from_ref), + canvas: Dom::from_ref(canvas), htmlcanvas: htmlcanvas.map(Dom::from_ref), - canvas_state: DomRefCell::new(CanvasState::new( - global, - Size2D::new(size.width as u64, size.height as u64), - )), - width: size.width as u32, - height: size.height as u32, + canvas_state: DomRefCell::new(CanvasState::new(global, canvas.get_size())), } } pub fn new( global: &GlobalScope, canvas: &OffscreenCanvas, - size: Size2D<u64>, htmlcanvas: Option<&HTMLCanvasElement>, ) -> DomRoot<OffscreenCanvasRenderingContext2D> { let boxed = Box::new(OffscreenCanvasRenderingContext2D::new_inherited( - global, - Some(canvas), - size, - htmlcanvas, + global, canvas, htmlcanvas, )); reflect_dom_object( boxed, @@ -75,12 +63,21 @@ impl OffscreenCanvasRenderingContext2D { OffscreenCanvasRenderingContext2DBinding::Wrap, ) } + /* + pub fn get_canvas_state(&self) -> Ref<CanvasState> { + self.canvas_state.borrow() + } + */ + + pub fn set_canvas_bitmap_dimensions(&self, size: Size2D<u64>) { + self.canvas_state.borrow().set_bitmap_dimensions(size); + } } impl OffscreenCanvasRenderingContext2DMethods for OffscreenCanvasRenderingContext2D { // https://html.spec.whatwg.org/multipage/offscreencontext2d-canvas fn Canvas(&self) -> DomRoot<OffscreenCanvas> { - DomRoot::from_ref(self.canvas.as_ref().expect("No canvas.")) + DomRoot::from_ref(&self.canvas) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect @@ -315,7 +312,7 @@ impl OffscreenCanvasRenderingContext2DMethods for OffscreenCanvasRenderingContex // 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().get_image_data( - Size2D::new(self.width, self.height), + self.canvas.get_size(), &self.global(), sx, sy, @@ -326,12 +323,9 @@ impl OffscreenCanvasRenderingContext2DMethods for OffscreenCanvasRenderingContex // 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( - Size2D::new(self.width, self.height), - imagedata, - dx, - dy, - ) + self.canvas_state + .borrow() + .put_image_data(self.canvas.get_size(), imagedata, dx, dy) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata @@ -347,7 +341,7 @@ impl OffscreenCanvasRenderingContext2DMethods for OffscreenCanvasRenderingContex dirty_height: i32, ) { self.canvas_state.borrow().put_image_data_( - Size2D::new(self.width, self.height), + self.canvas.get_size(), imagedata, dx, dy, diff --git a/components/script/dom/paintrenderingcontext2d.rs b/components/script/dom/paintrenderingcontext2d.rs index 1bbb52d05fe..e4b0a3cf71e 100644 --- a/components/script/dom/paintrenderingcontext2d.rs +++ b/components/script/dom/paintrenderingcontext2d.rs @@ -21,6 +21,7 @@ use crate::dom::canvasgradient::CanvasGradient; use crate::dom::canvaspattern::CanvasPattern; use crate::dom::canvasrenderingcontext2d::CanvasRenderingContext2D; use crate::dom::paintworkletglobalscope::PaintWorkletGlobalScope; +use crate::euclidext::Size2DExt; use canvas_traits::canvas::CanvasImageData; use canvas_traits::canvas::CanvasMsg; use canvas_traits::canvas::FromLayoutMsg; @@ -75,7 +76,7 @@ impl PaintRenderingContext2D { let size = size * device_pixel_ratio; self.device_pixel_ratio.set(device_pixel_ratio); self.context - .set_bitmap_dimensions(size.to_untyped().to_u32()); + .set_canvas_bitmap_dimensions(size.to_untyped().to_u64()); self.scale_by_device_pixel_ratio(); } diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 228ccd491b9..c843ab578d1 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -2963,11 +2963,16 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { let src_origin = Point2D::new(x, y); let src_size = Size2D::new(width as u32, height as u32); let fb_size = Size2D::new(fb_width as u32, fb_height as u32); - let src_rect = match pixels::clip(src_origin, src_size, fb_size) { + let src_rect = match pixels::clip(src_origin, src_size.to_u64(), fb_size.to_u64()) { Some(rect) => rect, None => return, }; + // Note: we're casting a Rect<u64> back into a Rect<u32> here, but it's okay because + // it used u32 data types to begin with. It just got converted to Rect<u64> in + // pixels::clip + let src_rect = src_rect.to_u32(); + let mut dest_offset = 0; if x < 0 { dest_offset += -x * bytes_per_pixel; @@ -4485,3 +4490,13 @@ impl WebGLMessageSender { self.wake_after_send(|| self.sender.send_dom_to_texture(command)) } } + +pub trait Size2DExt { + fn to_u64(&self) -> Size2D<u64>; +} + +impl Size2DExt for Size2D<u32> { + fn to_u64(&self) -> Size2D<u64> { + return Size2D::new(self.width as u64, self.height as u64); + } +} diff --git a/components/script/euclidext.rs b/components/script/euclidext.rs new file mode 100644 index 00000000000..39de2aa2ccb --- /dev/null +++ b/components/script/euclidext.rs @@ -0,0 +1,43 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use euclid::default::{Rect, Size2D}; + +pub trait Size2DExt { + fn to_u64(&self) -> Size2D<u64>; +} + +impl Size2DExt for Size2D<f32> { + fn to_u64(&self) -> Size2D<u64> { + self.cast() + } +} + +impl Size2DExt for Size2D<f64> { + fn to_u64(&self) -> Size2D<u64> { + self.cast() + } +} + +impl Size2DExt for Size2D<u32> { + fn to_u64(&self) -> Size2D<u64> { + self.cast() + } +} + +pub trait RectExt { + fn to_u64(&self) -> Rect<u64>; +} + +impl RectExt for Rect<f64> { + fn to_u64(&self) -> Rect<u64> { + self.cast() + } +} + +impl RectExt for Rect<u32> { + fn to_u64(&self) -> Rect<u64> { + self.cast() + } +} diff --git a/components/script/lib.rs b/components/script/lib.rs index 250f860eda2..87eec7cab02 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -65,6 +65,7 @@ mod dom; mod canvas_state; #[warn(deprecated)] mod compartments; +mod euclidext; #[warn(deprecated)] pub mod fetch; #[warn(deprecated)] diff --git a/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.interpolate.multiple.html.ini b/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.interpolate.multiple.html.ini index 19172f06169..2b4b3558760 100644 --- a/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.interpolate.multiple.html.ini +++ b/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.interpolate.multiple.html.ini @@ -1,4 +1,3 @@ [2d.gradient.interpolate.multiple.html] [OffscreenCanvas test: 2d.gradient.interpolate.multiple] - expected: FAIL - + expected: PASS diff --git a/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.interpolate.multiple.worker.js.ini b/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.interpolate.multiple.worker.js.ini index d2000f8aae4..4ef93cea653 100644 --- a/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.interpolate.multiple.worker.js.ini +++ b/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.interpolate.multiple.worker.js.ini @@ -1,4 +1,3 @@ [2d.gradient.interpolate.multiple.worker.html] [2d] - expected: FAIL - + expected: PASS diff --git a/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.interpolate.overlap.html.ini b/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.interpolate.overlap.html.ini deleted file mode 100644 index b0891336db1..00000000000 --- a/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.interpolate.overlap.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[2d.gradient.interpolate.overlap.html] - [OffscreenCanvas test: 2d.gradient.interpolate.overlap] - expected: FAIL - diff --git a/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.interpolate.overlap.worker.js.ini b/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.interpolate.overlap.worker.js.ini deleted file mode 100644 index 30b1c8e6cde..00000000000 --- a/tests/wpt/metadata/offscreen-canvas/fill-and-stroke-styles/2d.gradient.interpolate.overlap.worker.js.ini +++ /dev/null @@ -1,4 +0,0 @@ -[2d.gradient.interpolate.overlap.worker.html] - [2d] - expected: FAIL - diff --git a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.2dstate.html.ini b/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.2dstate.html.ini deleted file mode 100644 index 6bb1b2ab136..00000000000 --- a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.2dstate.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[initial.reset.2dstate.html] - [Resetting the canvas state resets 2D state variables] - expected: FAIL - diff --git a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.2dstate.worker.js.ini b/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.2dstate.worker.js.ini deleted file mode 100644 index 65b5e704ef8..00000000000 --- a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.2dstate.worker.js.ini +++ /dev/null @@ -1,4 +0,0 @@ -[initial.reset.2dstate.worker.html] - [Resetting the canvas state resets 2D state variables] - expected: FAIL - diff --git a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.clip.html.ini b/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.clip.html.ini deleted file mode 100644 index 831dfb2521c..00000000000 --- a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.clip.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[initial.reset.clip.html] - [Resetting the canvas state resets the current clip region] - expected: FAIL - diff --git a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.clip.worker.js.ini b/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.clip.worker.js.ini deleted file mode 100644 index 24edd2020ce..00000000000 --- a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.clip.worker.js.ini +++ /dev/null @@ -1,4 +0,0 @@ -[initial.reset.clip.worker.html] - [Resetting the canvas state resets the current clip region] - expected: FAIL - diff --git a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.different.html.ini b/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.different.html.ini deleted file mode 100644 index 061e290fcd5..00000000000 --- a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.different.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[initial.reset.different.html] - [Changing size resets canvas to transparent black] - expected: FAIL - diff --git a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.different.worker.js.ini b/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.different.worker.js.ini deleted file mode 100644 index 247627d6ce7..00000000000 --- a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.different.worker.js.ini +++ /dev/null @@ -1,4 +0,0 @@ -[initial.reset.different.worker.html] - [Changing size resets canvas to transparent black] - expected: FAIL - diff --git a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.gradient.html.ini b/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.gradient.html.ini deleted file mode 100644 index dcfe0bf696b..00000000000 --- a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.gradient.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[initial.reset.gradient.html] - [Resetting the canvas state does not invalidate any existing gradients] - expected: FAIL - diff --git a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.gradient.worker.js.ini b/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.gradient.worker.js.ini deleted file mode 100644 index 7876111284e..00000000000 --- a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.gradient.worker.js.ini +++ /dev/null @@ -1,4 +0,0 @@ -[initial.reset.gradient.worker.html] - [Resetting the canvas state does not invalidate any existing gradients] - expected: FAIL - diff --git a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.same.html.ini b/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.same.html.ini deleted file mode 100644 index 5a08092726b..00000000000 --- a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.same.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[initial.reset.same.html] - [Setting size (not changing the value) resets canvas to transparent black] - expected: FAIL - diff --git a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.same.worker.js.ini b/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.same.worker.js.ini deleted file mode 100644 index f11136a04df..00000000000 --- a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.same.worker.js.ini +++ /dev/null @@ -1,4 +0,0 @@ -[initial.reset.same.worker.html] - [Setting size (not changing the value) resets canvas to transparent black] - expected: FAIL - diff --git a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.transform.html.ini b/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.transform.html.ini deleted file mode 100644 index 8dc1ce9f0f2..00000000000 --- a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.transform.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[initial.reset.transform.html] - [Resetting the canvas state resets the current transformation matrix] - expected: FAIL - diff --git a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.transform.worker.js.ini b/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.transform.worker.js.ini deleted file mode 100644 index 62bfb15adf0..00000000000 --- a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/initial.reset.transform.worker.js.ini +++ /dev/null @@ -1,4 +0,0 @@ -[initial.reset.transform.worker.html] - [Resetting the canvas state resets the current transformation matrix] - expected: FAIL - diff --git a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/offscreencanvas.resize.html.ini b/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/offscreencanvas.resize.html.ini index 30cc4c73ed2..bb34106d98d 100644 --- a/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/offscreencanvas.resize.html.ini +++ b/tests/wpt/metadata/offscreen-canvas/the-offscreen-canvas/offscreencanvas.resize.html.ini @@ -1,6 +1,4 @@ [offscreencanvas.resize.html] - [Verify that resizing a 2d context resets its state.] - expected: FAIL [Verify that writing to the width and height attributes of an OffscreenCanvas works when there is a 2d context attached.] expected: FAIL @@ -8,9 +6,6 @@ [Verify that resizing an OffscreenCanvas with a webgl context propagates the new size to its placeholder canvas asynchronously.] expected: FAIL - [Verify that setting the size of a 2d context to the same size it already had resets its state.] - expected: FAIL - [Verify that resizing an OffscreenCanvas with a 2d context propagates the new size to its placeholder canvas asynchronously.] expected: FAIL @@ -25,4 +20,3 @@ [Verify that writing to the width or height attribute of a placeholder canvas throws an exception even when not changing the value of the attribute.] expected: FAIL - |