blob: 034d19e94bc3a2f7e42791439c6918b67476a502 [file] [log] [blame]
/*
* Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
* for details. All rights reserved. Use of this source code is governed by a
* BSD-style license that can be found in the LICENSE file.
*/
/**
* @description This test ensures that putImageData works correctly, the end
* result should be a 100x100px green square.
*/
import "dart:html";
import "../../testcommon.dart";
import "../../../Utils/async_utils.dart";
var NaN = double.NAN;
var Inf = double.INFINITY;
var NegInf = double.NEGATIVE_INFINITY;
main() {
document.body.setInnerHtml('''
<canvas id="canvas" width="100" height="100"></canvas><br/>
''', treeSanitizer: new NullTreeSanitizer());
var context;
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;
}
}
}
dataToArray(data) {
var result = new List(data.length);
for (var i = 0; i < data.length; i++)
result[i] = data[i];
return result;
}
getPixel(x, y) {
var data = context.getImageData(x,y,1,1);
if (data == null) // getImageData failed, which should never happen
return [-1,-1,-1,-1];
return dataToArray(data.data);
}
pixelShouldBe(x, y, colour) {
shouldBeList(getPixel(x, y), colour);
}
var canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
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]);
shouldThrow(() => context.putImageData({}, 0, 0));
shouldThrow(() => context.putImageData(buffer, NaN, 0, 0, 0, 0, 0));
shouldThrow(() => context.putImageData(buffer, 0, NaN, 0, 0, 0, 0));
shouldThrow(() => context.putImageData(buffer, 0, 0, NaN, 0, 0, 0));
shouldThrow(() => context.putImageData(buffer, 0, 0, 0, NaN, 0, 0));
shouldThrow(() => context.putImageData(buffer, 0, 0, 0, 0, NaN, 0));
shouldThrow(() => context.putImageData(buffer, 0, 0, 0, 0, 0, NaN));
shouldThrow(() => context.putImageData(buffer, Inf, 0, 0, 0, 0, 0));
shouldThrow(() => context.putImageData(buffer, 0, Inf, 0, 0, 0, 0));
shouldThrow(() => context.putImageData(buffer, 0, 0, Inf, 0, 0, 0));
shouldThrow(() => context.putImageData(buffer, 0, 0, 0, Inf, 0, 0));
shouldThrow(() => context.putImageData(buffer, 0, 0, 0, 0, Inf, 0));
shouldThrow(() => context.putImageData(buffer, 0, 0, 0, 0, 0, Inf));
shouldThrow(() => context.putImageData(buffer, null, 0, 0, 0, 0, 0));
shouldThrow(() => context.putImageData(buffer, 0, null, 0, 0, 0, 0));
shouldThrow(() => context.putImageData(buffer, 0, 0, null, 0, 0, 0));
shouldThrow(() => context.putImageData(buffer, 0, 0, 0, null, 0, 0));
shouldThrow(() => context.putImageData(buffer, 0, 0, 0, 0, null, 0));
shouldThrow(() => context.putImageData(buffer, 0, 0, 0, 0, 0, null));
// 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);
rectcanvas = document.createElement("canvas");
rectcanvas.width = 10;
rectcanvas.height = 20;
rectbuffer = rectcanvas.getContext("2d");
rectbuffer.putImageData(smallbuffer, 0, 10);
}