Bug 629875/bug 669366. Switch back to our old behaviour for source rects larger than the source image for both Cairo and Azure canvas implementations. r=joe a=dveditz
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Fri, 22 Jul 2011 15:35:16 -0400
changeset 73255 b9ad0b9119b76a3a4d2df635b38bbf6b061aece7
parent 73254 d24c906511d1171a521e56c41c5445c37c5faec8
child 73256 2a4b2cd2c3cdf0d3b8d5805cdcbf9c3863d50da3
push id20841
push usermak77@bonardo.net
push dateMon, 25 Jul 2011 12:14:44 +0000
treeherdermozilla-central@87645ab8ab27 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjoe, dveditz
bugs629875, 669366
milestone8.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 629875/bug 669366. Switch back to our old behaviour for source rects larger than the source image for both Cairo and Azure canvas implementations. r=joe a=dveditz We haven't decided what the behaviour for source rects larger than the source image should be, and 4ede7b9b55bc breaks content like 20thingsilearned.com.
content/canvas/src/nsCanvasRenderingContext2D.cpp
content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
content/canvas/test/test_canvas.html
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -3292,57 +3292,34 @@ nsCanvasRenderingContext2D::DrawImage(ns
         dy = a6;
         dw = a7;
         dh = a8;
     } else {
         // XXX ERRMSG we need to report an error to developers here! (bug 329026)
         return NS_ERROR_INVALID_ARG;
     }
 
-    if (sw == 0.0 || sh == 0.0) {
-        // zero-sized source -- failure !?
-        return NS_ERROR_DOM_INDEX_SIZE_ERR;
-    }
-
     if (dw == 0.0 || dh == 0.0) {
         // not really failure, but nothing to do --
         // and noone likes a divide-by-zero
         return NS_OK;
     }
 
