diff options
author | Anthony Ramine <n.oxyde@gmail.com> | 2018-10-08 13:49:58 +0200 |
---|---|---|
committer | Anthony Ramine <n.oxyde@gmail.com> | 2018-10-09 14:57:02 +0200 |
commit | 6c469b90b1ae34bddcb7da19eacfa6ad4467cf35 (patch) | |
tree | 1746b4cef5b9710368c7c86b360906a417e0a78f /components/script/dom | |
parent | 05ef233097e17c3cdd0000f434d1592e8e26ff54 (diff) | |
download | servo-6c469b90b1ae34bddcb7da19eacfa6ad4467cf35.tar.gz servo-6c469b90b1ae34bddcb7da19eacfa6ad4467cf35.zip |
Share some code between 2D canvas and WebGL
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/canvasrenderingcontext2d.rs | 24 | ||||
-rw-r--r-- | components/script/dom/htmlcanvaselement.rs | 4 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 63 |
3 files changed, 27 insertions, 64 deletions
diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 2617f9e7ed5..dacabcccce5 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -1168,7 +1168,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { // FIXME(nox): This is probably wrong when this is a context for an // offscreen canvas. let canvas_size = self.canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()); - let read_rect = match clip(origin, size, canvas_size) { + let read_rect = match pixels::clip(origin, size, canvas_size) { Some(rect) => rect, None => { // All the pixels are outside the canvas surface. @@ -1220,7 +1220,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { Point2D::new(dirty_x, dirty_y), Size2D::new(dirty_width, dirty_height), ); - let src_rect = match clip(src_origin, src_size, imagedata_size) { + let src_rect = match pixels::clip(src_origin, src_size, imagedata_size) { Some(rect) => rect, None => return, }; @@ -1230,7 +1230,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { ); // By clipping to the canvas surface, we avoid sending any pixel // that would fall outside it. - let dst_rect = match clip(dst_origin, src_rect.size, canvas_size) { + let dst_rect = match pixels::clip(dst_origin, src_rect.size, canvas_size) { Some(rect) => rect, None => return, }; @@ -1537,21 +1537,3 @@ fn adjust_size_sign( } (origin, size.to_u32()) } - -fn clip( - mut origin: Point2D<i32>, - mut size: Size2D<u32>, - surface: Size2D<u32>, -) -> Option<Rect<u32>> { - if origin.x < 0 { - size.width = size.width.saturating_sub(-origin.x as u32); - origin.x = 0; - } - if origin.y < 0 { - size.height = size.height.saturating_sub(-origin.y as u32); - origin.y = 0; - } - Rect::new(origin.to_u32(), size) - .intersection(&Rect::from_size(surface)) - .filter(|rect| !rect.is_empty()) -} diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 5cc28fcf461..8f572336573 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -368,13 +368,13 @@ impl HTMLCanvasElementMethods for HTMLCanvasElement { context.get_rect(Rect::from_size(self.get_size())) }, Some(CanvasContext::WebGL(ref context)) => { - match context.get_image_data(self.Width(), self.Height()) { + match context.get_image_data(self.get_size()) { Some(data) => data, None => return Ok(USVString("data:,".into())), } }, Some(CanvasContext::WebGL2(ref context)) => { - match context.base_context().get_image_data(self.Width(), self.Height()) { + match context.base_context().get_image_data(self.get_size()) { Some(data) => data, None => return Ok(USVString("data:,".into())), } diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 4e3658fa524..bfccd5e6f68 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -52,7 +52,7 @@ use dom::webgluniformlocation::WebGLUniformLocation; use dom::webglvertexarrayobjectoes::WebGLVertexArrayObjectOES; use dom::window::Window; use dom_struct::dom_struct; -use euclid::Size2D; +use euclid::{Point2D, Rect, Size2D}; use half::f16; use ipc_channel::ipc; use js::jsapi::{JSContext, JSObject, Type}; @@ -1070,7 +1070,7 @@ impl WebGLRenderingContext { // can fail and that it is UB what happens in that case. // // https://www.khronos.org/registry/webgl/specs/latest/1.0/#2.2 - pub fn get_image_data(&self, width: u32, height: u32) -> Option<Vec<u8>> { + pub fn get_image_data(&self, mut size: Size2D<u32>) -> Option<Vec<u8>> { handle_potential_webgl_error!(self, self.validate_framebuffer(), return None); let (fb_width, fb_height) = handle_potential_webgl_error!( @@ -1078,15 +1078,12 @@ impl WebGLRenderingContext { self.get_current_framebuffer_size().ok_or(InvalidOperation), return None ); - let width = cmp::min(width, fb_width as u32); - let height = cmp::min(height, fb_height as u32); + size.width = cmp::min(size.width, fb_width as u32); + size.height = cmp::min(size.height, fb_height as u32); let (sender, receiver) = ipc::bytes_channel().unwrap(); self.send_command(WebGLCommand::ReadPixels( - 0, - 0, - width as i32, - height as i32, + Rect::from_size(size), constants::RGBA, constants::UNSIGNED_BYTE, sender, @@ -2879,45 +2876,29 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return self.webgl_error(InvalidOperation); } - let mut src_x = x; - let mut src_y = y; - let mut src_width = width; - let mut src_height = height; - let mut dest_offset = 0; - - if src_x < 0 { - if src_width <= -src_x { - return; - } - dest_offset += bytes_per_pixel * -src_x; - src_width += src_x; - src_x = 0; - } - if src_y < 0 { - if src_height <= -src_y { - return; - } - dest_offset += row_len * -src_y; - src_height += src_y; - src_y = 0; - } + 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) { + Some(rect) => rect, + None => return, + }; - if src_x + src_width > fb_width { - src_width = fb_width - src_x; + let mut dest_offset = 0; + if x < 0 { + dest_offset += -x * bytes_per_pixel; } - if src_y + src_height > fb_height { - src_height = fb_height - src_y; + if y < 0 { + dest_offset += -y * row_len; } let (sender, receiver) = ipc::bytes_channel().unwrap(); - self.send_command(WebGLCommand::ReadPixels( - src_x, src_y, src_width, src_height, format, pixel_type, sender, - )); - + self.send_command(WebGLCommand::ReadPixels(src_rect, format, pixel_type, sender)); let src = receiver.recv().unwrap(); - let src_row_len = (src_width * bytes_per_pixel) as usize; - for i in 0..src_height { - let dest_start = (dest_offset + i * dest_stride) as usize; + + let src_row_len = src_rect.size.width as usize * bytes_per_pixel as usize; + for i in 0..src_rect.size.height { + let dest_start = dest_offset as usize + i as usize * dest_stride as usize; let dest_end = dest_start + src_row_len; let src_start = i as usize * src_row_len; let src_end = src_start + src_row_len; |