| description("This test ensures that putImageData works correctly, the end result should be a 100x100px green square."); |
| |
| function fillRect(imageData, x, y, width, height, r, g, b, a) |
| { |
| var bytesPerRow = imageData.width * 4; |
| var data =imageData.data; |
| for (var i = 0; i < height; i++) { |
| var rowOrigin = (y+i) * bytesPerRow; |
| rowOrigin += x * 4; |
| for (var j = 0; j < width; j++) { |
| var position = rowOrigin + j * 4; |
| data[position + 0] = r; |
| data[position + 1] = g; |
| data[position + 2] = b; |
| data[position + 3] = a; |
| } |
| } |
| } |
| |
| function dataToArray(data) { |
| var result = new Array(data.length) |
| for (var i = 0; i < data.length; i++) |
| result[i] = data[i]; |
| return result; |
| } |
| |
| function getPixel(x, y) { |
| var data = context.getImageData(x,y,1,1); |
| if (!data) // getImageData failed, which should never happen |
| return [-1,-1,-1,-1]; |
| return dataToArray(data.data); |
| } |
| |
| function pixelShouldBe(x, y, colour) { |
| shouldBe("getPixel(" + [x, y] +")", "["+colour+"]"); |
| } |
| |
| var canvas = document.getElementById("canvas"); |
| var context = canvas.getContext("2d"); |
| |
| if (!context.createImageData) |
| context.createImageData = function(w,h) { |
| var data = this.getImageData(0, 0, w, h); |
| for (var i = 0; i < data.data.length; i++) |
| data.data[i] = 0; |
| } |
| var buffer = context.createImageData(100,100); |
| // Fill top left corner |
| fillRect(buffer, 0, 0, 50, 50, 0, 128,0,255); |
| context.putImageData(buffer, 0, 0); |
| pixelShouldBe( 0, 0, [0, 128,0,255]); |
| pixelShouldBe(25, 25, [0, 128,0,255]); |
| pixelShouldBe(49, 0, [0, 128,0,255]); |
| pixelShouldBe( 0, 49, [0, 128,0,255]); |
| pixelShouldBe(49, 49, [0, 128,0,255]); |
| pixelShouldBe(50, 0, [0, 0, 0, 0]); |
| pixelShouldBe( 0, 50, [0, 0, 0, 0]); |
| pixelShouldBe(50, 50, [0, 0, 0, 0]); |
| |
| // Test positioned drawing -- make bottom right green |
| context.putImageData(buffer, 0, 50); |
| pixelShouldBe( 0, 50, [0, 128,0,255]); |
| pixelShouldBe(25, 75, [0, 128,0,255]); |
| pixelShouldBe(49, 50, [0, 128,0,255]); |
| pixelShouldBe( 0, 99, [0, 128,0,255]); |
| pixelShouldBe(49, 99, [0, 128,0,255]); |
| |
| // Test translation doesn't effect putImageData |
| context.translate(50, -50); |
| context.putImageData(buffer, 50, 50); |
| pixelShouldBe(50, 50, [0, 128,0,255]); |
| pixelShouldBe(75, 75, [0, 128,0,255]); |
| pixelShouldBe(99, 99, [0, 128,0,255]); |
| pixelShouldBe(50, 49, [0, 0, 0, 0]); |
| context.translate(-50, 50); |
| |
| // Test dirty rect handling |
| buffer = context.createImageData(50,50); |
| fillRect(buffer, 0, 0, 50, 50, 0, 128, 0, 255); |
| context.putImageData(buffer, 50, 0); |
| fillRect(buffer, 0, 0, 50, 50, 255, 0, 0, 255); |
| context.putImageData(buffer, 50, 0, 15, 15, 20, 20); |
| context.fillStyle="rgb(0,128,0)"; |
| context.fillRect(65, 15, 20, 20); |
| var points = [0, 5, 15, 25, 35, 45]; |
| for (var x = 0; x < points.length; x++) |
| for (var y = 0; y < points.length; y++) |
| pixelShouldBe(points[x] + 50, points[y], [0, 128, 0, 255]); |
| |
| // Test drawing outside the canvas border |
| fillRect(buffer, 0, 0, 50, 50, 255, 0, 0, 255); |
| context.putImageData(buffer, -50, 0); |
| pixelShouldBe(0, 25, [0, 128,0,255]); |
| context.putImageData(buffer, 100, 0); |
| pixelShouldBe(99, 25, [0, 128,0,255]); |
| context.putImageData(buffer, 0, -50); |
| pixelShouldBe(25, 0, [0, 128,0,255]); |
| context.putImageData(buffer, 0, 100); |
| pixelShouldBe(25, 99, [0, 128,0,255]); |
| |
| // test drawing with non-intersecting dirty rect |
| context.putImageData(buffer, 50, 0, 50, 0, 100, 100); |
| context.putImageData(buffer, 50, 0, -50, 0, 50, 100); |
| context.putImageData(buffer, 50, 0, 0, 50, 100, 100); |
| context.putImageData(buffer, 50, 0, 50, -50, 100, 100); |
| for (var x = 0; x < points.length; x++) |
| for (var y = 0; y < points.length; y++) |
| pixelShouldBe(points[x] + 50, points[y], [0, 128, 0, 255]); |
| |
| // Test drawing to region intersect edge of canvas |
| buffer = context.createImageData(100, 100); |
| fillRect(buffer, 0, 0, 100, 100, 0, 128, 0, 255); |
| fillRect(buffer, 10, 10, 80, 80, 255, 0, 0, 255); |
| |
| //left edge |
| context.putImageData(buffer, -90, 0); |
| pixelShouldBe(0, 25, [0, 128,0,255]); |
| pixelShouldBe(0, 50, [0, 128,0,255]); |
| pixelShouldBe(0, 75, [0, 128,0,255]); |
| //right edge |
| context.putImageData(buffer, 90, 0); |
| pixelShouldBe(99, 25, [0, 128,0,255]); |
| pixelShouldBe(99, 50, [0, 128,0,255]); |
| pixelShouldBe(99, 75, [0, 128,0,255]); |
| //top edge |
| context.putImageData(buffer, 0, -90); |
| pixelShouldBe(25, 0, [0, 128,0,255]); |
| pixelShouldBe(50, 0, [0, 128,0,255]); |
| pixelShouldBe(75, 0, [0, 128,0,255]); |
| //bottom edge |
| context.putImageData(buffer, 0, 90); |
| pixelShouldBe(25, 99, [0, 128,0,255]); |
| pixelShouldBe(50, 99, [0, 128,0,255]); |
| pixelShouldBe(75, 99, [0, 128,0,255]); |
| |
| // Test drawing with only part of the dirty region intersecting the window |
| // left edge |
| context.putImageData(buffer, 0, 0, -90, 0, 100, 100); |
| pixelShouldBe(0, 25, [0, 128,0,255]); |
| pixelShouldBe(0, 50, [0, 128,0,255]); |
| pixelShouldBe(0, 75, [0, 128,0,255]); |
| pixelShouldBe(10, 25, [0, 128,0,255]); |
| pixelShouldBe(10, 50, [0, 128,0,255]); |
| pixelShouldBe(10, 75, [0, 128,0,255]); |
| //right edge |
| context.putImageData(buffer, 0, 0, 90, 0, 100, 100); |
| pixelShouldBe(99, 25, [0, 128,0,255]); |
| pixelShouldBe(99, 50, [0, 128,0,255]); |
| pixelShouldBe(99, 75, [0, 128,0,255]); |
| pixelShouldBe(89, 25, [0, 128,0,255]); |
| pixelShouldBe(89, 50, [0, 128,0,255]); |
| pixelShouldBe(89, 75, [0, 128,0,255]); |
| // top edge |
| context.putImageData(buffer, 0, 0, 0, -90, 100, 100); |
| pixelShouldBe(25, 0, [0, 128,0,255]); |
| pixelShouldBe(50, 0, [0, 128,0,255]); |
| pixelShouldBe(75, 0, [0, 128,0,255]); |
| pixelShouldBe(25, 10, [0, 128,0,255]); |
| pixelShouldBe(50, 10, [0, 128,0,255]); |
| pixelShouldBe(75, 10, [0, 128,0,255]); |
| //bottom edge |
| context.putImageData(buffer, 0, 0, 0, 90, 100, 100); |
| pixelShouldBe(25, 99, [0, 128,0,255]); |
| pixelShouldBe(50, 99, [0, 128,0,255]); |
| pixelShouldBe(75, 99, [0, 128,0,255]); |
| pixelShouldBe(25, 89, [0, 128,0,255]); |
| pixelShouldBe(50, 89, [0, 128,0,255]); |
| pixelShouldBe(75, 89, [0, 128,0,255]); |
| |
| // Test clamping of dx/dy |
| var smallbuffer = context.createImageData(10, 10); |
| fillRect(smallbuffer, 0, 0, 10, 10, 255, 0, 0, 255); |
| context.putImageData(smallbuffer, 1.5, 1); |
| pixelShouldBe(11, 11, [0, 128,0,255]); |
| fillRect(smallbuffer, 0, 0, 10, 10, 0, 128, 0, 255); |
| context.putImageData(smallbuffer, 1.5, 1); |
| pixelShouldBe(1, 1, [0, 128,0,255]); |
| |
| // test clamping of dirtyX/Y/Width/Height |
| fillRect(smallbuffer, 0, 0, 10, 10, 0, 128, 0, 255); |
| context.fillStyle = "red"; |
| context.fillRect(1, 1, 9, 9); |
| context.putImageData(smallbuffer, 1, 1, 0.5, 0.5, 8.5, 8.5); |
| pixelShouldBe(1, 1, [0, 128,0,255]); |
| pixelShouldBe(10, 10, [0, 128,0,255]); |
| context.fillRect(1, 1, 9, 9); |
| context.putImageData(smallbuffer, 1, 1, 0.25, 0.25, 9, 9); |
| pixelShouldBe(1, 1, [0, 128,0,255]); |
| pixelShouldBe(10, 10, [0, 128,0,255]); |
| context.fillRect(1, 1, 8, 8); |
| context.putImageData(smallbuffer, 1, 1, 0.0, 0.0, 8.5, 8.5); |
| pixelShouldBe(1, 1, [0, 128,0,255]); |
| pixelShouldBe(9, 9, [0, 128,0,255]); |
| context.fillRect(1, 1, 8, 8); |
| context.putImageData(smallbuffer, 1, 1, 0.0, 0.0, 8.25, 8.25); |
| pixelShouldBe(1, 1, [0, 128,0,255]); |
| pixelShouldBe(9, 9, [0, 128,0,255]); |
| context.fillRect(1, 1, 7, 7); |
| context.putImageData(smallbuffer, 1, 1, 0.5, 0.5, 7.9, 7.9); |
| pixelShouldBe(1, 1, [0, 128,0,255]); |
| pixelShouldBe(9, 9, [0, 128,0,255]); |
| |
| |
| shouldThrowErrorName("context.putImageData({}, 0, 0)", "TypeError"); |
| shouldThrow("context.putImageData(buffer, NaN, 0, 0, 0, 0, 0)", "'TypeError: Value NaN is outside the range [-2147483648, 2147483647]'"); |
| shouldThrow("context.putImageData(buffer, 0, NaN, 0, 0, 0, 0)", "'TypeError: Value NaN is outside the range [-2147483648, 2147483647]'"); |
| shouldThrow("context.putImageData(buffer, 0, 0, NaN, 0, 0, 0)", "'TypeError: Value NaN is outside the range [-2147483648, 2147483647]'"); |
| shouldThrow("context.putImageData(buffer, 0, 0, 0, NaN, 0, 0)", "'TypeError: Value NaN is outside the range [-2147483648, 2147483647]'"); |
| shouldThrow("context.putImageData(buffer, 0, 0, 0, 0, NaN, 0)", "'TypeError: Value NaN is outside the range [-2147483648, 2147483647]'"); |
| shouldThrow("context.putImageData(buffer, 0, 0, 0, 0, 0, NaN)", "'TypeError: Value NaN is outside the range [-2147483648, 2147483647]'"); |
| shouldThrow("context.putImageData(buffer, Infinity, 0, 0, 0, 0, 0)", "'TypeError: Value Infinity is outside the range [-2147483648, 2147483647]'"); |
| shouldThrow("context.putImageData(buffer, 0, Infinity, 0, 0, 0, 0)", "'TypeError: Value Infinity is outside the range [-2147483648, 2147483647]'"); |
| shouldThrow("context.putImageData(buffer, 0, 0, Infinity, 0, 0, 0)", "'TypeError: Value Infinity is outside the range [-2147483648, 2147483647]'"); |
| shouldThrow("context.putImageData(buffer, 0, 0, 0, Infinity, 0, 0)", "'TypeError: Value Infinity is outside the range [-2147483648, 2147483647]'"); |
| shouldThrow("context.putImageData(buffer, 0, 0, 0, 0, Infinity, 0)", "'TypeError: Value Infinity is outside the range [-2147483648, 2147483647]'"); |
| shouldThrow("context.putImageData(buffer, 0, 0, 0, 0, 0, Infinity)", "'TypeError: Value Infinity is outside the range [-2147483648, 2147483647]'"); |
| shouldThrow("context.putImageData(buffer, undefined, 0, 0, 0, 0, 0)", "'TypeError: Value NaN is outside the range [-2147483648, 2147483647]'"); |
| shouldThrow("context.putImageData(buffer, 0, undefined, 0, 0, 0, 0)", "'TypeError: Value NaN is outside the range [-2147483648, 2147483647]'"); |
| shouldThrow("context.putImageData(buffer, 0, 0, undefined, 0, 0, 0)", "'TypeError: Value NaN is outside the range [-2147483648, 2147483647]'"); |
| shouldThrow("context.putImageData(buffer, 0, 0, 0, undefined, 0, 0)", "'TypeError: Value NaN is outside the range [-2147483648, 2147483647]'"); |
| shouldThrow("context.putImageData(buffer, 0, 0, 0, 0, undefined, 0)", "'TypeError: Value NaN is outside the range [-2147483648, 2147483647]'"); |
| shouldThrow("context.putImageData(buffer, 0, 0, 0, 0, 0, undefined)", "'TypeError: Value NaN is outside the range [-2147483648, 2147483647]'"); |
| |
| // Ensure we don't mess up bounds clipping checks |
| var rectcanvas = document.createElement("canvas"); |
| rectcanvas.width = 20; |
| rectcanvas.height = 10; |
| var rectbuffer = rectcanvas.getContext("2d"); |
| rectbuffer.putImageData(smallbuffer, 10, 0); |
| |
| var rectcanvas = document.createElement("canvas"); |
| rectcanvas.width = 10; |
| rectcanvas.height = 20; |
| var rectbuffer = rectcanvas.getContext("2d"); |
| rectbuffer.putImageData(smallbuffer, 0, 10); |