diff options
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/canvasrenderingcontext2d.rs | 51 | ||||
-rw-r--r-- | components/script/dom/htmlcanvaselement.rs | 54 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 52 |
3 files changed, 84 insertions, 73 deletions
diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 748f3746c6e..9a6443c052f 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -143,6 +143,10 @@ impl CanvasRenderingContext2D { .unwrap(); } + pub fn ipc_renderer(&self) -> IpcSender<CanvasMsg> { + self.ipc_renderer.clone() + } + fn mark_as_dirty(&self) { let canvas = self.canvas.root(); let node = NodeCast::from_ref(canvas.r()); @@ -245,6 +249,7 @@ impl CanvasRenderingContext2D { // Pixels come from cache in BGRA order and drawImage expects RGBA so we // have to swap the color values byte_swap(&mut data); + let size = Size2D::new(size.width as f64, size.height as f64); (data, size) }, None => return Err(InvalidState), @@ -338,7 +343,7 @@ impl CanvasRenderingContext2D { fn fetch_image_data(&self, image_element: &HTMLImageElement) - -> Option<(Vec<u8>, Size2D<f64>)> { + -> Option<(Vec<u8>, Size2D<i32>)> { let url = match image_element.get_url() { Some(url) => url, None => return None, @@ -351,7 +356,7 @@ impl CanvasRenderingContext2D { } }; - let image_size = Size2D::new(img.width as f64, img.height as f64); + let image_size = Size2D::new(img.width as i32, img.height as i32); let image_data = match img.format { PixelFormat::RGBA8 => img.bytes.to_vec(), PixelFormat::K8 => panic!("K8 color type not supported"), @@ -362,28 +367,6 @@ impl CanvasRenderingContext2D { Some((image_data, image_size)) } - // TODO(ecoal95): Move this to `HTMLCanvasElement`, and support WebGL contexts - fn fetch_canvas_data(&self, - canvas_element: &HTMLCanvasElement, - source_rect: Rect<f64>) - -> Option<(Vec<u8>, Size2D<f64>)> { - let context = match canvas_element.get_or_init_2d_context() { - Some(context) => context, - None => return None, - }; - - let canvas_size = canvas_element.get_size(); - let image_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64); - - let renderer = context.r().get_ipc_renderer(); - let (sender, receiver) = ipc::channel::<Vec<u8>>().unwrap(); - // Reads pixels from source canvas - renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::GetImageData(source_rect.to_i32(), - image_size, sender))).unwrap(); - - Some((receiver.recv().unwrap(), image_size)) - } - #[inline] fn request_image_from_cache(&self, url: Url) -> ImageResponse { let canvas = self.canvas.root(); @@ -975,26 +958,20 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } }, HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(canvas) => { - let canvas_element = canvas.r(); - - let canvas_size = canvas_element.get_size(); - let source_rect = Rect::new(Point2D::zero(), - Size2D::new(canvas_size.width as f64, canvas_size.height as f64)); + let canvas = canvas.r(); + let _ = canvas.get_or_init_2d_context(); - match self.fetch_canvas_data(&canvas_element, source_rect) { + match canvas.fetch_all_data() { Some((data, size)) => (data, size), None => return Err(InvalidState), } }, HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eCanvasRenderingContext2D(context) => { let canvas = context.r().Canvas(); - let canvas_element = canvas.r(); - - let canvas_size = canvas_element.get_size(); - let source_rect = Rect::new(Point2D::zero(), - Size2D::new(canvas_size.width as f64, canvas_size.height as f64)); + let canvas = canvas.r(); + let _ = canvas.get_or_init_2d_context(); - match self.fetch_canvas_data(&canvas_element, source_rect) { + match canvas.fetch_all_data() { Some((data, size)) => (data, size), None => return Err(InvalidState), } @@ -1004,7 +981,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { if let Ok(rep) = RepetitionStyle::from_str(&repetition) { return Ok(CanvasPattern::new(self.global.root().r(), image_data, - Size2D::new(image_size.width as i32, image_size.height as i32), + image_size, rep)); } return Err(Syntax); diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 3c254ffa330..7677f1afcaf 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::CanvasMsg; +use canvas_traits::{CanvasMsg, FromLayoutMsg}; use dom::attr::Attr; use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding; use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods; @@ -22,11 +22,12 @@ use dom::node::{Node, NodeTypeId, window_from_node}; use dom::virtualmethods::VirtualMethods; use dom::webglrenderingcontext::{LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext}; use euclid::size::Size2D; -use ipc_channel::ipc::IpcSender; +use ipc_channel::ipc::{self, IpcSender}; use js::jsapi::{HandleValue, JSContext}; use offscreen_gl_context::GLContextAttributes; use std::cell::Cell; use std::default::Default; +use std::iter::repeat; use util::str::{DOMString, parse_unsigned_integer}; const DEFAULT_WIDTH: u32 = 300; @@ -114,27 +115,23 @@ impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { #[allow(unsafe_code)] unsafe fn get_renderer_id(&self) -> Option<usize> { let ref canvas = *self.unsafe_get(); - if let Some(context) = canvas.context.get() { + canvas.context.get().map(|context| { match context { - CanvasContext::Context2d(context) => Some(context.to_layout().get_renderer_id()), - CanvasContext::WebGL(context) => Some(context.to_layout().get_renderer_id()), + CanvasContext::Context2d(context) => context.to_layout().get_renderer_id(), + CanvasContext::WebGL(context) => context.to_layout().get_renderer_id(), } - } else { - None - } + }) } #[allow(unsafe_code)] unsafe fn get_ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> { let ref canvas = *self.unsafe_get(); - if let Some(context) = canvas.context.get() { + canvas.context.get().map(|context| { match context { - CanvasContext::Context2d(context) => Some(context.to_layout().get_ipc_renderer()), - CanvasContext::WebGL(context) => Some(context.to_layout().get_ipc_renderer()), + CanvasContext::Context2d(context) => context.to_layout().get_ipc_renderer(), + CanvasContext::WebGL(context) => context.to_layout().get_ipc_renderer(), } - } else { - None - } + }) } #[allow(unsafe_code)] @@ -150,6 +147,15 @@ impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { impl HTMLCanvasElement { + pub fn ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> { + self.context.get().map(|context| { + match context { + CanvasContext::Context2d(context) => context.root().r().ipc_renderer(), + CanvasContext::WebGL(context) => context.root().r().ipc_renderer(), + } + }) + } + pub fn get_or_init_2d_context(&self) -> Option<Root<CanvasRenderingContext2D>> { if self.context.get().is_none() { let window = window_from_node(self); @@ -200,6 +206,26 @@ impl HTMLCanvasElement { pub fn is_valid(&self) -> bool { self.height.get() != 0 && self.width.get() != 0 } + + pub fn fetch_all_data(&self) -> Option<(Vec<u8>, Size2D<i32>)> { + let size = self.get_size(); + + if size.width == 0 || size.height == 0 { + return None + } + + let data = if let Some(renderer) = self.ipc_renderer() { + let (sender, receiver) = ipc::channel().unwrap(); + let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendPixelContents(sender)); + renderer.send(msg).unwrap(); + + receiver.recv().unwrap().to_vec() + } else { + repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect() + }; + + Some((data, size)) + } } impl HTMLCanvasElementMethods for HTMLCanvasElement { diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 93398ffee56..cd71f64d077 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -124,6 +124,27 @@ impl WebGLRenderingContext { self.ipc_renderer.send(CanvasMsg::Common(CanvasCommonMsg::Recreate(size))).unwrap(); } + pub fn ipc_renderer(&self) -> IpcSender<CanvasMsg> { + self.ipc_renderer.clone() + } + + pub fn webgl_error(&self, err: WebGLError) { + // If an error has been detected no further errors must be + // recorded until `getError` has been called + if self.last_error.get().is_none() { + self.last_error.set(Some(err)); + } + } + + pub fn bound_texture_for(&self, target: u32) -> Option<JS<WebGLTexture>> { + match target { + constants::TEXTURE_2D => self.bound_texture_2d.get(), + constants::TEXTURE_CUBE_MAP => self.bound_texture_cube_map.get(), + + _ => unreachable!(), + } + } + fn mark_as_dirty(&self) { let canvas = self.canvas.root(); let node = NodeCast::from_ref(canvas.r()); @@ -845,8 +866,15 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { }, // TODO(ecoal95): Getting canvas data is implemented in CanvasRenderingContext2D, but // we need to refactor it moving it to `HTMLCanvasElement` and supporting WebGLContext - ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::eHTMLCanvasElement(_rooted_canvas) - => unimplemented!(), + ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::eHTMLCanvasElement(canvas) => { + let canvas = canvas.r(); + if let Some((mut data, size)) = canvas.fetch_all_data() { + byte_swap(&mut data); + (data, size) + } else { + return + } + }, ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::eHTMLVideoElement(_rooted_video) => unimplemented!(), }; @@ -898,26 +926,6 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } } - -impl WebGLRenderingContext { - pub fn webgl_error(&self, err: WebGLError) { - // If an error has been detected no further errors must be - // recorded until `getError` has been called - if self.last_error.get().is_none() { - self.last_error.set(Some(err)); - } - } - - pub fn bound_texture_for(&self, target: u32) -> Option<JS<WebGLTexture>> { - match target { - constants::TEXTURE_2D => self.bound_texture_2d.get(), - constants::TEXTURE_CUBE_MAP => self.bound_texture_cube_map.get(), - - _ => unreachable!(), - } - } -} - pub trait LayoutCanvasWebGLRenderingContextHelpers { #[allow(unsafe_code)] unsafe fn get_renderer_id(&self) -> usize; |