-    // The following check might do the validation of the float arguments:
-    //   (!FloatValidate(sx, sy, sw, sh) || !FloatValidate(dx, dy, dw, dh))
-    // but we would also need to validate some sums for overflow (e.g. sx + sw).
-    if (!FloatValidate(sx + sw, sy + sh, dx + dw, dy + dh)) {
+    if (!FloatValidate(sx, sy, sw, sh) || !FloatValidate(dx, dy, dw, dh)) {
         return NS_OK;
     }
 
-    // Handle negative sw, sh, dw and dh by flipping the rectangle over in the
-    // relevant direction.
-    if (sw < 0.0) {
-      sx += sw;
-      sw = -sw;
-    }
-    if (sh < 0.0) {
-      sy += sh;
-      sh = -sh;
-    }
-    if (dw < 0.0) {
-      dx += dw;
-      dw = -dw;
-    }
-    if (dh < 0.0) {
-      dy += dh;
-      dh = -dh;
-    }
-
-    // Checking source image boundaries.
-    if (sx < 0 || sx + sw > (double) imgSize.width || 
-        sy < 0 || sy + sh > (double) imgSize.height) {
-      return NS_ERROR_DOM_INDEX_SIZE_ERR;
+    // check args
+    if (sx < 0.0 || sy < 0.0 ||
+        sw < 0.0 || sw > (double) imgSize.width ||
+        sh < 0.0 || sh > (double) imgSize.height ||
+        dw < 0.0 || dh < 0.0)
+    {
+        // XXX ERRMSG we need to report an error to developers here! (bug 329026)
+        return NS_ERROR_DOM_INDEX_SIZE_ERR;
     }
 
     matrix.Translate(gfxPoint(sx, sy));
     matrix.Scale(sw/dw, sh/dh);
 
     pattern = new gfxPattern(imgsurf);
     pattern->SetMatrix(matrix);
     pattern->SetExtend(gfxPattern::EXTEND_PAD);
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -3736,49 +3736,27 @@ nsCanvasRenderingContext2DAzure::DrawIma
     dy = a6;
     dw = a7;
     dh = a8;
   } else {
     // XXX ERRMSG we need to report an error to developers here! (bug 329026)
     return NS_ERROR_INVALID_ARG;
   }
 
-  if (sw == 0.0 || sh == 0.0) {
-    // zero-sized source -- failure !?
-    return NS_ERROR_DOM_INDEX_SIZE_ERR;
-  }
-
   if (dw == 0.0 || dh == 0.0) {
     // not really failure, but nothing to do --
     // and noone likes a divide-by-zero
     return NS_OK;
   }
 
-  // Handle negative sw, sh, dw and dh by flipping the rectangle over in the
-  // relevant direction.
-  if (sw < 0.0) {
-    sx += sw;
-    sw = -sw;
-  }
-  if (sh < 0.0) {
-    sy += sh;
-    sh = -sh;
-  }
-  if (dw < 0.0) {
-    dx += dw;
-    dw = -dw;
-  }
-  if (dh < 0.0) {
-    dy += dh;
-    dh = -dh;
-  }
-
-  // Checking source image boundaries.
-  if (sx < 0 || sx + sw > (double) imgSize.width || 
-      sy < 0 || sy + sh > (double) imgSize.height) {
+  if (sx < 0.0 || sy < 0.0 ||
+      sw < 0.0 || sw > (double) imgSize.width ||
+      sh < 0.0 || sh > (double) imgSize.height ||
+      dw < 0.0 || dh < 0.0) {
+    // XXX - Unresolved spec issues here, for now return error.
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
 
   Filter filter;
 
   if (CurrentState().imageSmoothingEnabled)
     filter = mgfx::FILTER_LINEAR;
   else
--- a/content/canvas/test/test_canvas.html
+++ b/content/canvas/test/test_canvas.html
@@ -3037,75 +3037,51 @@ todo(img.complete === false, "img.comple
 var _thrown = undefined; try {
   ctx.drawImage(img, 0, 0);
 } catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INVALID_STATE_ERR, "should throw INVALID_STATE_ERR");
 
 
 }
 </script>
 
-<!-- [[[ test_2d.drawImage.negativedir.html ]]] -->
-
-<p>Canvas test: 2d.drawImage.negativedir</p>
-<canvas id="c117a" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
-<script>
-
-
-function test_2d_drawImage_negativedir() {
-
-var canvas = document.getElementById('c117a');
-var ctx = canvas.getContext('2d');
-
-ctx.fillStyle = '#f00';
-ctx.fillRect(0, 0, 100, 50);
-ctx.drawImage(document.getElementById('ggrr-256x256_0.png'), 0, 178, 50, -100, 0, 0, 50, 100);
-ctx.drawImage(document.getElementById('ggrr-256x256_0.png'), 0, 78, 50, 100, 50, 100, 50, -100);
-isPixel(ctx, 1,1, 0,255,0,255, 2);
-isPixel(ctx, 1,48, 0,255,0,255, 2);
-isPixel(ctx, 98,1, 0,255,0,255, 2);
-isPixel(ctx, 98,48, 0,255,0,255, 2);
-isPixel(ctx, 48,1, 0,255,0,255, 2);
-isPixel(ctx, 48,48, 0,255,0,255, 2);
-isPixel(ctx, 51,1, 0,255,0,255, 2);
-isPixel(ctx, 51,48, 0,255,0,255, 2);
-isPixel(ctx, 25,25, 0,255,0,255, 2);
-isPixel(ctx, 75,25, 0,255,0,255, 2);
-
-
-}
-</script>
-<img src="image_ggrr-256x256.png" id="ggrr-256x256_0.png" class="resource">
-
 <!-- [[[ test_2d.drawImage.negativedest.html ]]] -->
 
 <p>Canvas test: 2d.drawImage.negativedest</p>
 <canvas id="c117" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
 
 
 function test_2d_drawImage_negativedest() {
 
 var canvas = document.getElementById('c117');
 var ctx = canvas.getContext('2d');
 
+var _thrown_outer = false;
+try {
+
 ctx.fillStyle = '#f00';
 ctx.fillRect(0, 0, 100, 50);
 ctx.drawImage(document.getElementById('ggrr-256x256_1.png'), 100, 78, 50, 50, 0, 50, 50, -50);
 ctx.drawImage(document.getElementById('ggrr-256x256_1.png'), 100, 128, 50, -50, 100, 50, -50, -50);
 isPixel(ctx, 1,1, 0,255,0,255, 2);
 isPixel(ctx, 1,48, 0,255,0,255, 2);
 isPixel(ctx, 98,1, 0,255,0,255, 2);
 isPixel(ctx, 98,48, 0,255,0,255, 2);
 isPixel(ctx, 48,1, 0,255,0,255, 2);
 isPixel(ctx, 48,48, 0,255,0,255, 2);
 isPixel(ctx, 51,1, 0,255,0,255, 2);
 isPixel(ctx, 51,48, 0,255,0,255, 2);
 isPixel(ctx, 25,25, 0,255,0,255, 2);
 isPixel(ctx, 75,25, 0,255,0,255, 2);
 
+} catch (e) {
+    _thrown_outer = true;
+}
+todo(!_thrown_outer, 'should not throw exception');
+
 
 }
 </script>
 <img src="image_ggrr-256x256.png" id="ggrr-256x256_1.png" class="resource">
 
 <!-- [[[ test_2d.drawImage.negativesource.html ]]] -->
 
 <p>Canvas test: 2d.drawImage.negativesource</p>
@@ -3113,31 +3089,39 @@ isPixel(ctx, 75,25, 0,255,0,255, 2);
 <script>
 
 
 function test_2d_drawImage_negativesource() {
 
 var canvas = document.getElementById('c118');
 var ctx = canvas.getContext('2d');
 
+var _thrown_outer = false;
+try {
+
 ctx.fillStyle = '#f00';
 ctx.fillRect(0, 0, 100, 50);
 ctx.drawImage(document.getElementById('ggrr-256x256_2.png'), 100, 78, -100, 50, 0, 0, 50, 50);
 ctx.drawImage(document.getElementById('ggrr-256x256_2.png'), 100, 128, -100, -50, 50, 0, 50, 50);
 isPixel(ctx, 1,1, 0,255,0,255, 2);
 isPixel(ctx, 1,48, 0,255,0,255, 2);
 isPixel(ctx, 98,1, 0,255,0,255, 2);
 isPixel(ctx, 98,48, 0,255,0,255, 2);
 isPixel(ctx, 48,1, 0,255,0,255, 2);
 isPixel(ctx, 48,48, 0,255,0,255, 2);
 isPixel(ctx, 51,1, 0,255,0,255, 2);
 isPixel(ctx, 51,48, 0,255,0,255, 2);
 isPixel(ctx, 25,25, 0,255,0,255, 2);
 isPixel(ctx, 75,25, 0,255,0,255, 2);
 
+} catch (e) {
+    _thrown_outer = true;
+}
+todo(!_thrown_outer, 'should not throw exception');
+
 
 }
 </script>
 <img src="image_ggrr-256x256.png" id="ggrr-256x256_2.png" class="resource">
 
 <!-- [[[ test_2d.drawImage.nonfinite.html ]]] -->
 
 <p>Canvas test: 2d.drawImage.nonfinite</p>
@@ -3523,45 +3507,52 @@ var _thrown = undefined; try {
 
 
 
 function test_2d_drawImage_outsidesource() {
 
 var canvas = document.getElementById('c122');
 var ctx = canvas.getContext('2d');
 
+var _thrown_outer = false;
+try {
+
 ctx.drawImage(document.getElementById('green_7.png'), 10.5, 10.5, 89.5, 39.5, 0, 0, 100, 50);
 ctx.drawImage(document.getElementById('green_7.png'), 5.5, 5.5, -5.5, -5.5, 0, 0, 100, 50);
 ctx.drawImage(document.getElementById('green_7.png'), 100, 50, -5, -5, 0, 0, 100, 50);
-
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_11.png'), -0.001, 0, 100, 50, 0, 0, 100, 50);
 } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_11.png'), 0, -0.001, 100, 50, 0, 0, 100, 50);
 } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_11.png'), 0, 0, 100.001, 50, 0, 0, 100, 50);
 } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_11.png'), 0, 0, 100, 50.001, 0, 0, 100, 50);
 } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_11.png'), 50, 0, 50.001, 50, 0, 0, 100, 50);
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_11.png'), 0, 0, -5, 5, 0, 0, 100, 50);
 } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_11.png'), 0, 0, 5, -5, 0, 0, 100, 50);
 } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_11.png'), 110, 60, -20, -20, 0, 0, 100, 50);
 } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
