diff options
44 files changed, 1569 insertions, 120 deletions
diff --git a/components/canvas/canvas_paint_task.rs b/components/canvas/canvas_paint_task.rs index c8781419f10..4822fd48750 100644 --- a/components/canvas/canvas_paint_task.rs +++ b/components/canvas/canvas_paint_task.rs @@ -16,7 +16,6 @@ use util::vec::byte_swap; use cssparser::RGBA; use std::borrow::ToOwned; -use std::ops::Add; use std::sync::mpsc::{channel, Sender}; #[derive(Clone)] @@ -27,6 +26,8 @@ pub enum CanvasMsg { BeginPath, ClosePath, Fill, + DrawImage(Vec<u8>, Rect<i32>, Rect<i32>, bool), + DrawImageSelf(Size2D<i32>, Rect<i32>, Rect<i32>, bool), MoveTo(Point2D<f32>), LineTo(Point2D<f32>), QuadraticCurveTo(Point2D<f32>, Point2D<f32>), @@ -38,10 +39,140 @@ pub enum CanvasMsg { Recreate(Size2D<i32>), SendPixelContents(Sender<Vec<u8>>), GetImageData(Rect<i32>, Size2D<i32>, Sender<Vec<u8>>), - PutImageData(Vec<u8>, Rect<i32>, Option<Rect<i32>>, Size2D<i32>), + PutImageData(Vec<u8>, Rect<i32>, Option<Rect<i32>>), Close, } +impl<'a> CanvasPaintTask<'a> { + /// It reads image data from the canvas + /// canvas_size: The size of the canvas we're reading from + /// read_rect: The area of the canvas we want to read from + fn read_pixels(&self, read_rect: Rect<i32>, canvas_size: Size2D<i32>) -> Vec<u8>{ + let canvas_rect = Rect(Point2D(0i32, 0i32), canvas_size); + let src_read_rect = canvas_rect.intersection(&read_rect).unwrap_or(Rect::zero()); + + let mut image_data = Vec::new(); + if src_read_rect.is_empty() || canvas_size.width <= 0 && canvas_size.height <= 0 { + return image_data; + } + + let data_surface = self.drawtarget.snapshot().get_data_surface(); + let mut src_data = Vec::new(); + data_surface.with_data(|element| { src_data = element.to_vec(); }); + let stride = data_surface.stride(); + + //start offset of the copyable rectangle + let mut src = (src_read_rect.origin.y * stride + src_read_rect.origin.x * 4) as usize; + //copy the data to the destination vector + for _ in range(0, src_read_rect.size.height) { + let row = &src_data[src .. src + (4 * src_read_rect.size.width) as usize]; + image_data.push_all(row); + src += stride as usize; + } + + image_data + } + + /// It writes image data to the canvas + /// source_rect: the area of the image data to be written + /// dest_rect: The area of the canvas where the imagedata will be copied + /// smoothing_enabled: if smoothing is applied to the copied pixels + fn write_pixels(&self, imagedata: &Vec<u8>, + image_size: Size2D<i32>, + source_rect: Rect<i32>, + dest_rect: Rect<i32>, + smoothing_enabled: bool) { + // From spec https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-drawimage + // When scaling up, if the imageSmoothingEnabled attribute is set to true, the user agent should attempt + // to apply a smoothing algorithm to the image data when it is scaled. + // Otherwise, the image must be rendered using nearest-neighbor interpolation. + let filter = if smoothing_enabled { + Filter::Linear + } else { + Filter::Point + }; + + let source_surface = self.drawtarget.create_source_surface_from_data(imagedata.as_slice(), + image_size, image_size.width * 4, SurfaceFormat::B8G8R8A8); + + let draw_surface_options = DrawSurfaceOptions::new(filter, true); + let draw_options = DrawOptions::new(1.0f64 as AzFloat, 0); + + self.drawtarget.draw_surface(source_surface, + dest_rect.to_azfloat(), + source_rect.to_azfloat(), + draw_surface_options, draw_options); + } + + /// dirty_rect: original dirty_rect provided by the putImageData call + /// image_data_rect: the area of the image to be copied + /// Result: It retuns the modified dirty_rect by the rules described in + /// the spec https://html.spec.whatwg.org/#dom-context-2d-putimagedata + fn calculate_dirty_rect(&self, + mut dirty_rect: Rect<i32>, + image_data_rect: Rect<i32>) -> Rect<i32>{ + // 1) If dirtyWidth is negative, + // let dirtyX be dirtyX+dirtyWidth, + // and let dirtyWidth be equal to the absolute magnitude of dirtyWidth. + if dirty_rect.size.width < 0 { + dirty_rect.origin.x = dirty_rect.origin.x + dirty_rect.size.width; + dirty_rect.size.width = -dirty_rect.size.width; + } + + // 2) If dirtyHeight is negative, let dirtyY be dirtyY+dirtyHeight, + // and let dirtyHeight be equal to the absolute magnitude of dirtyHeight. + if dirty_rect.size.height < 0 { + dirty_rect.origin.y = dirty_rect.origin.y + dirty_rect.size.height; + dirty_rect.size.height = -dirty_rect.size.height; + } + + // 3) If dirtyX is negative, let dirtyWidth be dirtyWidth+dirtyX, and let dirtyX be zero. + if dirty_rect.origin.x < 0 { + dirty_rect.size.width += dirty_rect.origin.x; + dirty_rect.origin.x = 0; + } + + // 3) If dirtyY is negative, let dirtyHeight be dirtyHeight+dirtyY, and let dirtyY be zero. + if dirty_rect.origin.y < 0 { + dirty_rect.size.height += dirty_rect.origin.y; + dirty_rect.origin.y = 0; + } + + // 4) If dirtyX+dirtyWidth is greater than the width attribute of the imagedata argument, + // let dirtyWidth be the value of that width attribute, minus the value of dirtyX. + if dirty_rect.origin.x + dirty_rect.size.width > image_data_rect.size.width { + dirty_rect.size.width = image_data_rect.size.width - dirty_rect.origin.x; + } + + // 4) If dirtyY+dirtyHeight is greater than the height attribute of the imagedata argument, + // let dirtyHeight be the value of that height attribute, minus the value of dirtyY. + if dirty_rect.origin.y + dirty_rect.size.height > image_data_rect.size.height { + dirty_rect.size.height = image_data_rect.size.height - dirty_rect.origin.y; + } + + dirty_rect + } + + /// It writes an image to the destination canvas + /// imagedata: Pixel information of the image to be written + /// source_rect: Area of the source image to be copied + /// dest_rect: Area of the destination canvas where the pixels will be copied + /// smoothing_enabled: It determines if smoothing is applied to the image result + fn write_image(&self, mut imagedata: Vec<u8>, + source_rect: Rect<i32>, dest_rect: Rect<i32>, smoothing_enabled: bool) { + if imagedata.len() == 0 { + return + } + // Image data already contains the portion of the image we want to draw + // so the source rect corresponds to the whole area of the copied imagedata + let source_rect = Rect(Point2D(0i32, 0i32), source_rect.size); + // rgba -> bgra + byte_swap(imagedata.as_mut_slice()); + self.write_pixels(&imagedata, source_rect.size, source_rect, dest_rect, smoothing_enabled); + } + +} + pub struct CanvasPaintTask<'a> { drawtarget: DrawTarget, fill_style: Pattern, @@ -80,6 +211,12 @@ impl<'a> CanvasPaintTask<'a> { CanvasMsg::BeginPath => painter.begin_path(), CanvasMsg::ClosePath => painter.close_path(), CanvasMsg::Fill => painter.fill(), + CanvasMsg::DrawImage(imagedata, dest_rect, source_rect, smoothing_enabled) => { + painter.draw_image(imagedata, dest_rect, source_rect, smoothing_enabled) + } + CanvasMsg::DrawImageSelf(image_size, dest_rect, source_rect, smoothing_enabled) => { + painter.draw_image_self(image_size, dest_rect, source_rect, smoothing_enabled) + } CanvasMsg::MoveTo(ref point) => painter.move_to(point), CanvasMsg::LineTo(ref point) => painter.line_to(point), CanvasMsg::QuadraticCurveTo(ref cp, ref pt) => { @@ -97,8 +234,8 @@ impl<'a> CanvasPaintTask<'a> { CanvasMsg::Recreate(size) => painter.recreate(size), CanvasMsg::SendPixelContents(chan) => painter.send_pixel_contents(chan), CanvasMsg::GetImageData(dest_rect, canvas_size, chan) => painter.get_image_data(dest_rect, canvas_size, chan), - CanvasMsg::PutImageData(imagedata, image_data_rect, dirty_rect, canvas_size) - => painter.put_image_data(imagedata, image_data_rect, dirty_rect, canvas_size), + CanvasMsg::PutImageData(imagedata, image_data_rect, dirty_rect) + => painter.put_image_data(imagedata, image_data_rect, dirty_rect), CanvasMsg::Close => break, } } @@ -147,6 +284,21 @@ impl<'a> CanvasPaintTask<'a> { }; } + fn draw_image(&self, imagedata: Vec<u8>, dest_rect: Rect<i32>, + source_rect: Rect<i32>, smoothing_enabled: bool) { + self.write_image(imagedata, source_rect, dest_rect, smoothing_enabled); + } + + fn draw_image_self(&self, image_size: Size2D<i32>, + dest_rect: Rect<i32>, source_rect: Rect<i32>, + smoothing_enabled: bool) { + // Reads pixels from source image + // In this case source and target are the same canvas + let imagedata = self.read_pixels(source_rect, image_size); + // Writes on target canvas + self.write_image(imagedata, source_rect, dest_rect, smoothing_enabled); + } + fn move_to(&self, point: &Point2D<AzFloat>) { self.path_builder.move_to(*point) } @@ -220,36 +372,16 @@ impl<'a> CanvasPaintTask<'a> { dest_rect.size.height = 1; } - let canvas_rect = Rect(Point2D(0i32, 0i32), canvas_size); - let src_read_rect = canvas_rect.intersection(&dest_rect).unwrap_or(Rect::zero()); - - let mut dest_data = Vec::new(); - //load the canvas data to the source vector - if !src_read_rect.is_empty() && canvas_size.width != 0 && canvas_size.height != 0 { - let data_surface = self.drawtarget.snapshot().get_data_surface(); - let mut src_data = Vec::new(); - data_surface.with_data(|element| { - src_data = element.to_vec(); - }); - - let stride = data_surface.stride(); - - //start offset of the copyable rectangle - let mut src = (src_read_rect.origin.y * stride + src_read_rect.origin.x * 4) as usize; - //copy the data to the destination vector - for _ in 0..src_read_rect.size.height { - let row = &src_data[src .. src + (4 * src_read_rect.size.width) as usize]; - dest_data.push_all(row); - src += stride as usize; - } - } + let mut dest_data = self.read_pixels(dest_rect, canvas_size); + // bgra -> rgba byte_swap(dest_data.as_mut_slice()); chan.send(dest_data).unwrap(); } - fn put_image_data(&mut self, mut imagedata: Vec<u8>, image_data_rect: Rect<i32>, - dirty_rect: Option<Rect<i32>>, canvas_size: Size2D<i32>) { + fn put_image_data(&mut self, mut imagedata: Vec<u8>, + image_data_rect: Rect<i32>, + dirty_rect: Option<Rect<i32>>) { if image_data_rect.size.width <= 0 || image_data_rect.size.height <= 0 { return @@ -259,46 +391,37 @@ impl<'a> CanvasPaintTask<'a> { // rgba -> bgra byte_swap(imagedata.as_mut_slice()); - let new_image_data_rect = Rect(Point2D(0i32, 0i32), - Size2D(image_data_rect.size.width, image_data_rect.size.height)); - - let new_dirty_rect = match dirty_rect { - Some(mut dirty_rect) => { - if dirty_rect.size.width < 0 { - dirty_rect.origin.x = dirty_rect.origin.x + dirty_rect.size.width; - dirty_rect.size.width = -dirty_rect.size.width; - } - if dirty_rect.size.height < 0 { - dirty_rect.origin.y = dirty_rect.origin.y + dirty_rect.size.height; - dirty_rect.size.height = -dirty_rect.size.height; - } - new_image_data_rect.intersection(&dirty_rect) - }, - None => Some(new_image_data_rect) + let image_rect = Rect(Point2D(0i32, 0i32), + Size2D(image_data_rect.size.width, image_data_rect.size.height)); + + // Dirty rectangle defines the area of the source image to be copied + // on the destination canvas + let source_rect = match dirty_rect { + Some(dirty_rect) => + self.calculate_dirty_rect(dirty_rect, image_data_rect), + // If no dirty area is provided we consider the whole source image + // as the area to be copied to the canvas + None => image_rect, }; - if let Some(new_dirty_rect) = new_dirty_rect { - let moved_dirty_rect = Rect(new_dirty_rect.origin.add(image_data_rect.origin), - new_dirty_rect.size).intersection(&Rect(Point2D(0i32, 0i32), - canvas_size)).unwrap_or(Rect::zero()); - if moved_dirty_rect.is_empty() { - return - } - - let source_surface = self.drawtarget.create_source_surface_from_data(&imagedata, - image_data_rect.size, image_data_rect.size.width * 4, SurfaceFormat::B8G8R8A8); - - let draw_surface_options = DrawSurfaceOptions::new(Filter::Linear, true); - let draw_options = DrawOptions::new(1.0f64 as AzFloat, 0); - - self.drawtarget.draw_surface(source_surface, - Rect(Point2D(moved_dirty_rect.origin.x as AzFloat, moved_dirty_rect.origin.y as AzFloat), - Size2D(moved_dirty_rect.size.width as AzFloat, moved_dirty_rect.size.height as AzFloat)), - Rect(Point2D((moved_dirty_rect.origin.x - image_data_rect.origin.x) as AzFloat, - (moved_dirty_rect.origin.y - image_data_rect.origin.y) as AzFloat), - Size2D(moved_dirty_rect.size.width as AzFloat, moved_dirty_rect.size.height as AzFloat)), - draw_surface_options, draw_options); + // 5) If either dirtyWidth or dirtyHeight is negative or zero, + // stop without affecting any bitmaps + if source_rect.size.width <= 0 || source_rect.size.height <= 0 { + return } + + // 6) For all integer values of x and y where dirtyX ≤ x < dirty + // X+dirtyWidth and dirtyY ≤ y < dirtyY+dirtyHeight, copy the + // four channels of the pixel with coordinate (x, y) in the imagedata + // data structure's Canvas Pixel ArrayBuffer to the pixel with coordinate + // (dx+x, dy+y) in the rendering context's scratch bitmap. + // It also clips the destination rectangle to the canvas area + let dest_rect = Rect( + Point2D(image_data_rect.origin.x + source_rect.origin.x, + image_data_rect.origin.y + source_rect.origin.y), + Size2D(source_rect.size.width, source_rect.size.height)); + + self.write_pixels(&imagedata, image_data_rect.size, source_rect, dest_rect, true) } } @@ -404,3 +527,14 @@ impl FillOrStrokeStyle { } } } + +pub trait ToAzFloat { + fn to_azfloat(&self) -> Rect<AzFloat>; +} + +impl ToAzFloat for Rect<i32> { + fn to_azfloat(&self) -> Rect<AzFloat> { + Rect(Point2D(self.origin.x as AzFloat, self.origin.y as AzFloat), + Size2D(self.size.width as AzFloat, self.size.height as AzFloat)) + } +} diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 4c2e05b4b9e..58f3b51ab05 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -6,6 +6,7 @@ use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasWindingRule; use dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods; +use dom::bindings::codegen::UnionTypes::HTMLCanvasElementOrCanvasRenderingContext2D; use dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern; use dom::bindings::error::Error::{IndexSize, TypeError}; use dom::bindings::error::Fallible; @@ -37,6 +38,7 @@ pub struct CanvasRenderingContext2D { global: GlobalField, renderer: Sender<CanvasMsg>, canvas: JS<HTMLCanvasElement>, + image_smoothing_enabled: Cell<bool>, stroke_color: Cell<RGBA>, fill_color: Cell<RGBA>, transform: Cell<Matrix2D<f32>>, @@ -56,6 +58,7 @@ impl CanvasRenderingContext2D { global: GlobalField::from_rooted(&global), renderer: CanvasPaintTask::start(size), canvas: JS::from_rooted(canvas), + image_smoothing_enabled: Cell::new(true), stroke_color: Cell::new(black), fill_color: Cell::new(black), transform: Cell::new(Matrix2D::identity()), @@ -75,6 +78,120 @@ impl CanvasRenderingContext2D { fn update_transform(&self) { self.renderer.send(CanvasMsg::SetTransform(self.transform.get())).unwrap() } + + // It is used by DrawImage to calculate the size of the source and destination rectangles based + // on the drawImage call arguments + // source rectangle = area of the original image to be copied + // destination rectangle = area of the destination canvas where the source image is going to be drawn + fn adjust_source_dest_rects(&self, + canvas: JSRef<HTMLCanvasElement>, + sx: f64, sy: f64, sw: f64, sh: f64, + dx: f64, dy: f64, dw: f64, dh: f64) -> (Rect<i32>, Rect<i32>) { + let image_size = canvas.get_size(); + let image_rect = Rect(Point2D(0f64, 0f64), + Size2D(image_size.width as f64, image_size.height as f64)); + + // The source rectangle is the rectangle whose corners are the four points (sx, sy), + // (sx+sw, sy), (sx+sw, sy+sh), (sx, sy+sh). + let source_rect = Rect(Point2D(sx, sy), + Size2D(sw, sh)); + + // When the source rectangle is outside the source image, + // the source rectangle must be clipped to the source image + let source_rect_clipped = source_rect.intersection(&image_rect).unwrap_or(Rect::zero()); + + // Width and height ratios between the non clipped and clipped source rectangles + let width_ratio: f64 = source_rect_clipped.size.width / source_rect.size.width; + let height_ratio: f64 = source_rect_clipped.size.height / source_rect.size.height; + + // When the source rectangle is outside the source image, + // the destination rectangle must be clipped in the same proportion. + let dest_rect_width_scaled: f64 = dw * width_ratio; + let dest_rect_height_scaled: f64 = dh * height_ratio; + + // The destination rectangle is the rectangle whose corners are the four points (dx, dy), + // (dx+dw, dy), (dx+dw, dy+dh), (dx, dy+dh). + let dest_rect = Rect(Point2D(dx.to_i32().unwrap(), + dy.to_i32().unwrap()), + Size2D(dest_rect_width_scaled.to_i32().unwrap(), + dest_rect_height_scaled.to_i32().unwrap())); + + let source_rect = Rect(Point2D(source_rect_clipped.origin.x.to_i32().unwrap(), + source_rect_clipped.origin.y.to_i32().unwrap()), + Size2D(source_rect_clipped.size.width.to_i32().unwrap(), + source_rect_clipped.size.height.to_i32().unwrap())); + + return (source_rect, dest_rect) + } + + // + // drawImage coordinates explained + // + // Source Image Destination Canvas + // +-------------+ +-------------+ + // | | | | + // |(sx,sy) | |(dx,dy) | + // | +----+ | | +----+ | + // | | | | | | | | + // | | |sh |---->| | |dh | + // | | | | | | | | + // | +----+ | | +----+ | + // | sw | | dw | + // | | | | + // +-------------+ +-------------+ + // + // + // The rectangle (sx, sy, sw, sh) from the source image + // is copied on the rectangle (dx, dy, dh, dw) of the destination canvas + // + // https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-drawimage + fn draw_html_canvas_element(&self, + canvas: JSRef<HTMLCanvasElement>, + sx: f64, sy: f64, sw: f64, sh: f64, + dx: f64, dy: f64, dw: f64, dh: f64) -> Fallible<()> { + + // 1. Check the usability of the image argument + if !canvas.is_valid() { + return Ok(()) + } + + // 2. Establish the source and destination rectangles + let (source_rect, dest_rect) = self.adjust_source_dest_rects(canvas, sx, sy, sw, sh, dx, dy, dw, dh); + + if !is_rect_valid(source_rect) || !is_rect_valid(dest_rect) { + return Err(IndexSize) + } + + let smoothing_enabled = self.image_smoothing_enabled.get(); + let canvas_size = canvas.get_size(); + + // If the source and target canvas are the same + let msg = if self.canvas.root().r() == canvas { + CanvasMsg::DrawImageSelf(canvas_size, dest_rect, source_rect, smoothing_enabled) + } else { // Source and target canvases are different + let context = canvas.get_2d_context().root(); + let renderer = context.r().get_renderer(); + let (sender, receiver) = channel::<Vec<u8>>(); + // Reads pixels from source image + renderer.send(CanvasMsg::GetImageData(source_rect, canvas_size, sender)).unwrap(); + let imagedata = receiver.recv().unwrap(); + // Writes pixels to destination canvas + CanvasMsg::DrawImage(imagedata, dest_rect, source_rect, smoothing_enabled) + }; + + self.renderer.send(msg).unwrap(); + Ok(()) + } +} + +pub trait CanvasRenderingContext2DHelpers { + fn get_renderer(&self) -> Sender<CanvasMsg>; +} + +impl CanvasRenderingContext2DHelpers for CanvasRenderingContext2D { + fn get_renderer(&self) -> Sender<CanvasMsg> { + self.renderer.clone() + } } pub trait LayoutCanvasRenderingContext2DHelpers { @@ -151,6 +268,102 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> self.renderer.send(CanvasMsg::Fill).unwrap(); } + // https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-drawimage + fn DrawImage(self, image: HTMLCanvasElementOrCanvasRenderingContext2D, + dx: f64, dy: f64) -> Fallible<()> { + + // From rules described in the spec: + // If the sx, sy, sw, and sh arguments are omitted, they must default to 0, 0, + // the image's intrinsic width in image pixels, + // and the image's intrinsic height in image pixels, respectively + let sx: f64 = 0f64; + let sy: f64 = 0f64; + + match image { + HTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(image) => { + let canvas = image.root(); + let canvas_size = canvas.r().get_size(); + let dw: f64 = canvas_size.width as f64; + let dh: f64 = canvas_size.height as f64; + let sw: f64 = dw; + let sh: f64 = dh; + return self.draw_html_canvas_element(canvas.r(), + sx, sy, sw, sh, + dx, dy, dw, dh) + } + HTMLCanvasElementOrCanvasRenderingContext2D::eCanvasRenderingContext2D(image) => { + let image = image.root(); + let context = image.r(); + let canvas = context.Canvas().root(); + let canvas_size = canvas.r().get_size(); + let dw: f64 = canvas_size.width as f64; + let dh: f64 = canvas_size.height as f64; + let sw: f64 = dw; + let sh: f64 = dh; + return self.draw_html_canvas_element(canvas.r(), + sx, sy, sw, sh, + dx, dy, dw, dh) + } + } + } + + // https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-drawimage + fn DrawImage_(self, image: HTMLCanvasElementOrCanvasRenderingContext2D, + dx: f64, dy: f64, dw: f64, dh: f64) -> Fallible<()> { + + // From rules described in the spec: + // If the sx, sy, sw, and sh arguments are omitted, they must default to 0, 0, + // the image's intrinsic width in image pixels, + // and the image's intrinsic height in image pixels, respectively + let sx: f64 = 0f64; + let sy: f64 = 0f64; + + match image { + HTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(image) => { + let canvas = image.root(); + let canvas_size = canvas.r().get_size(); + let sw: f64 = canvas_size.width as f64; + let sh: f64 = canvas_size.height as f64; + return self.draw_html_canvas_element(canvas.r(), + sx, sy, sw, sh, + dx, dy, dw, dh) + } + HTMLCanvasElementOrCanvasRenderingContext2D::eCanvasRenderingContext2D(image) => { + let image = image.root(); + let context = image.r(); + let canvas = context.Canvas().root(); + let canvas_size = canvas.r().get_size(); + let sw: f64 = canvas_size.width as f64; + let sh: f64 = canvas_size.height as f64; + return self.draw_html_canvas_element(canvas.r(), + sx, sy, sw, sh, + dx, dy, dw, dh) + } + } + } + + // https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-drawimage + fn DrawImage__(self, image: HTMLCanvasElementOrCanvasRenderingContext2D, + sx: f64, sy: f64, sw: f64, sh: f64, + dx: f64, dy: f64, dw: f64, dh: f64) -> Fallible<()> { + match image { + HTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(image) => { + let canvas = image.root(); + return self.draw_html_canvas_element(canvas.r(), + sx, sy, sw, sh, + dx, dy, dw, dh) + } + HTMLCanvasElementOrCanvasRenderingContext2D::eCanvasRenderingContext2D(image) => { + let image = image.root(); + let context = image.r(); + let canvas = context.Canvas().root(); + return self.draw_html_canvas_element(canvas.r(), + sx, sy, sw, sh, + dx, dy, dw, dh) + } + } + } + fn MoveTo(self, x: f64, y: f64) { self.renderer.send(CanvasMsg::MoveTo(Point2D(x as f32, y as f32))).unwrap(); } @@ -175,6 +388,16 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> start as f32, end as f32, ccw)).unwrap(); } + // https://html.spec.whatwg.org/#dom-context-2d-imagesmoothingenabled + fn ImageSmoothingEnabled(self) -> bool { + self.image_smoothing_enabled.get() + } + + // https://html.spec.whatwg.org/#dom-context-2d-imagesmoothingenabled + fn SetImageSmoothingEnabled(self, value: bool) -> () { + self.image_smoothing_enabled.set(value); + } + fn StrokeStyle(self) -> StringOrCanvasGradientOrCanvasPattern { // FIXME(pcwalton, #4761): This is not spec-compliant. See: // @@ -261,8 +484,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> 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(CanvasMsg::PutImageData(data, image_data_rect, dirty_rect, canvas_size)).unwrap() + self.renderer.send(CanvasMsg::PutImageData(data, image_data_rect, dirty_rect)).unwrap() } fn PutImageData_(self, imagedata: JSRef<ImageData>, dx: f64, dy: f64, @@ -274,8 +496,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> 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(CanvasMsg::PutImageData(data, image_data_rect, dirty_rect, canvas_size)).unwrap() + self.renderer.send(CanvasMsg::PutImageData(data, image_data_rect, dirty_rect)).unwrap() } fn CreateLinearGradient(self, x0: f64, y0: f64, x1: f64, y1: f64) -> Fallible<Temporary<CanvasGradient>> { @@ -309,3 +530,8 @@ pub fn parse_color(string: &str) -> Result<RGBA,()> { } } +// Used by drawImage to determine if a source or destination rectangle is valid +// Origin coordinates and size cannot be negative. Size has to be greater than zero +fn is_rect_valid(rect: Rect<i32>) -> bool { + rect.origin.x >= 0 && rect.origin.y >= 0 && rect.size.width > 0 && rect.size.height > 0 +} diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 9c3c11d5dbc..e4fc68565a3 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -91,12 +91,22 @@ impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { pub trait HTMLCanvasElementHelpers { fn get_size(&self) -> Size2D<i32>; + fn get_2d_context(self) -> Temporary<CanvasRenderingContext2D>; + fn is_valid(self) -> bool; } impl<'a> HTMLCanvasElementHelpers for JSRef<'a, HTMLCanvasElement> { fn get_size(&self) -> Size2D<i32> { Size2D(self.Width() as i32, self.Height() as i32) } + + fn get_2d_context(self) -> Temporary<CanvasRenderingContext2D> { + self.GetContext(String::from_str("2d")).unwrap() + } + + fn is_valid(self) -> bool { + self.height.get() != 0 && self.width.get() != 0 + } } impl<'a> HTMLCanvasElementMethods for JSRef<'a, HTMLCanvasElement> { diff --git a/components/script/dom/webidls/CanvasRenderingContext2D.webidl b/components/script/dom/webidls/CanvasRenderingContext2D.webidl index 1cc40eb0f3f..0218600bba1 100644 --- a/components/script/dom/webidls/CanvasRenderingContext2D.webidl +++ b/components/script/dom/webidls/CanvasRenderingContext2D.webidl @@ -6,6 +6,12 @@ enum CanvasWindingRule { "nonzero", "evenodd" }; // http://www.whatwg.org/html/#2dcontext +typedef (/* HTMLImageElement or + HTMLVideoElement or */ + HTMLCanvasElement or + CanvasRenderingContext2D /* or + ImageBitmap */) CanvasImageSource; + //[Constructor(optional unsigned long width, unsigned long height), Exposed=Window,Worker] interface CanvasRenderingContext2D { @@ -47,7 +53,7 @@ interface CanvasRenderingContext2D { // attribute DOMString globalCompositeOperation; // (default source-over) // image smoothing - // attribute boolean imageSmoothingEnabled; // (default true) + attribute boolean imageSmoothingEnabled; // (default true) // colours and styles (see also the CanvasDrawingStyles interface) attribute (DOMString or CanvasGradient or CanvasPattern) strokeStyle; // (default black) @@ -101,9 +107,12 @@ interface CanvasRenderingContext2D { //TextMetrics measureText(DOMString text); // drawing images - //void drawImage(CanvasImageSource image, unrestricted double dx, unrestricted double dy); - //void drawImage(CanvasImageSource image, unrestricted double dx, unrestricted double dy, unrestricted double dw, unrestricted double dh); - //void drawImage(CanvasImageSource image, unrestricted double sx, unrestricted double sy, unrestricted double sw, unrestricted double sh, unrestricted double dx, unrestricted double dy, unrestricted double dw, unrestricted double dh); + [Throws] + void drawImage(CanvasImageSource image, /* unrestricted */ double dx, /* unrestricted */ double dy); + [Throws] + void drawImage(CanvasImageSource image, /* unrestricted */ double dx, /* unrestricted */ double dy, /* unrestricted */ double dw, /* unrestricted */ double dh); + [Throws] + void drawImage(CanvasImageSource image, /* unrestricted */ double sx, /* unrestricted */ double sy, /* unrestricted */ double sw, /* unrestricted */ double sh, /* unrestricted */ double dx, /* unrestricted */ double dy, /* unrestricted */ double dw, /* unrestricted */ double dh); // hit regions //void addHitRegion(optional HitRegionOptions options); @@ -135,7 +144,7 @@ interface CanvasPathMethods { /*unrestricted*/ double x, /*unrestricted*/ double y); - //void arcTo(double x1, double y1, double x2, double y2, double radius); + //void arcTo(double x1, double y1, double x2, double y2, double radius); // NOT IMPLEMENTED [LenientFloat] void arcTo(double x1, double y1, double x2, double y2, double radiusX, double radiusY, double rotation); //void rect(double x, double y, double w, double h); diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index bc520d62f3e..750871127ad 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -898,6 +898,7 @@ dependencies = [ name = "util" version = "0.0.1" dependencies = [ + "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "bitflags 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.2.0 (git+https://github.com/servo/rust-cssparser)", "geom 0.1.0 (git+https://github.com/servo/rust-geom)", diff --git a/components/util/Cargo.toml b/components/util/Cargo.toml index 1fc0ac21f61..706ca02e9b6 100644 --- a/components/util/Cargo.toml +++ b/components/util/Cargo.toml @@ -24,6 +24,9 @@ git = "https://github.com/servo/rust-cssparser" [dependencies.selectors] git = "https://github.com/servo/rust-selectors" +[dependencies.azure] +git = "https://github.com/servo/rust-azure" + [dependencies.geom] git = "https://github.com/servo/rust-geom" diff --git a/components/util/lib.rs b/components/util/lib.rs index 62068621467..c9b1c5bb76a 100644 --- a/components/util/lib.rs +++ b/components/util/lib.rs @@ -24,6 +24,7 @@ #[macro_use] extern crate log; +extern crate azure; extern crate alloc; #[macro_use] extern crate bitflags; extern crate cssparser; diff --git a/tests/html/test_canvas_drawimage.html b/tests/html/test_canvas_drawimage.html new file mode 100644 index 00000000000..54a7082f9f3 --- /dev/null +++ b/tests/html/test_canvas_drawimage.html @@ -0,0 +1,263 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style type=''> +html { + font-family: helvetica, sans-serif; +} + +canvas { + padding: 15px; + margin: 10px; +} + +.example { + display: inline-block; + width: 280px; + margin-top: 50px; + margin-right: 50px; +} + +.title { + text-align: center; +} + +.description { + width: 100%; +} + +.description div { + display: inline-block; + text-align: center; + font-size: 13px; +} + +.description .source { + width: 100px; +} + +.description .target { + width: 130px; +} + +.example-title { + text-align: center; + font-size: 16px; +} + +.error { + color: red; +} + +</style> +<body> + <h1 class="title">DrawImage canvas to canvas</h1> +</body> + +<script type="text/javascript"> + +var smoothingEnabled = false; +var examplesNum = 0; + +var imageSource = { + width: 50, + height: 50 +}; + +var destCanvas = { + width: 100, + height: 100 +}; + +// 2 arguments, the dest origin is 0,0 +// The source canvas will copied to the 0,0 position of the destination canvas +drawImage(0, 0); +// 2 arguments, the dest origin is not 0,0 +// The source canvas will copied to the 25, 25 position of the destination canvas +drawImage(25, 25); +// 4 arguments, the source origin is not 0,0, the dest size is provided +// The source canvas will copied to the 50, 50 position of the destination canvas and +// on an area of 50x50 pixels +drawImage(50, 50, 50, 50); +// 4 arguments, the dest origin is not 0,0 and the dest size is provided but +// does not match the size of the source. The image will be distorted +// The source canvas will copied to the 50,50 position of the destination canvas +// and it will be shrunk to a and area of 25x25 +drawImage(50, 50, 25, 25); +// The source canvas will copied to the 50,50 position of the destination canvas +// over an area of 50x25 pixels +// The copied image will be distorted along the x axis +drawImage(50, 50, 50, 25); +// 8 arguments, both destination and source origins are 0, 0 +// An area of 25x25 pixels of the source image will be copied to +// an area of 25x25 pixels of the destination canvas +drawImage(0, 0, 25, 25, 0, 0, 25, 25); +// 8 arguments the destination origin is not 0,0 +// An area of 25x25 pixels of the source image will be copied to +// an area of 25x25 pixels of the destination canvas in the position 25,25 +drawImage(0, 0, 25, 25, 25, 25, 25, 25); +// The source rectangle overflows the source image +// The source area is clipped to fit the source image +// and the destination are is clipped in the same proportion +drawImage(25, 25, 50, 50, 0, 0, 50, 50); +// The destination rectangle has negative width and height +// An exception is raised and nothing is drawn +drawImage(25, 25, 50, 50, 0, 0, -100, -100); +// The destination rectangle is larger thant the destination canvas +// When the destination rectangle is outside the destination image (the scratch bitmap), the pixels +// that land outside the scratch bitmap are discarded, as if the destination was an infinite canvas +// whose rendering was clipped to the dimensions of the scratch bitmap. +drawImage(0, 0, 50, 50, 0, 0, 200, 200); +// The source rectangle is larger than the source canvas +// The source area is clipped to fit the source image +// and the destination are is clipped in the same proportion +drawImage(0, 0, 100, 100, 0, 0, 50, 50); +// Negative coorditanes of the source rectangle +// The source area is clipped to fit the source image +// and the destination are is clipped in the same proportion +drawImage(-25, -25, 50, 50, 0, 0, 50, 50); + +// Example with non squared origin and source canvases +imageSource = { + width: 100, + height: 50 +}; + +destCanvas = { + width: 100, + height: 50 +}; + +drawImage(0, 0); + +function renderExample(title) { + var container = document.createElement('div'); + container.id = 'example' + examplesNum++; + container.setAttribute('class', 'example'); + + var h2 = document.createElement('h2'); + h2.textContent = title; + h2.setAttribute('class', 'example-title'); + container.appendChild(h2); + + var div1 = document.createElement('div'); + var canvas1 = document.createElement('canvas'); + var canvas2 = document.createElement('canvas'); + div1.appendChild(canvas1); + div1.appendChild(canvas2); + container.appendChild(div1); + + var div2 = document.createElement('div'); + div2.setAttribute('class', 'description'); + var source = document.createElement('div'); + source.textContent = ' Source (' + imageSource.width + ',' + imageSource.height + ')'; + source.setAttribute('class', 'source'); + + var arrow = document.createElement('div'); + arrow.textContent = ' -> '; + arrow.setAttribute('class', 'arrow'); + + var target = document.createElement('div'); + target.textContent = 'Target (' + destCanvas.width + ',' + destCanvas.height + ')'; + target.setAttribute('class', 'target'); + + div2.appendChild(source); + div2.appendChild(arrow); + div2.appendChild(target); + container.appendChild(div2); + + return container; +} + +function drawImage() { + var args = Array.prototype.slice.call(arguments); + + var div = renderExample('drawImage(' + args.toString() + ')'); + var canvasEls = div.querySelectorAll('canvas'); + var canvas1 = canvasEls[0]; + var canvas2 = canvasEls[1]; + + canvas1.width = imageSource.width; + canvas1.height = imageSource.height; + + var ctx1 = canvas1.getContext('2d'); + ctx1.fillStyle = "#00FFFF"; + ctx1.fillRect(0, 0, imageSource.width, imageSource.height); + + ctx1.fillStyle = "#000000"; + ctx1.fillRect(5,5,40,40); + ctx1.clearRect(10,10,30,30); + ctx1.strokeRect(15,15,20,20); + + canvas2.width = destCanvas.width; + canvas2.height = destCanvas.height; + + var ctx2 = canvas2.getContext('2d'); + ctx2.fillStyle = "#FF0000"; + ctx2.fillRect(0, 0, destCanvas.width, destCanvas.height); + ctx2.imageSmoothingEnabled = smoothingEnabled; + + args.unshift(canvas1); + try { + ctx2.drawImage.apply(ctx2, args); + } + catch(err) { + var title = div.querySelector('.example-title'); + var error = document.createElement('h2'); + error.setAttribute('class', 'example-title error'); + div.insertBefore(error, title); + error.textContent += "Call Failed: " + err.message; + } + + document.body.appendChild(div); +}; + + +function drawImage() { + var args = Array.prototype.slice.call(arguments); + + var div = renderExample('drawImage(' + args.toString() + ')'); + var canvasEls = div.querySelectorAll('canvas'); + var canvas1 = canvasEls[0]; + var canvas2 = canvasEls[1]; + + canvas1.width = imageSource.width; + canvas1.height = imageSource.height; + + var ctx1 = canvas1.getContext('2d'); + ctx1.fillStyle = "#00FFFF"; + ctx1.fillRect(0, 0, imageSource.width, imageSource.height); + + ctx1.fillStyle = "#000000"; + ctx1.fillRect(5,5,40,40); + ctx1.clearRect(10,10,30,30); + ctx1.strokeRect(15,15,20,20); + + canvas2.width = destCanvas.width; + canvas2.height = destCanvas.height; + + var ctx2 = canvas2.getContext('2d'); + ctx2.fillStyle = "#FF0000"; + ctx2.fillRect(0, 0, destCanvas.width, destCanvas.height); + ctx2.imageSmoothingEnabled = smoothingEnabled; + + args.unshift(canvas1); + try { + ctx2.drawImage.apply(ctx2, args); + } + catch(err) { + var title = div.querySelector('.example-title'); + var error = document.createElement('h2'); + error.setAttribute('class', 'example-title error'); + div.insertBefore(error, title); + error.textContent += "Call Failed: " + err.message; + } + + document.body.appendChild(div); +}; + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_1.html b/tests/ref/2dcontext/drawimage_1.html new file mode 100644 index 00000000000..4c3ab02b123 --- /dev/null +++ b/tests/ref/2dcontext/drawimage_1.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script> + +var sourceWidth = 50; +var sourceHeight = 50; +var smoothingEnabled = false; +var destCanvas = document.getElementById('dest'); +var sourceCanvas = document.createElement('canvas'); +sourceCanvas.width = sourceWidth; +sourceCanvas.height = sourceHeight; + +var sourceCtx = sourceCanvas.getContext('2d'); +sourceCtx.fillStyle = "#00FFFF"; +sourceCtx.fillRect(0, 0, sourceWidth, sourceHeight); +sourceCtx.fillStyle = "#000000"; +sourceCtx.fillRect(5,5,40,40); + +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.imageSmoothingEnabled = smoothingEnabled; +// 2 arguments, the dest origin is 0,0 +// The source canvas will copied to the 0,0 position of the destination canvas +destCtx.drawImage(sourceCanvas, 0, 0); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_10.html b/tests/ref/2dcontext/drawimage_10.html new file mode 100644 index 00000000000..0430a54d1c0 --- /dev/null +++ b/tests/ref/2dcontext/drawimage_10.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script> + +var sourceWidth = 50; +var sourceHeight = 50; +var smoothingEnabled = false; +var destCanvas = document.getElementById('dest'); +var sourceCanvas = document.createElement('canvas'); +sourceCanvas.width = sourceWidth; +sourceCanvas.height = sourceHeight; + +var sourceCtx = sourceCanvas.getContext('2d'); +sourceCtx.fillStyle = "#00FFFF"; +sourceCtx.fillRect(0, 0, sourceWidth, sourceHeight); +sourceCtx.fillStyle = "#000000"; +sourceCtx.fillRect(5,5,40,40); + +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.imageSmoothingEnabled = smoothingEnabled; + +// The destination rectangle is larger thant the destination canvas +// When the destination rectangle is outside the destination image (the scratch bitmap), the pixels +// that land outside the scratch bitmap are discarded, as if the destination was an infinite canvas +// whose rendering was clipped to the dimensions of the scratch bitmap. +destCtx.drawImage(sourceCanvas, 0, 0, 50, 50, 0, 0, 200, 200); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_10_ref.html b/tests/ref/2dcontext/drawimage_10_ref.html new file mode 100644 index 00000000000..cd05233b8f7 --- /dev/null +++ b/tests/ref/2dcontext/drawimage_10_ref.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script type="text/javascript"> + +var destCanvas = document.getElementById('dest'); +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.fillStyle = "#00FFFF"; +destCtx.fillRect(0, 0, 100, 100); +destCtx.fillStyle = "#000000"; +destCtx.fillRect(20, 20, 80, 80); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_11.html b/tests/ref/2dcontext/drawimage_11.html new file mode 100644 index 00000000000..b0f148527be --- /dev/null +++ b/tests/ref/2dcontext/drawimage_11.html @@ -0,0 +1,41 @@ + <!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script> + +var sourceWidth = 50; +var sourceHeight = 50; +var smoothingEnabled = false; +var destCanvas = document.getElementById('dest'); +var sourceCanvas = document.createElement('canvas'); +sourceCanvas.width = sourceWidth; +sourceCanvas.height = sourceHeight; + +var sourceCtx = sourceCanvas.getContext('2d'); +sourceCtx.fillStyle = "#00FFFF"; +sourceCtx.fillRect(0, 0, sourceWidth, sourceHeight); +sourceCtx.fillStyle = "#000000"; +sourceCtx.fillRect(5,5,40,40); + +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.imageSmoothingEnabled = smoothingEnabled; + +// The source rectangle is larger than the source canvas +// The source area is clipped to fit the source image +// and the destination are is clipped in the same proportion +destCtx.drawImage(sourceCanvas, 0, 0, 100, 100, 0, 0, 50, 50); + +</script> +</body> +</html> diff --git a/tests/ref/2dcontext/drawimage_11_ref.html b/tests/ref/2dcontext/drawimage_11_ref.html new file mode 100644 index 00000000000..970f626dfbd --- /dev/null +++ b/tests/ref/2dcontext/drawimage_11_ref.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script type="text/javascript"> + +var destCanvas = document.getElementById('dest'); +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.fillStyle = "#00FFFF"; +destCtx.fillRect(0, 0, 25, 25); +destCtx.fillStyle = "#000000"; +destCtx.fillRect(2, 2, 20, 20); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_12.html b/tests/ref/2dcontext/drawimage_12.html new file mode 100644 index 00000000000..f667f9fa093 --- /dev/null +++ b/tests/ref/2dcontext/drawimage_12.html @@ -0,0 +1,41 @@ + <!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script> + +var sourceWidth = 50; +var sourceHeight = 50; +var smoothingEnabled = false; +var destCanvas = document.getElementById('dest'); +var sourceCanvas = document.createElement('canvas'); +sourceCanvas.width = sourceWidth; +sourceCanvas.height = sourceHeight; + +var sourceCtx = sourceCanvas.getContext('2d'); +sourceCtx.fillStyle = "#00FFFF"; +sourceCtx.fillRect(0, 0, sourceWidth, sourceHeight); +sourceCtx.fillStyle = "#000000"; +sourceCtx.fillRect(5,5,40,40); + +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.imageSmoothingEnabled = smoothingEnabled; + +// Negative coorditanes of the source rectangle +// The source area is clipped to fit the source image +// and the destination are is clipped in the same proportion +destCtx.drawImage(sourceCanvas, -25, -25, 50, 50, 0, 0, 50, 50); + +</script> +</body> +</html> diff --git a/tests/ref/2dcontext/drawimage_12_ref.html b/tests/ref/2dcontext/drawimage_12_ref.html new file mode 100644 index 00000000000..190f74f93ef --- /dev/null +++ b/tests/ref/2dcontext/drawimage_12_ref.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script type="text/javascript"> + +var destCanvas = document.getElementById('dest'); +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.fillStyle = "#00FFFF"; +destCtx.fillRect(0, 0, 25, 25); +destCtx.fillStyle = "#000000"; +destCtx.fillRect(5, 5, 20, 20); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_1_ref.html b/tests/ref/2dcontext/drawimage_1_ref.html new file mode 100644 index 00000000000..d0bac45ed5b --- /dev/null +++ b/tests/ref/2dcontext/drawimage_1_ref.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } + canvas { + display: block; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script type="text/javascript"> + +var sourceWidth = 50; +var sourceHeight = 50; +var destCanvas = document.getElementById('dest'); +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.fillStyle = "#00FFFF"; +destCtx.fillRect(0, 0, sourceWidth, sourceHeight); +destCtx.fillStyle = "#000000"; +destCtx.fillRect(5, 5, 40, 40); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_2.html b/tests/ref/2dcontext/drawimage_2.html new file mode 100644 index 00000000000..3cca00648c8 --- /dev/null +++ b/tests/ref/2dcontext/drawimage_2.html @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script> + +var sourceWidth = 50; +var sourceHeight = 50; +var smoothingEnabled = false; +var destCanvas = document.getElementById('dest'); +var sourceCanvas = document.createElement('canvas'); +sourceCanvas.width = sourceWidth; +sourceCanvas.height = sourceHeight; + +var sourceCtx = sourceCanvas.getContext('2d'); +sourceCtx.fillStyle = "#00FFFF"; +sourceCtx.fillRect(0, 0, sourceWidth, sourceHeight); +sourceCtx.fillStyle = "#000000"; +sourceCtx.fillRect(5,5,40,40); + +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.imageSmoothingEnabled = smoothingEnabled; + +// 2 arguments, the dest origin is not 0,0 +// The source canvas will copied to the 25, 25 position of the destination canvas +destCtx.drawImage(sourceCanvas, 25, 25); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_2_ref.html b/tests/ref/2dcontext/drawimage_2_ref.html new file mode 100644 index 00000000000..72ec289f714 --- /dev/null +++ b/tests/ref/2dcontext/drawimage_2_ref.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } + canvas { + display: block; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script type="text/javascript"> + +var sourceWidth = 50; +var sourceHeight = 50; +var destCanvas = document.getElementById('dest'); +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.fillStyle = "#00FFFF"; +destCtx.fillRect(25, 25, sourceWidth, sourceHeight); +destCtx.fillStyle = "#000000"; +destCtx.fillRect(30, 30, 40, 40); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_3.html b/tests/ref/2dcontext/drawimage_3.html new file mode 100644 index 00000000000..392723bd9f7 --- /dev/null +++ b/tests/ref/2dcontext/drawimage_3.html @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script> + +var sourceWidth = 50; +var sourceHeight = 50; +var smoothingEnabled = false; +var destCanvas = document.getElementById('dest'); +var sourceCanvas = document.createElement('canvas'); +sourceCanvas.width = sourceWidth; +sourceCanvas.height = sourceHeight; + +var sourceCtx = sourceCanvas.getContext('2d'); +sourceCtx.fillStyle = "#00FFFF"; +sourceCtx.fillRect(0, 0, sourceWidth, sourceHeight); +sourceCtx.fillStyle = "#000000"; +sourceCtx.fillRect(5,5,40,40); + +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.imageSmoothingEnabled = smoothingEnabled; + +// 4 arguments, the source origin is not 0,0, the dest size is provided +// The source canvas will copied to the 50, 50 position of the destination canvas and +// on an area of 50x50 pixels +destCtx.drawImage(sourceCanvas, 50, 50, 50, 50); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_3_ref.html b/tests/ref/2dcontext/drawimage_3_ref.html new file mode 100644 index 00000000000..3e153f1ca65 --- /dev/null +++ b/tests/ref/2dcontext/drawimage_3_ref.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } + canvas { + display: block; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script type="text/javascript"> + +var sourceWidth = 50; +var sourceHeight = 50; +var destCanvas = document.getElementById('dest'); +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.fillStyle = "#00FFFF"; +destCtx.fillRect(50, 50, sourceWidth, sourceHeight); +destCtx.fillStyle = "#000000"; +destCtx.fillRect(55, 55, 40, 40); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_4.html b/tests/ref/2dcontext/drawimage_4.html new file mode 100644 index 00000000000..a46986a68f0 --- /dev/null +++ b/tests/ref/2dcontext/drawimage_4.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script> + +var sourceWidth = 50; +var sourceHeight = 50; +var smoothingEnabled = false; +var destCanvas = document.getElementById('dest'); +var sourceCanvas = document.createElement('canvas'); +sourceCanvas.width = sourceWidth; +sourceCanvas.height = sourceHeight; + +var sourceCtx = sourceCanvas.getContext('2d'); +sourceCtx.fillStyle = "#00FFFF"; +sourceCtx.fillRect(0, 0, sourceWidth, sourceHeight); +sourceCtx.fillStyle = "#000000"; +sourceCtx.fillRect(5,5,40,40); + +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.imageSmoothingEnabled = smoothingEnabled; + +// 4 arguments, the dest origin is not 0,0 and the dest size is provided but +// does not match the size of the source. The image will be distorted +// The source canvas will copied to the 50,50 position of the destination canvas +// and it will be shrunk to a and area of 20x20 +destCtx.drawImage(sourceCanvas, 50, 50, 20, 20); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_4_ref.html b/tests/ref/2dcontext/drawimage_4_ref.html new file mode 100644 index 00000000000..9a8cc99371c --- /dev/null +++ b/tests/ref/2dcontext/drawimage_4_ref.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script type="text/javascript"> + +var destCanvas = document.getElementById('dest'); +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.fillStyle = "#00FFFF"; +destCtx.fillRect(50, 50, 20, 20); +destCtx.fillStyle = "#000000"; +destCtx.fillRect(52, 52, 16, 16); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_5.html b/tests/ref/2dcontext/drawimage_5.html new file mode 100644 index 00000000000..3052d66ece8 --- /dev/null +++ b/tests/ref/2dcontext/drawimage_5.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script> + +var sourceWidth = 50; +var sourceHeight = 50; +var smoothingEnabled = false; +var destCanvas = document.getElementById('dest'); +var sourceCanvas = document.createElement('canvas'); +sourceCanvas.width = sourceWidth; +sourceCanvas.height = sourceHeight; + +var sourceCtx = sourceCanvas.getContext('2d'); +sourceCtx.fillStyle = "#00FFFF"; +sourceCtx.fillRect(0, 0, sourceWidth, sourceHeight); +sourceCtx.fillStyle = "#000000"; +sourceCtx.fillRect(5,5,40,40); + +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.imageSmoothingEnabled = smoothingEnabled; + +// The source canvas will copied to the 50,50 position of the destination canvas +// over an area of 50x25 pixels +// The copied image will be distorted along the x axis + +destCtx.drawImage(sourceCanvas, 50, 50, 50, 20); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_5_ref.html b/tests/ref/2dcontext/drawimage_5_ref.html new file mode 100644 index 00000000000..47dd63ee2b3 --- /dev/null +++ b/tests/ref/2dcontext/drawimage_5_ref.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script type="text/javascript"> + +var destCanvas = document.getElementById('dest'); +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.fillStyle = "#00FFFF"; +destCtx.fillRect(50, 50, 50, 20); +destCtx.fillStyle = "#000000"; +destCtx.fillRect(55, 52, 40, 16); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_6.html b/tests/ref/2dcontext/drawimage_6.html new file mode 100644 index 00000000000..e94efaadfa1 --- /dev/null +++ b/tests/ref/2dcontext/drawimage_6.html @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script> + +var sourceWidth = 50; +var sourceHeight = 50; +var smoothingEnabled = false; +var destCanvas = document.getElementById('dest'); +var sourceCanvas = document.createElement('canvas'); +sourceCanvas.width = sourceWidth; +sourceCanvas.height = sourceHeight; + +var sourceCtx = sourceCanvas.getContext('2d'); +sourceCtx.fillStyle = "#00FFFF"; +sourceCtx.fillRect(0, 0, sourceWidth, sourceHeight); +sourceCtx.fillStyle = "#000000"; +sourceCtx.fillRect(5,5,40,40); + +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.imageSmoothingEnabled = smoothingEnabled; + +// 8 arguments, both destination and source origins are 0, 0 +// An area of 25x25 pixels of the source image will be copied to +// an area of 25x25 pixels of the destination canvas +destCtx.drawImage(sourceCanvas, 0, 0, 25, 25, 0, 0, 25, 25); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_6_ref.html b/tests/ref/2dcontext/drawimage_6_ref.html new file mode 100644 index 00000000000..190f74f93ef --- /dev/null +++ b/tests/ref/2dcontext/drawimage_6_ref.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script type="text/javascript"> + +var destCanvas = document.getElementById('dest'); +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.fillStyle = "#00FFFF"; +destCtx.fillRect(0, 0, 25, 25); +destCtx.fillStyle = "#000000"; +destCtx.fillRect(5, 5, 20, 20); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_7.html b/tests/ref/2dcontext/drawimage_7.html new file mode 100644 index 00000000000..9ace085d979 --- /dev/null +++ b/tests/ref/2dcontext/drawimage_7.html @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script> + +var sourceWidth = 50; +var sourceHeight = 50; +var smoothingEnabled = false; +var destCanvas = document.getElementById('dest'); +var sourceCanvas = document.createElement('canvas'); +sourceCanvas.width = sourceWidth; +sourceCanvas.height = sourceHeight; + +var sourceCtx = sourceCanvas.getContext('2d'); +sourceCtx.fillStyle = "#00FFFF"; +sourceCtx.fillRect(0, 0, sourceWidth, sourceHeight); +sourceCtx.fillStyle = "#000000"; +sourceCtx.fillRect(5,5,40,40); + +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.imageSmoothingEnabled = smoothingEnabled; + +// 8 arguments the destination origin is not 0,0 +// An area of 25x25 pixels of the source image will be copied to +// an area of 25x25 pixels of the destination canvas in the position 25,25 +destCtx.drawImage(sourceCanvas, 0, 0, 25, 25, 25, 25, 25, 25); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_7_ref.html b/tests/ref/2dcontext/drawimage_7_ref.html new file mode 100644 index 00000000000..51b2b276cad --- /dev/null +++ b/tests/ref/2dcontext/drawimage_7_ref.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script type="text/javascript"> + +var destCanvas = document.getElementById('dest'); +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.fillStyle = "#00FFFF"; +destCtx.fillRect(25, 25, 25, 25); +destCtx.fillStyle = "#000000"; +destCtx.fillRect(30, 30, 20, 20); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_8.html b/tests/ref/2dcontext/drawimage_8.html new file mode 100644 index 00000000000..d1c1f5bced6 --- /dev/null +++ b/tests/ref/2dcontext/drawimage_8.html @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script> + +var sourceWidth = 50; +var sourceHeight = 50; +var smoothingEnabled = false; +var destCanvas = document.getElementById('dest'); +var sourceCanvas = document.createElement('canvas'); +sourceCanvas.width = sourceWidth; +sourceCanvas.height = sourceHeight; + +var sourceCtx = sourceCanvas.getContext('2d'); +sourceCtx.fillStyle = "#00FFFF"; +sourceCtx.fillRect(0, 0, sourceWidth, sourceHeight); +sourceCtx.fillStyle = "#000000"; +sourceCtx.fillRect(5,5,40,40); + +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.imageSmoothingEnabled = smoothingEnabled; + +// The source rectangle overflows the source image +// The source area is clipped to fit the source image +// and the destination are is clipped in the same proportion +destCtx.drawImage(sourceCanvas, 25, 25, 50, 50, 0, 0, 50, 50); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_8_ref.html b/tests/ref/2dcontext/drawimage_8_ref.html new file mode 100644 index 00000000000..652bf6eb994 --- /dev/null +++ b/tests/ref/2dcontext/drawimage_8_ref.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script type="text/javascript"> + +var destCanvas = document.getElementById('dest'); +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.fillStyle = "#00FFFF"; +destCtx.fillRect(0, 0, 25, 25); +destCtx.fillStyle = "#000000"; +destCtx.fillRect(0, 0, 20, 20); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/2dcontext/drawimage_9.html b/tests/ref/2dcontext/drawimage_9.html new file mode 100644 index 00000000000..510f9c923c2 --- /dev/null +++ b/tests/ref/2dcontext/drawimage_9.html @@ -0,0 +1,48 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script> + +var sourceWidth = 50; +var sourceHeight = 50; +var smoothingEnabled = false; +var destCanvas = document.getElementById('dest'); +var sourceCanvas = document.createElement('canvas'); +sourceCanvas.width = sourceWidth; +sourceCanvas.height = sourceHeight; + +var sourceCtx = sourceCanvas.getContext('2d'); +sourceCtx.fillStyle = "#00FFFF"; +sourceCtx.fillRect(0, 0, sourceWidth, sourceHeight); +sourceCtx.fillStyle = "#000000"; +sourceCtx.fillRect(5,5,40,40); + +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +destCtx.imageSmoothingEnabled = smoothingEnabled; + +// The destination rectangle has negative width and height +// An exception is raised and nothing is drawn +try { + destCtx.drawImage(sourceCanvas, 25, 50, 50, 0, 0, -100, -100); + // It makes the test fail if the exception is not thrown + destCtx.fillStyle = "#0000FF"; + destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); +} +catch(err) { + console.err("Exception Thrown"); +} + +</script> +</body> +</html> diff --git a/tests/ref/2dcontext/drawimage_9_ref.html b/tests/ref/2dcontext/drawimage_9_ref.html new file mode 100644 index 00000000000..b9be7e514f1 --- /dev/null +++ b/tests/ref/2dcontext/drawimage_9_ref.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> +</head> +<style> + html, body { + margin: 0; + } +</style> +<body> +<canvas id="dest" height="100" width="100"></canvas> +<script type="text/javascript"> + +var destCanvas = document.getElementById('dest'); +var destCtx = destCanvas.getContext('2d'); +destCtx.fillStyle = "#FF0000"; +destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height); + +</script> +</body> +</html>
\ No newline at end of file diff --git a/tests/ref/canvas_lineto_a.html b/tests/ref/2dcontext/lineto_a.html index aa54ae333bf..aa54ae333bf 100644 --- a/tests/ref/canvas_lineto_a.html +++ b/tests/ref/2dcontext/lineto_a.html diff --git a/tests/ref/canvas_lineto_ref.html b/tests/ref/2dcontext/lineto_ref.html index e6dd3333e32..e6dd3333e32 100644 --- a/tests/ref/canvas_lineto_ref.html +++ b/tests/ref/2dcontext/lineto_ref.html diff --git a/tests/ref/canvas_transform_a.html b/tests/ref/2dcontext/transform_a.html index cc958361124..cc958361124 100644 --- a/tests/ref/canvas_transform_a.html +++ b/tests/ref/2dcontext/transform_a.html diff --git a/tests/ref/canvas_transform_ref.html b/tests/ref/2dcontext/transform_ref.html index 2c0898134f4..2c0898134f4 100644 --- a/tests/ref/canvas_transform_ref.html +++ b/tests/ref/2dcontext/transform_ref.html diff --git a/tests/ref/basic.list b/tests/ref/basic.list index d4f0bde917a..3d322ac5d8c 100644 --- a/tests/ref/basic.list +++ b/tests/ref/basic.list @@ -9,6 +9,21 @@ # Should be == with expected failure: fragment=top != ../html/acid2.html acid2_ref.html +== 2dcontext/drawimage_1.html 2dcontext/drawimage_1_ref.html +== 2dcontext/drawimage_10.html 2dcontext/drawimage_10_ref.html +== 2dcontext/drawimage_11.html 2dcontext/drawimage_11_ref.html +== 2dcontext/drawimage_12.html 2dcontext/drawimage_12_ref.html +== 2dcontext/drawimage_2.html 2dcontext/drawimage_2_ref.html +== 2dcontext/drawimage_3.html 2dcontext/drawimage_3_ref.html +== 2dcontext/drawimage_4.html 2dcontext/drawimage_4_ref.html +== 2dcontext/drawimage_5.html 2dcontext/drawimage_5_ref.html +== 2dcontext/drawimage_6.html 2dcontext/drawimage_6_ref.html +== 2dcontext/drawimage_7.html 2dcontext/drawimage_7_ref.html +== 2dcontext/drawimage_8.html 2dcontext/drawimage_8_ref.html +== 2dcontext/drawimage_9.html 2dcontext/drawimage_9_ref.html +== 2dcontext/lineto_a.html 2dcontext/lineto_ref.html +== 2dcontext/transform_a.html 2dcontext/transform_ref.html + == abs_float_pref_width_a.html abs_float_pref_width_ref.html == acid1_a.html acid1_b.html == acid2_noscroll.html acid2_ref_broken.html @@ -65,10 +80,6 @@ flaky_cpu == append_style_a.html append_style_b.html == box_sizing_sanity_check_a.html box_sizing_sanity_check_ref.html == br.html br-ref.html == canvas_as_block_element_a.html canvas_as_block_element_ref.html -== canvas_linear_gradient_a.html canvas_linear_gradient_ref.html -== canvas_lineto_a.html canvas_lineto_ref.html -== canvas_radial_gradient_a.html canvas_radial_gradient_ref.html -== canvas_transform_a.html canvas_transform_ref.html == case-insensitive-font-family.html case-insensitive-font-family-ref.html == clear_generated_content_table_a.html clear_generated_content_table_ref.html == clip_a.html clip_ref.html diff --git a/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.canvas.html.ini b/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.canvas.html.ini deleted file mode 100644 index 50084ff0b01..00000000000 --- a/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.canvas.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.drawImage.canvas.html] - type: testharness - [Canvas test: 2d.drawImage.canvas] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.null.html.ini b/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.null.html.ini new file mode 100644 index 00000000000..82a420e5a71 --- /dev/null +++ b/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.null.html.ini @@ -0,0 +1,5 @@ +[2d.drawImage.null.html] + type: testharness + [Canvas test: 2d.drawImage.null] + expected: FAIL + diff --git a/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.1.html.ini b/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.1.html.ini deleted file mode 100644 index f1466e20fe5..00000000000 --- a/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.1.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.drawImage.self.1.html] - type: testharness - [Canvas test: 2d.drawImage.self.1] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.2.html.ini b/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.2.html.ini deleted file mode 100644 index a7e3656486d..00000000000 --- a/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.2.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.drawImage.self.2.html] - type: testharness - [Canvas test: 2d.drawImage.self.2] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.wrongtype.html.ini b/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.wrongtype.html.ini new file mode 100644 index 00000000000..703d0a05082 --- /dev/null +++ b/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.wrongtype.html.ini @@ -0,0 +1,5 @@ +[2d.drawImage.wrongtype.html] + type: testharness + [Incorrect image types in drawImage do not match any defined overloads, so WebIDL throws a TypeError] + expected: FAIL + diff --git a/tests/wpt/metadata/2dcontext/image-smoothing/imagesmoothing.html.ini b/tests/wpt/metadata/2dcontext/image-smoothing/imagesmoothing.html.ini deleted file mode 100644 index 0aa58081d2f..00000000000 --- a/tests/wpt/metadata/2dcontext/image-smoothing/imagesmoothing.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[imagesmoothing.html] - type: testharness - [When the CanvasRenderingContext2D object is created, the attribute must be set to true.] - expected: FAIL - diff --git a/tests/wpt/metadata/html/dom/interfaces.html.ini b/tests/wpt/metadata/html/dom/interfaces.html.ini index a269b210e2f..6036b185dce 100644 --- a/tests/wpt/metadata/html/dom/interfaces.html.ini +++ b/tests/wpt/metadata/html/dom/interfaces.html.ini @@ -6975,9 +6975,6 @@ [CanvasRenderingContext2D interface: attribute globalCompositeOperation] expected: FAIL - [CanvasRenderingContext2D interface: attribute imageSmoothingEnabled] - expected: FAIL - [CanvasRenderingContext2D interface: operation createPattern(CanvasImageSource,DOMString)] expected: FAIL @@ -7056,9 +7053,6 @@ [CanvasRenderingContext2D interface: operation drawImage(CanvasImageSource,unrestricted double,unrestricted double,unrestricted double,unrestricted double)] expected: FAIL - [CanvasRenderingContext2D interface: operation drawImage(CanvasImageSource,unrestricted double,unrestricted double,unrestricted double,unrestricted double,unrestricted double,unrestricted double,unrestricted double,unrestricted double)] - expected: FAIL - [CanvasRenderingContext2D interface: operation addHitRegion(HitRegionOptions)] expected: FAIL @@ -7152,9 +7146,6 @@ [CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "globalCompositeOperation" with the proper type (14)] expected: FAIL - [CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "imageSmoothingEnabled" with the proper type (15)] - expected: FAIL - [CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "strokeStyle" with the proper type (16)] expected: FAIL @@ -7281,21 +7272,9 @@ [CanvasRenderingContext2D interface: calling measureText(DOMString) on document.createElement("canvas").getContext("2d") with too few arguments must throw TypeError] expected: FAIL - [CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "drawImage" with the proper type (49)] - expected: FAIL - - [CanvasRenderingContext2D interface: calling drawImage(CanvasImageSource,unrestricted double,unrestricted double) on document.createElement("canvas").getContext("2d") with too few arguments must throw TypeError] - expected: FAIL - - [CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "drawImage" with the proper type (50)] - expected: FAIL - [CanvasRenderingContext2D interface: calling drawImage(CanvasImageSource,unrestricted double,unrestricted double,unrestricted double,unrestricted double) on document.createElement("canvas").getContext("2d") with too few arguments must throw TypeError] expected: FAIL - [CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "drawImage" with the proper type (51)] - expected: FAIL - [CanvasRenderingContext2D interface: calling drawImage(CanvasImageSource,unrestricted double,unrestricted double,unrestricted double,unrestricted double,unrestricted double,unrestricted double,unrestricted double,unrestricted double) on document.createElement("canvas").getContext("2d") with too few arguments must throw TypeError] expected: FAIL |