diff options
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/canvasrenderingcontext2d.rs | 57 | ||||
-rw-r--r-- | components/script/dom/htmlcanvaselement.rs | 10 | ||||
-rw-r--r-- | components/script/dom/imagedata.rs | 87 | ||||
-rw-r--r-- | components/script/dom/mod.rs | 1 | ||||
-rw-r--r-- | components/script/dom/webidls/CanvasRenderingContext2D.webidl | 13 | ||||
-rw-r--r-- | components/script/dom/webidls/ImageData.webidl | 23 |
6 files changed, 183 insertions, 8 deletions
diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 2984a60c270..4b2232ee2f5 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -4,19 +4,24 @@ use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods; +use dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods; +use dom::bindings::error::Error::IndexSize; +use dom::bindings::error::Fallible; use dom::bindings::global::{GlobalRef, GlobalField}; use dom::bindings::js::{JS, JSRef, LayoutJS, Temporary}; use dom::bindings::utils::{Reflector, reflect_dom_object}; -use dom::htmlcanvaselement::HTMLCanvasElement; +use dom::htmlcanvaselement::{HTMLCanvasElement, HTMLCanvasElementHelpers}; +use dom::imagedata::{ImageData, ImageDataHelpers}; use geom::point::Point2D; use geom::rect::Rect; use geom::size::Size2D; use canvas::canvas_paint_task::{CanvasMsg, CanvasPaintTask}; -use canvas::canvas_paint_task::CanvasMsg::{ClearRect, Close, FillRect, Recreate, StrokeRect}; +use canvas::canvas_paint_task::CanvasMsg::{ClearRect, Close, FillRect, Recreate, StrokeRect, GetImageData, PutImageData}; -use std::sync::mpsc::Sender; +use std::num::{Float, ToPrimitive}; +use std::sync::mpsc::{channel, Sender}; #[dom_struct] pub struct CanvasRenderingContext2D { @@ -75,6 +80,52 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32)); self.renderer.send(StrokeRect(rect)).unwrap(); } + + fn CreateImageData(self, sw: f64, sh: f64) -> Fallible<Temporary<ImageData>> { + if sw == 0.0 || sh == 0.0 { + return Err(IndexSize) + } + + Ok(ImageData::new(self.global.root().r(), sw.abs().to_u32().unwrap(), sh.abs().to_u32().unwrap(), None)) + } + + fn CreateImageData_(self, imagedata: JSRef<ImageData>) -> Fallible<Temporary<ImageData>> { + Ok(ImageData::new(self.global.root().r(), imagedata.Width(), imagedata.Height(), None)) + } + + fn GetImageData(self, sx: f64, sy: f64, sw: f64, sh: f64) -> Fallible<Temporary<ImageData>> { + if sw == 0.0 || sh == 0.0 { + return Err(IndexSize) + } + + let (sender, receiver) = channel::<Vec<u8>>(); + let dest_rect = Rect(Point2D(sx.to_i32().unwrap(), sy.to_i32().unwrap()), Size2D(sw.to_i32().unwrap(), sh.to_i32().unwrap())); + let canvas_size = self.canvas.root().r().get_size(); + self.renderer.send(GetImageData(dest_rect, canvas_size, sender)).unwrap(); + let data = receiver.recv().unwrap(); + Ok(ImageData::new(self.global.root().r(), sw.abs().to_u32().unwrap(), sh.abs().to_u32().unwrap(), Some(data))) + } + + fn PutImageData(self, imagedata: JSRef<ImageData>, dx: f64, dy: f64) { + let data = imagedata.get_data_array(&self.global.root().r()); + let image_data_rect = Rect(Point2D(dx.to_i32().unwrap(), dy.to_i32().unwrap()), imagedata.get_size()); + let dirty_rect = None; + let canvas_size = self.canvas.root().r().get_size(); + self.renderer.send(PutImageData(data, image_data_rect, dirty_rect, canvas_size)).unwrap() + } + + fn PutImageData_(self, imagedata: JSRef<ImageData>, dx: f64, dy: f64, + dirtyX: f64, dirtyY: f64, dirtyWidth: f64, dirtyHeight: f64) { + let data = imagedata.get_data_array(&self.global.root().r()); + let image_data_rect = Rect(Point2D(dx.to_i32().unwrap(), dy.to_i32().unwrap()), + Size2D(imagedata.Width().to_i32().unwrap(), + imagedata.Height().to_i32().unwrap())); + let dirty_rect = Some(Rect(Point2D(dirtyX.to_i32().unwrap(), dirtyY.to_i32().unwrap()), + Size2D(dirtyWidth.to_i32().unwrap(), + dirtyHeight.to_i32().unwrap()))); + let canvas_size = self.canvas.root().r().get_size(); + self.renderer.send(PutImageData(data, image_data_rect, dirty_rect, canvas_size)).unwrap() + } } #[unsafe_destructor] diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 60ff0f88f82..c3ea7fe6cb1 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -83,6 +83,16 @@ impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { } } +pub trait HTMLCanvasElementHelpers { + fn get_size(&self) -> Size2D<i32>; +} + +impl<'a> HTMLCanvasElementHelpers for JSRef<'a, HTMLCanvasElement> { + fn get_size(&self) -> Size2D<i32> { + Size2D(self.Width() as i32, self.Height() as i32) + } +} + impl<'a> HTMLCanvasElementMethods for JSRef<'a, HTMLCanvasElement> { fn Width(self) -> u32 { self.width.get() diff --git a/components/script/dom/imagedata.rs b/components/script/dom/imagedata.rs new file mode 100644 index 00000000000..4c88da4786d --- /dev/null +++ b/components/script/dom/imagedata.rs @@ -0,0 +1,87 @@ +/* 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 http://mozilla.org/MPL/2.0/. */ + +use dom::bindings::codegen::Bindings::ImageDataBinding; +use dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods; +use dom::bindings::global::GlobalRef; +use dom::bindings::js::{JSRef, Temporary}; +use dom::bindings::utils::{Reflector, reflect_dom_object}; +use geom::size::Size2D; +use js::jsapi::{JSContext, JSObject}; +use js::jsfriendapi::bindgen::{JS_NewUint8ClampedArray, JS_GetUint8ClampedArrayData}; +use libc::uint8_t; +use std::vec::Vec; +use collections::slice; +use std::ptr; + +#[dom_struct] +#[allow(raw_pointer_derive)] +pub struct ImageData { + reflector_: Reflector, + width: u32, + height: u32, + data: *mut JSObject, +} + +impl ImageData { + #[allow(unsafe_blocks)] + fn new_inherited(width: u32, height: u32, data: Option<Vec<u8>>, global: GlobalRef) -> ImageData { + unsafe { + let cx = global.get_cx(); + let js_object: *mut JSObject = JS_NewUint8ClampedArray(cx, width * height * 4); + + if let Some(vec) = data { + let js_object_data: *mut uint8_t = JS_GetUint8ClampedArrayData(js_object, cx); + ptr::copy_nonoverlapping_memory(js_object_data, vec.as_ptr(), vec.len()) + } + + ImageData { + reflector_: Reflector::new(), + width: width, + height: height, + data: js_object, + } + } + } + + pub fn new(global: GlobalRef, width: u32, height: u32, data: Option<Vec<u8>>) -> Temporary<ImageData> { + reflect_dom_object(box ImageData::new_inherited(width, height, data, global), + global, ImageDataBinding::Wrap) + } +} + +pub trait ImageDataHelpers { + fn get_data_array(self, global: &GlobalRef) -> Vec<u8>; + fn get_size(&self) -> Size2D<i32>; +} + +impl<'a> ImageDataHelpers for JSRef<'a, ImageData> { + #[allow(unsafe_blocks)] + fn get_data_array(self, global: &GlobalRef) -> Vec<u8> { + unsafe { + let cx = global.get_cx(); + let data: *const uint8_t = JS_GetUint8ClampedArrayData(self.Data(cx), cx) as *const uint8_t; + let len = self.Width() * self.Height() * 4; + slice::from_raw_parts(data, len as uint).to_vec() + } + } + + fn get_size(&self) -> Size2D<i32> { + Size2D(self.Width() as i32, self.Height() as i32) + } +} + +impl<'a> ImageDataMethods for JSRef<'a, ImageData> { + fn Width(self) -> u32 { + self.width + } + + fn Height(self) -> u32 { + self.height + } + + fn Data(self, _: *mut JSContext) -> *mut JSObject { + self.data + } +} diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index d5446e525b4..1d95cf1d2d5 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -290,6 +290,7 @@ pub mod htmltrackelement; pub mod htmlulistelement; pub mod htmlvideoelement; pub mod htmlunknownelement; +pub mod imagedata; pub mod keyboardevent; pub mod location; pub mod messageevent; diff --git a/components/script/dom/webidls/CanvasRenderingContext2D.webidl b/components/script/dom/webidls/CanvasRenderingContext2D.webidl index 2043347bfd2..6cef3012c25 100644 --- a/components/script/dom/webidls/CanvasRenderingContext2D.webidl +++ b/components/script/dom/webidls/CanvasRenderingContext2D.webidl @@ -96,9 +96,12 @@ interface CanvasRenderingContext2D { //void removeHitRegion(DOMString id); // pixel manipulation - //ImageData createImageData(double sw, double sh); - //ImageData createImageData(ImageData imagedata); - //ImageData getImageData(double sx, double sy, double sw, double sh); - //void putImageData(ImageData imagedata, double dx, double dy); - //void putImageData(ImageData imagedata, double dx, double dy, double dirtyX, double dirtyY, double dirtyWidth, double dirtyHeight); + [Throws] + ImageData createImageData(double sw, double sh); + [Throws] + ImageData createImageData(ImageData imagedata); + [Throws] + ImageData getImageData(double sx, double sy, double sw, double sh); + void putImageData(ImageData imagedata, double dx, double dy); + void putImageData(ImageData imagedata, double dx, double dy, double dirtyX, double dirtyY, double dirtyWidth, double dirtyHeight); }; diff --git a/components/script/dom/webidls/ImageData.webidl b/components/script/dom/webidls/ImageData.webidl new file mode 100644 index 00000000000..23f54a61e7d --- /dev/null +++ b/components/script/dom/webidls/ImageData.webidl @@ -0,0 +1,23 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#imagedata + * + * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and Opera Software ASA. + * You are granted a license to use, reproduce and create derivative works of this document. + */ + +//[Constructor(unsigned long sw, unsigned long sh), +//Constructor(Uint8ClampedArray data, unsigned long sw, optional unsigned long sh), +//Exposed=(Window,Worker)] +interface ImageData { + //[Constant] + readonly attribute unsigned long width; + //[Constant] + readonly attribute unsigned long height; + //[Constant, StoreInSlot] + readonly attribute Uint8ClampedArray data; +};
\ No newline at end of file |