-isPixel(ctx, 50,25, 0,255,0,255, 2);
+todo_isPixel(ctx, 50,25, 0,255,0,255, 2);
+
+} catch (e) {
+    _thrown_outer = true;
+}
+todo(!_thrown_outer, 'should not throw exception');
 
 
 }
 </script>
 <img src="image_green.png" id="green_7.png" class="resource">
 <img src="image_red.png" id="red_11.png" class="resource">
 
 <!-- [[[ test_2d.drawImage.path.html ]]] -->
@@ -3708,23 +3699,23 @@ function test_2d_drawImage_zerosource() 
 
 var canvas = document.getElementById('c128');
 var ctx = canvas.getContext('2d');
 
 ctx.fillStyle = '#0f0';
 ctx.fillRect(0, 0, 100, 50);
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_14.png'), 10, 10, 0, 1, 0, 0, 100, 50);
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_14.png'), 10, 10, 1, 0, 0, 0, 100, 50);
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 var _thrown = undefined; try {
   ctx.drawImage(document.getElementById('red_14.png'), 10, 10, 0, 0, 0, 0, 100, 50);
-} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
+} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR");
 isPixel(ctx, 50,25, 0,255,0,255, 2);
 
 
 }
 </script>
 <img src="image_red.png" id="red_14.png" class="resource">
 
 <!-- [[[ test_2d.fillRect.basic.html ]]] -->
