aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/canvasrenderingcontext2d.rs108
1 files changed, 77 insertions, 31 deletions
diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs
index 2d4e38d4884..798e1f558e5 100644
--- a/components/script/dom/canvasrenderingcontext2d.rs
+++ b/components/script/dom/canvasrenderingcontext2d.rs
@@ -275,7 +275,7 @@ impl CanvasRenderingContext2D {
}
fn fetch_image_data(&self,
- image_element: &&HTMLImageElement)
+ image_element: &HTMLImageElement)
-> Option<(Vec<u8>, Size2D<f64>)> {
let url = match image_element.get_url() {
Some(url) => url,
@@ -288,18 +288,36 @@ impl CanvasRenderingContext2D {
};
let image_size = Size2D::new(img.width as f64, img.height as f64);
- let mut image_data = match img.pixels {
+ let image_data = match img.pixels {
PixelsByColorType::RGBA8(ref pixels) => pixels.to_vec(),
PixelsByColorType::K8(_) => panic!("K8 color type not supported"),
PixelsByColorType::RGB8(_) => panic!("RGB8 color type not supported"),
PixelsByColorType::KA8(_) => panic!("KA8 color type not supported"),
};
- // Pixels come from cache in BGRA order and drawImage expects RGBA so we
- // have to swap the color values
- byte_swap(&mut image_data);
+
return Some((image_data, image_size));
}
+ 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_renderer();
+ let (sender, receiver) = channel::<Vec<u8>>();
+ // Reads pixels from source canvas
+ renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::GetImageData(source_rect, image_size, sender))).unwrap();
+
+ return Some((receiver.recv().unwrap(), image_size));
+ }
+
fn request_image_from_cache(&self, url: Url) -> ImageResponse {
let canvas = self.canvas.root();
let window = window_from_node(canvas.r());
@@ -580,7 +598,12 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
// If the image argument is an HTMLImageElement object that is in the broken state,
// then throw an InvalidStateError exception
let (image_data, image_size) = match self.fetch_image_data(&image_element) {
- Some((data, size)) => (data, size),
+ Some((mut data, size)) => {
+ // Pixels come from cache in BGRA order and drawImage expects RGBA so we
+ // have to swap the color values
+ byte_swap(&mut data);
+ (data, size)
+ },
None => return Err(InvalidState),
};
let dw: f64 = image_size.width as f64;
@@ -636,7 +659,12 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
// If the image argument is an HTMLImageElement object that is in the broken state,
// then throw an InvalidStateError exception
let (image_data, image_size) = match self.fetch_image_data(&image_element) {
- Some((data, size)) => (data, size),
+ Some((mut data, size)) => {
+ // Pixels come from cache in BGRA order and drawImage expects RGBA so we
+ // have to swap the color values
+ byte_swap(&mut data);
+ (data, size)
+ },
None => return Err(InvalidState),
};
let sw: f64 = image_size.width as f64;
@@ -677,7 +705,12 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
// If the image argument is an HTMLImageElement object that is in the broken state,
// then throw an InvalidStateError exception
let (image_data, image_size) = match self.fetch_image_data(&image_element) {
- Some((data, size)) => (data, size),
+ Some((mut data, size)) => {
+ // Pixels come from cache in BGRA order and drawImage expects RGBA so we
+ // have to swap the color values
+ byte_swap(&mut data);
+ (data, size)
+ },
None => return Err(InvalidState),
};
return self.draw_image_data(image_data,
@@ -1015,38 +1048,51 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern
fn CreatePattern(self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
repetition: DOMString) -> Fallible<Root<CanvasPattern>> {
- match image {
+ let (image_data, image_size) = match image {
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => {
let image_element = image.r();
-
- let url = match image_element.get_url() {
- Some(url) => url,
+ // https://html.spec.whatwg.org/multipage/#img-error
+ // If the image argument is an HTMLImageElement object that is in the broken state,
+ // then throw an InvalidStateError exception
+ match self.fetch_image_data(&image_element) {
+ Some((data, size)) => (data, size),
None => return Err(InvalidState),
- };
+ }
+ },
+ HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(canvas) => {
+ let canvas_element = canvas.r();
- let img = match self.request_image_from_cache(url) {
- ImageResponse::Loaded(img) => img,
- ImageResponse::PlaceholderLoaded(_) | ImageResponse::None => return Err(InvalidState),
- };
+ 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 image_size = Size2D::new(img.width as f64, img.height as f64);
- let image_data = match img.pixels {
- PixelsByColorType::RGBA8(ref pixels) => pixels.to_vec(),
- PixelsByColorType::K8(_) => panic!("K8 color type not supported"),
- PixelsByColorType::RGB8(_) => panic!("RGB8 color type not supported"),
- PixelsByColorType::KA8(_) => panic!("KA8 color type not supported"),
- };
+ match self.fetch_canvas_data(&canvas_element, source_rect) {
+ 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));
- if let Some(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),
- rep));
+ match self.fetch_canvas_data(&canvas_element, source_rect) {
+ Some((data, size)) => (data, size),
+ None => return Err(InvalidState),
}
- return Err(Syntax);
},
- _ => return Err(Type("Not implemented".to_owned())),
+ };
+
+ if let Some(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),
+ rep));
}
+ return Err(Syntax);
}
// https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth