diff options
author | Tetsuharu OHZEKI <saneyuki.snyk@gmail.com> | 2015-03-25 03:07:34 +0900 |
---|---|---|
committer | Tetsuharu OHZEKI <saneyuki.snyk@gmail.com> | 2015-03-25 15:13:34 +0900 |
commit | bc06526610d901a6a80c3146353c82d13c54f2b4 (patch) | |
tree | e4b8a63c48323035e754b2e45bbfda448f77b16c /components/script/dom/canvasrenderingcontext2d.rs | |
parent | 05c6d046ddbfbbe626a69bed32cf681569e86eb7 (diff) | |
download | servo-bc06526610d901a6a80c3146353c82d13c54f2b4.tar.gz servo-bc06526610d901a6a80c3146353c82d13c54f2b4.zip |
Add guards to almost CanvasRenderingContext2D methods according to the spec.
http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas_CR/ says
"Except where otherwise specified, for the 2D context interface,
any method call with a numeric argument whose value is infinite or a
NaN value must be ignored."
We might define the annotation to generate this behavior in glue code.
However, at now, I use this workaround way.
Diffstat (limited to 'components/script/dom/canvasrenderingcontext2d.rs')
-rw-r--r-- | components/script/dom/canvasrenderingcontext2d.rs | 90 |
1 files changed, 89 insertions, 1 deletions
diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 621bb629df0..37108922fc5 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasWin 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::Error::{IndexSize, NotSupported, TypeError}; use dom::bindings::error::Fallible; use dom::bindings::global::{GlobalRef, GlobalField}; use dom::bindings::js::{JS, JSRef, LayoutJS, Temporary}; @@ -207,22 +207,44 @@ impl LayoutCanvasRenderingContext2DHelpers for LayoutJS<CanvasRenderingContext2D } } +// We add a guard to each of methods by the spec: +// http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas_CR/ +// +// > Except where otherwise specified, for the 2D context interface, +// > any method call with a numeric argument whose value is infinite or a NaN value must be ignored. +// +// Restricted values are guarded in glue code. Therefore we need not add a guard. +// +// FIXME: this behavior should might be generated by some annotattions to idl. impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> { fn Canvas(self) -> Temporary<HTMLCanvasElement> { Temporary::new(self.canvas) } fn Scale(self, x: f64, y: f64) { + if !(x.is_finite() && y.is_finite()) { + return; + } + self.transform.set(self.transform.get().scale(x as f32, y as f32)); self.update_transform() } fn Translate(self, x: f64, y: f64) { + if !(x.is_finite() && y.is_finite()) { + return; + } + self.transform.set(self.transform.get().translate(x as f32, y as f32)); self.update_transform() } fn Transform(self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) { + if !(a.is_finite() && b.is_finite() && c.is_finite() && + d.is_finite() && e.is_finite() && f.is_finite()) { + return; + } + self.transform.set(self.transform.get().mul(&Matrix2D::new(a as f32, b as f32, c as f32, @@ -233,6 +255,11 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> } fn SetTransform(self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) { + if !(a.is_finite() && b.is_finite() && c.is_finite() && + d.is_finite() && e.is_finite() && f.is_finite()) { + return; + } + self.transform.set(Matrix2D::new(a as f32, b as f32, c as f32, @@ -243,16 +270,31 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> } fn FillRect(self, x: f64, y: f64, width: f64, height: f64) { + if !(x.is_finite() && y.is_finite() && + width.is_finite() && height.is_finite()) { + return; + } + let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32)); self.renderer.send(CanvasMsg::FillRect(rect)).unwrap(); } fn ClearRect(self, x: f64, y: f64, width: f64, height: f64) { + if !(x.is_finite() && y.is_finite() && + width.is_finite() && height.is_finite()) { + return; + } + let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32)); self.renderer.send(CanvasMsg::ClearRect(rect)).unwrap(); } fn StrokeRect(self, x: f64, y: f64, width: f64, height: f64) { + if !(x.is_finite() && y.is_finite() && + width.is_finite() && height.is_finite()) { + return; + } + let rect = Rect(Point2D(x as f32, y as f32), Size2D(width as f32, height as f32)); self.renderer.send(CanvasMsg::StrokeRect(rect)).unwrap(); } @@ -272,6 +314,9 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> // https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-drawimage fn DrawImage(self, image: HTMLCanvasElementOrCanvasRenderingContext2D, dx: f64, dy: f64) -> Fallible<()> { + if !(dx.is_finite() && dy.is_finite()) { + return Ok(()); + } // From rules described in the spec: // If the sx, sy, sw, and sh arguments are omitted, they must default to 0, 0, @@ -311,6 +356,10 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> // 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<()> { + if !(dx.is_finite() && dy.is_finite() && + dw.is_finite() && dh.is_finite()) { + return Ok(()); + } // From rules described in the spec: // If the sx, sy, sw, and sh arguments are omitted, they must default to 0, 0, @@ -347,6 +396,11 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> fn DrawImage__(self, image: HTMLCanvasElementOrCanvasRenderingContext2D, sx: f64, sy: f64, sw: f64, sh: f64, dx: f64, dy: f64, dw: f64, dh: f64) -> Fallible<()> { + if !(sx.is_finite() && sy.is_finite() && sw.is_finite() && sh.is_finite() && + dx.is_finite() && dy.is_finite() && dw.is_finite() && dh.is_finite()) { + return Ok(()); + } + match image { HTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(image) => { let canvas = image.root(); @@ -366,19 +420,37 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> } fn MoveTo(self, x: f64, y: f64) { + if !(x.is_finite() && y.is_finite()) { + return; + } + self.renderer.send(CanvasMsg::MoveTo(Point2D(x as f32, y as f32))).unwrap(); } fn LineTo(self, x: f64, y: f64) { + if !(x.is_finite() && y.is_finite()) { + return; + } + self.renderer.send(CanvasMsg::LineTo(Point2D(x as f32, y as f32))).unwrap(); } fn QuadraticCurveTo(self, cpx: f64, cpy: f64, x: f64, y: f64) { + if !(cpx.is_finite() && cpy.is_finite() && + x.is_finite() && y.is_finite()) { + return; + } + self.renderer.send(CanvasMsg::QuadraticCurveTo(Point2D(cpx as f32, cpy as f32), Point2D(x as f32, y as f32))).unwrap(); } fn BezierCurveTo(self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) { + if !(cp1x.is_finite() && cp1y.is_finite() && cp2x.is_finite() && cp2y.is_finite() && + x.is_finite() && y.is_finite()) { + return; + } + self.renderer.send(CanvasMsg::BezierCurveTo(Point2D(cp1x as f32, cp1y as f32), Point2D(cp2x as f32, cp2y as f32), Point2D(x as f32, y as f32))).unwrap(); @@ -463,6 +535,10 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> } fn CreateImageData(self, sw: f64, sh: f64) -> Fallible<Temporary<ImageData>> { + if !(sw.is_finite() && sh.is_finite()) { + return Err(NotSupported); + } + if sw == 0.0 || sh == 0.0 { return Err(IndexSize) } @@ -491,6 +567,12 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> } fn PutImageData(self, imagedata: JSRef<ImageData>, dx: Finite<f64>, dy: Finite<f64>) { + // XXX: + // By the spec: http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas_CR/#dom-context-2d-putimagedata + // "If any of the arguments to the method are infinite or NaN, the method must throw a NotSupportedError exception" + // But this arguments are stricted value, so if they are not finite values, + // they will be TypeError by WebIDL spec before call this methods. + 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; @@ -499,6 +581,12 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> fn PutImageData_(self, imagedata: JSRef<ImageData>, dx: Finite<f64>, dy: Finite<f64>, dirtyX: Finite<f64>, dirtyY: Finite<f64>, dirtyWidth: Finite<f64>, dirtyHeight: Finite<f64>) { + // XXX: + // By the spec: http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas_CR/#dom-context-2d-putimagedata + // "If any of the arguments to the method are infinite or NaN, the method must throw a NotSupportedError exception" + // But this arguments are stricted value, so if they are not finite values, + // they will be TypeError by WebIDL spec before call this methods. + 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(), |