@@ -19526,18 +19517,18 @@ ok(ctx.arcTo(0, 0, 0, 0, 1) === undefine
 ok(ctx.rect(0, 0, 0, 0) === undefined, "ctx.rect(0, 0, 0, 0) === undefined");
 ok(ctx.arc(0, 0, 1, 0, 0, true) === undefined, "ctx.arc(0, 0, 1, 0, 0, true) === undefined");
 ok(ctx.fill() === undefined, "ctx.fill() === undefined");
 ok(ctx.stroke() === undefined, "ctx.stroke() === undefined");
 ok(ctx.clip() === undefined, "ctx.clip() === undefined");
 if (ctx.putImageData) {
     ok(ctx.putImageData(ctx.getImageData(0, 0, 1, 1), 0, 0) === undefined, "ctx.putImageData(ctx.getImageData(0, 0, 1, 1), 0, 0) === undefined");
 }
-ok(ctx.drawImage(document.getElementById('yellow_11.png'), 0, 0, 1, 1, 0, 0, 0, 0) === undefined, "ctx.drawImage(document.getElementById('yellow_11.png'), 0, 0, 1, 1, 0, 0, 0, 0) === undefined");
-ok(ctx.drawImage(canvas, 0, 0, 1, 1, 0, 0, 0, 0) === undefined, "ctx.drawImage(canvas, 0, 0, 1, 1, 0, 0, 0, 0) === undefined");
+ok(ctx.drawImage(document.getElementById('yellow_11.png'), 0, 0, 0, 0, 0, 0, 0, 0) === undefined, "ctx.drawImage(document.getElementById('yellow_11.png'), 0, 0, 0, 0, 0, 0, 0, 0) === undefined");
+ok(ctx.drawImage(canvas, 0, 0, 0, 0, 0, 0, 0, 0) === undefined, "ctx.drawImage(canvas, 0, 0, 0, 0, 0, 0, 0, 0) === undefined");
 ok(ctx.createLinearGradient(0, 0, 0, 0).addColorStop(0, 'white') === undefined, "ctx.createLinearGradient(0, 0, 0, 0).addColorStop(0, 'white') === undefined");
 
 
 }
 </script>
 <img src="image_yellow.png" id="yellow_11.png" class="resource">
 
 <!-- [[[ test_bug397524.html ]]] -->
@@ -21918,21 +21909,16 @@ function runTests() {
   ok(false, "unexpected exception thrown in: test_2d_drawImage_floatsource");
  }
  try {
   test_2d_drawImage_incomplete();
  } catch (e) {
   ok(false, "unexpected exception thrown in: test_2d_drawImage_incomplete");
  }
  try {
-  test_2d_drawImage_negativedir();
- } catch (e) {
-  ok(false, "unexpected exception thrown in: test_2d_drawImage_negativedir");
- }
- try {
   test_2d_drawImage_negativedest();
  } catch (e) {
   ok(false, "unexpected exception thrown in: test_2d_drawImage_negativedest");
  }
  try {
   test_2d_drawImage_negativesource();
  } catch (e) {
   ok(false, "unexpected exception thrown in: test_2d_drawImage_negativesource");