aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/canvasrenderingcontext2d.rs51
-rw-r--r--components/script/dom/htmlcanvaselement.rs54
-rw-r--r--components/script/dom/webglrenderingcontext.rs52
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;