diff options
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/canvasrenderingcontext2d.rs | 108 |
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 |