Skip to content

Commit

Permalink
Removed width and height from offscreenrenderingcontext2d; switched t…
Browse files Browse the repository at this point in the history
…o using canvas size where needed; made canvas definite instead of optional. still need to change sizing in associated classes to use u64 instead of u32

removed size from offscreencanvasrenderingcontext2d.rs; now getting canvas size through referenced canvas

Updated pixels::clip to use u64 data types and added trait to canvasrenderingcontext2d.rs to convert u32 sizes to u64

added Size2D<u32> to Size2D<u64> conversion to webglrenderingcontext and converted u32 sizes to u64 where relevant

updated get_rect to use u64. beginning to make type changes to canvas.rs

Updated canvas, canvas_data, and canvas_paint_thread to use u64 when relevant

Added ability to Recreate canvas when OffscreenCanvas::SetWidth() or OffscreenCanvas::SetHeight() are called

Fixed formatting; passes ./mach test-tidy 🎉
  • Loading branch information
Bailey Blankenship committed Oct 21, 2019
1 parent 328809a commit 5ad0303
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 60 deletions.
35 changes: 29 additions & 6 deletions components/canvas/canvas_data.rs
Expand Up @@ -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()
};
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand All @@ -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()
})
}
}
Expand Down Expand Up @@ -1189,3 +1189,26 @@ 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> {
return Size2D::new(self.width as u64, self.height as u64);
}
}

pub trait RectExt_ {
fn to_u64(&self) -> Rect<u64>;
}

impl RectExt_ for Rect<f64> {
fn to_u64(&self) -> Rect<u64> {
return Rect::new(
Point2D::new(self.origin.x as u64, self.origin.y as u64),
Size2D::new(self.size.width as u64, self.size.height as u64),
);
}
}
18 changes: 16 additions & 2 deletions components/canvas/canvas_paint_thread.rs
Expand Up @@ -4,7 +4,7 @@

use crate::canvas_data::*;
use canvas_traits::canvas::*;
use euclid::default::Size2D;
use euclid::default::{Point2D, Rect, Size2D};
use ipc_channel::ipc::{self, IpcSender};
use std::borrow::ToOwned;
use std::collections::HashMap;
Expand Down Expand Up @@ -142,9 +142,13 @@ impl<'a> CanvasPaintThread<'a> {
source_rect,
smoothing,
) => {
let source_rect_u64 = Rect::new(
Point2D::new(source_rect.origin.x as u64, source_rect.origin.y as u64),
Size2D::new(source_rect.size.width as u64, source_rect.size.width as u64),
);
let image_data = self
.canvas(canvas_id)
.read_pixels(source_rect.to_u32(), image_size.to_u32());
.read_pixels(source_rect_u64, image_size.to_u64());
self.canvas(other_canvas_id).draw_image(
image_data.into(),
source_rect.size,
Expand Down Expand Up @@ -207,3 +211,13 @@ impl<'a> CanvasPaintThread<'a> {
self.canvases.get_mut(&canvas_id).expect("Bogus canvas id")
}
}

pub trait Size2DExt {
fn to_u64(&self) -> Size2D<u64>;
}

impl Size2DExt for Size2D<f64> {
fn to_u64(&self) -> Size2D<u64> {
return Size2D::new(self.width as u64, self.height as u64);
}
}
6 changes: 3 additions & 3 deletions components/canvas_traits/canvas.rs
Expand Up @@ -29,7 +29,7 @@ pub enum CanvasMsg {
),
FromLayout(FromLayoutMsg, CanvasId),
FromScript(FromScriptMsg, CanvasId),
Recreate(Size2D<u32>, CanvasId),
Recreate(Size2D<u64>, CanvasId),
Close(CanvasId),
Exit,
}
Expand All @@ -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,
Expand Down
16 changes: 9 additions & 7 deletions components/pixels/lib.rs
Expand Up @@ -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);
Expand Down Expand Up @@ -85,18 +85,20 @@ 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);
let size = Size2D::new(size.width as u64, size.height as u64);
Rect::new(origin, size)
.intersection(&Rect::from_size(surface))
.filter(|rect| !rect.is_empty())
}
45 changes: 34 additions & 11 deletions components/script/dom/canvasrenderingcontext2d.rs
Expand Up @@ -172,12 +172,21 @@ impl CanvasState {
self.canvas_id.clone()
}

pub fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg> {
self.ipc_renderer.clone()
}

pub fn send_canvas_2d_msg(&self, msg: Canvas2dMsg) {
self.ipc_renderer
.send(CanvasMsg::Canvas2d(msg, 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;
Expand Down Expand Up @@ -298,7 +307,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));
Expand Down Expand Up @@ -1017,7 +1026,7 @@ impl CanvasState {
// https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata
pub fn GetImageData(
&self,
canvas_size: Size2D<u32>,
canvas_size: Size2D<u64>,
global: &GlobalScope,
sx: i32,
sy: i32,
Expand All @@ -1036,7 +1045,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.
Expand All @@ -1053,7 +1062,7 @@ impl CanvasState {
}

// https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
pub fn PutImageData(&self, canvas_size: Size2D<u32>, imagedata: &ImageData, dx: i32, dy: i32) {
pub fn PutImageData(&self, canvas_size: Size2D<u64>, imagedata: &ImageData, dx: i32, dy: i32) {
self.PutImageData_(
canvas_size,
imagedata,
Expand All @@ -1070,7 +1079,7 @@ impl CanvasState {
#[allow(unsafe_code)]
pub fn PutImageData_(
&self,
canvas_size: Size2D<u32>,
canvas_size: Size2D<u64>,
imagedata: &ImageData,
dx: i32,
dy: i32,
Expand Down Expand Up @@ -1098,7 +1107,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,
};
Expand Down Expand Up @@ -1495,7 +1504,7 @@ impl CanvasRenderingContext2D {
.borrow()
.ipc_renderer
.send(CanvasMsg::Recreate(
size,
size.to_u64(),
self.canvas_state.borrow().get_canvas_id(),
))
.unwrap();
Expand Down Expand Up @@ -1537,10 +1546,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,
)
}
Expand Down Expand Up @@ -1875,7 +1888,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
self.canvas_state.borrow().GetImageData(
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,
Expand All @@ -1889,7 +1902,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
self.canvas_state.borrow().PutImageData(
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,
Expand All @@ -1911,7 +1924,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
self.canvas_state.borrow().PutImageData_(
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,
Expand Down Expand Up @@ -2123,3 +2136,13 @@ fn adjust_size_sign(
}
(origin, size.to_u32())
}

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);
}
}
14 changes: 12 additions & 2 deletions components/script/dom/imagedata.rs
Expand Up @@ -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> {
Expand All @@ -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);
}
}
18 changes: 16 additions & 2 deletions components/script/dom/offscreencanvas.rs
Expand Up @@ -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(
Expand Down Expand Up @@ -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_bitmap_dimensions(self.get_size());
},
}
}
}

// https://html.spec.whatwg.org/multipage/#dom-offscreencanvas-height
Expand All @@ -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_bitmap_dimensions(self.get_size());
},
}
}
}
}

0 comments on commit 5ad0303

Please sign in to comment.