Bug 663194 - Calling drawImage with zero-size canvas should throw INVALID_STATE_ERR; r=sicking
authorMs2ger <ms2ger@gmail.com>
Sat, 11 Jun 2011 09:52:27 +0200
changeset 71416 8b3315430b6d608ce0e3dca08490e48caeeb1243
parent 71415 d2bdaef8a701c89e0035fef84557a9c3590e0e28
child 71417 68ea3c29fb0fe342b55c245e3f0bd87b3ced46f5
push id159
push usereakhgari@mozilla.com
push dateTue, 16 Aug 2011 17:53:11 +0000
treeherdermozilla-beta@8786e3e49240 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs663194
milestone7.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 663194 - Calling drawImage with zero-size canvas should throw INVALID_STATE_ERR; r=sicking
content/canvas/src/nsCanvasRenderingContext2D.cpp
content/canvas/test/Makefile.in
content/canvas/test/test_2d.drawImage.zerocanvas.html
content/html/content/public/nsHTMLCanvasElement.h
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -3286,18 +3286,24 @@ nsCanvasRenderingContext2D::DrawImage(ns
                                       float a2, float a3, float a4, float a5,
                                       float a6, float a7, float a8,
                                       PRUint8 optional_argc)
 {
     if (!imgElt) {
         return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
     }
 
-    double sx,sy,sw,sh;
-    double dx,dy,dw,dh;
+    nsCOMPtr<nsIContent> content = do_QueryInterface(imgElt);
+    nsHTMLCanvasElement* canvas = nsHTMLCanvasElement::FromContent(content);
+    if (canvas) {
+        nsIntSize size = canvas->GetSize();
+        if (size.width == 0 || size.height == 0) {
+            return NS_ERROR_DOM_INVALID_STATE_ERR;
+        }
+    }
 
     gfxMatrix matrix;
     nsRefPtr<gfxPattern> pattern;
     gfxIntSize imgSize;
     nsRefPtr<gfxASurface> imgsurf =
       CanvasImageCache::Lookup(imgElt, HTMLCanvasElement(), &imgSize);
 
     if (!imgsurf) {
@@ -3329,16 +3335,18 @@ nsCanvasRenderingContext2D::DrawImage(ns
         }
 
         if (res.mImageRequest) {
             CanvasImageCache::NotifyDrawImage(imgElt, HTMLCanvasElement(),
                                               res.mImageRequest, imgsurf, imgSize);
         }
     }
 
+    double sx,sy,sw,sh;
+    double dx,dy,dw,dh;
     if (optional_argc == 0) {
         dx = a1;
         dy = a2;
         sx = sy = 0.0;
         dw = sw = (double) imgSize.width;
         dh = sh = (double) imgSize.height;
     } else if (optional_argc == 2) {
         dx = a1;
--- a/content/canvas/test/Makefile.in
+++ b/content/canvas/test/Makefile.in
@@ -74,16 +74,17 @@ include $(topsrcdir)/config/rules.mk
 	test_2d.composite.canvas.source-out.html \
 	test_2d.composite.image.destination-atop.html \
 	test_2d.composite.image.destination-in.html \
 	test_2d.composite.image.source-in.html \
 	test_2d.composite.image.source-out.html \
 	test_2d.composite.uncovered.image.destination-in.html \
 	test_2d.composite.uncovered.image.source-in.html \
 	test_2d.composite.uncovered.image.source-out.html \
+	test_2d.drawImage.zerocanvas.html \
 	test_toDataURL_lowercase_ascii.html \
 	test_toDataURL_parameters.html \
 	test_mozGetAsFile.html \
 	test_canvas_strokeStyle_getter.html \
 	test_bug613794.html \
 	test_drawImage_edge_cases.html \
 	$(NULL)
 
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.drawImage.zerocanvas.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.drawImage.zerocanvas</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    ok(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 0;
+canvas2.height = 10;
+var _thrown = undefined; try {
+  ctx.drawImage(canvas2, 0, 0);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INVALID_STATE_ERR, "should throw INVALID_STATE_ERR");
+
+canvas2.width = 10;
+canvas2.height = 0;
+var _thrown = undefined; try {
+  ctx.drawImage(canvas2, 0, 0);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INVALID_STATE_ERR, "should throw INVALID_STATE_ERR");
+
+canvas2.width = 0;
+canvas2.height = 0;
+var _thrown = undefined; try {
+  ctx.drawImage(canvas2, 0, 0);
+} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INVALID_STATE_ERR, "should throw INVALID_STATE_ERR");
+
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+SimpleTest.finish();
+
+});
+</script>
+
--- a/content/html/content/public/nsHTMLCanvasElement.h
+++ b/content/html/content/public/nsHTMLCanvasElement.h
@@ -63,16 +63,23 @@ class nsHTMLCanvasElement : public nsGen
 {
   typedef mozilla::layers::CanvasLayer CanvasLayer;
   typedef mozilla::layers::LayerManager LayerManager;
 
 public:
   nsHTMLCanvasElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLCanvasElement();
 
+  static nsHTMLCanvasElement* FromContent(nsIContent* aPossibleCanvas)
+  {
+    if (!aPossibleCanvas || !aPossibleCanvas->IsHTML(nsGkAtoms::canvas)) {
+      return nsnull;
+    }
+    return static_cast<nsHTMLCanvasElement*>(aPossibleCanvas);
+  }
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)