Bug 1928997: Update tabs icon in Unified Search popup r=desktop-theme-reviewers,daleh...
[gecko.git] / dom / canvas / test / test_imagebitmap_cropping.html
blobbb0f06f423876811e29f83eb41e582bfade91728
1 <!DOCTYPE HTML>
2 <title>Test ImageBitmap Cropping (Bug 1190210)</title>
3 <meta charset="utf-8">
4 <script src="/tests/SimpleTest/SimpleTest.js"></script>
5 <link rel="stylesheet" href="/tests/SimpleTest/test.css">
6 <body>
7 <script type="text/javascript">
9 SimpleTest.waitForExplicitFinish();
11 /**
12 * [isPixel description]
13 * @param {[type]} ctx : canvas context
14 * @param {[type]} x : pixel x coordinate
15 * @param {[type]} y : pixel y coordinate
16 * @param {[type]} c : a rgba color code
17 * @param {[type]} d : error duration
18 * @return {Promise}
20 function isPixel(ctx, x, y, c, d) {
21 var pos = x + "," + y;
22 var color = c[0] + "," + c[1] + "," + c[2] + "," + c[3];
23 var pixel = ctx.getImageData(x, y, 1, 1);
24 var pr = pixel.data[0],
25 pg = pixel.data[1],
26 pb = pixel.data[2],
27 pa = pixel.data[3];
28 ok(c[0]-d <= pr && pr <= c[0]+d &&
29 c[1]-d <= pg && pg <= c[1]+d &&
30 c[2]-d <= pb && pb <= c[2]+d &&
31 c[3]-d <= pa && pa <= c[3]+d,
32 "pixel "+pos+" of "+ctx.canvas.id+" is "+pr+","+pg+","+pb+","+pa+"; expected "+color+" +/- "+d);
36 // The pattern of the 320x240.webm video.
37 // .------------------------------------------------.
38 // | 255 | 255 | 0 | 0 | 255 | 255 | 0 |
39 // | 255 | 255 | 255 | 255 | 0 | 0 | 0 |
40 // | 255 | 0 | 255 | 0 | 255 | 0 | 255 |
41 // | | | | | | | |
42 // ^ ^ ^ ^ ^ ^ ^ ^
43 // 0 46 92 138 184 230 276 319
46 // TEST_BITMAPS is a collection of test cases.
47 // Each object in the TEST_BITMAPS array is a test case with the following
48 // properties:
49 // 1) croppingArea: indicating the cropping area in format (x, y, width, height).
50 // 2) testedPixels: an array of pixels that is going to be checked.
51 // Each item in the testedPixels array contains:
52 // 2.1) "pixel": the coordinate of this pixel (x, y).
53 // 2.2) "expectedColor": the expected color of this pixel (r, g, b, a).
54 // 2.3) "tolerance": the acceptable tolerance of pixel values.
56 var TEST_BITMAPS = [
57 // Cropping area is exactly the same as source surface.
58 {'croppingArea': [0, 0, 320, 240],
59 'testedPixels': [{"pixel": [0, 0], "expectedColor": [255, 255, 255, 255], "tolerance": 5},
60 {"pixel": [50, 0], "expectedColor": [255, 255, 0, 255], "tolerance": 5}]},
61 // Cropping area completely covers the source surface.
62 {'croppingArea': [-100, -100, 520, 440],
63 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0], "tolerance": 5},
64 {"pixel": [519, 0], "expectedColor": [0, 0, 0, 0], "tolerance": 5},
65 {"pixel": [0, 439], "expectedColor": [0, 0, 0, 0], "tolerance": 5},
66 {"pixel": [519, 439], "expectedColor": [0, 0, 0, 0], "tolerance": 5},
67 {"pixel": [100, 100], "expectedColor": [255, 255, 255, 255], "tolerance": 5},
68 {"pixel": [150, 120], "expectedColor": [255, 255, 0, 255], "tolerance": 5},
69 {"pixel": [200, 140], "expectedColor": [0, 255, 255, 255], "tolerance": 5}]},
70 // Cropping area partially covers the left-upper part of the source surface.
71 {'croppingArea': [-100, -100, 320, 240],
72 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0 ], "tolerance": 5},
73 {"pixel": [100, 100], "expectedColor": [255, 255, 255, 255], "tolerance": 5},
74 {"pixel": [150, 100], "expectedColor": [255, 255, 0, 255], "tolerance": 5}]},
75 // Cropping area partially covers the middle-upper part of the source surface.
76 {'croppingArea': [ 100, -100, 220, 240],
77 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0 ], "tolerance": 5},
78 {"pixel": [0, 100], "expectedColor": [0, 255, 255, 255], "tolerance": 5},
79 {"pixel": [150, 100], "expectedColor": [255, 0, 0, 255], "tolerance": 5}]},
80 // Cropping area partially covers the right-upper part of the source surface.
81 {'croppingArea': [ 200, -100, 320, 240],
82 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0 ], "tolerance": 5},
83 {"pixel": [0, 100], "expectedColor": [255, 0, 255, 255], "tolerance": 5},
84 {"pixel": [100, 100], "expectedColor": [0, 0, 255, 255], "tolerance": 5}]},
85 // Cropping area partially covers the left-center part of the source surface.
86 {'croppingArea': [-100, 100, 320, 120],
87 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0 ], "tolerance": 5},
88 {"pixel": [200, 0], "expectedColor": [0, 255, 255, 255], "tolerance": 5},
89 {"pixel": [250, 10], "expectedColor": [0, 255, 0, 255], "tolerance": 5}]},
90 // Cropping area partially covers the left-bottom part of the source surface.
91 {'croppingArea': [-100, 200, 320, 240],
92 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0 ], "tolerance": 5},
93 {"pixel": [100, 0], "expectedColor": [0, 60, 136, 255], "tolerance": 5},
94 {"pixel": [180, 10], "expectedColor": [255, 255, 255, 255], "tolerance": 5}]},
95 // Cropping area partially covers the middle-bottom part of the source surface.
96 {'croppingArea': [ 40, 200, 200, 100],
97 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 60, 136, 255], "tolerance": 5},
98 {"pixel": [100, 20], "expectedColor": [107, 0, 210, 255], "tolerance": 5},
99 {"pixel": [80, 150], "expectedColor": [0, 0, 0, 0 ], "tolerance": 5}]},
100 // Cropping area partially covers the right-bottom part of the source surface.
101 {'croppingArea': [ 160, 100, 300, 300],
102 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 255, 0, 255], "tolerance": 5},
103 {"pixel": [120, 20], "expectedColor": [0, 0, 255, 255], "tolerance": 5},
104 {"pixel": [299, 299], "expectedColor": [0, 0, 0, 0 ], "tolerance": 5}]},
105 // Cropping area is completely outside the source surface. (upper-left)
106 {'croppingArea': [-500, -500, 20, 20],
107 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0], "tolerance": 5},
108 {"pixel": [19, 19], "expectedColor": [0, 0, 0, 0], "tolerance": 5}]},
109 // Cropping area is completely outside the source surface. (upper-right)
110 {'croppingArea': [ 500, -500, 20, 20],
111 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0], "tolerance": 5},
112 {"pixel": [19, 19], "expectedColor": [0, 0, 0, 0], "tolerance": 5}]},
113 // Cropping area is completely outside the source surface. (bottom-left)
114 {'croppingArea': [-200, 500, 20, 20],
115 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0], "tolerance": 5},
116 {"pixel": [19, 19], "expectedColor": [0, 0, 0, 0], "tolerance": 5}]},
117 // Cropping area is completely outside the source surface. (bottom-right)
118 {'croppingArea': [ 500, 200, 20, 20],
119 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0], "tolerance": 5},
120 {"pixel": [19, 19], "expectedColor": [0, 0, 0, 0], "tolerance": 5}]},
123 function failed(ex) {
124 ok(false, "Promise failure: " + ex);
127 var gImage;
128 var gVideo;
129 var gCanvas;
130 var gCtx;
131 var gImageData;
132 var gImageBitmap;
133 var gPNGBlob;
134 var gJPEGBlob;
136 function prepareSources() {
137 gVideo = document.createElement("video");
138 gVideo.src = "http://example.com/tests/dom/canvas/test/crossorigin/video.sjs?name=tests/dom/canvas/test/320x240.webm&type=video/webm&cors=anonymous";
139 gVideo.crossOrigin = "anonymous";
140 gVideo.autoplay = "true"
143 gCanvas = document.createElement("canvas");
144 gCtx = gCanvas.getContext("2d");
146 var resolver;
147 var promise = new Promise(function(resolve, reject) {
148 resolver = resolve;
151 // Prepare video.
152 gVideo.onloadeddata = function() {
153 ok(gVideo, "[Prepare Sources] gVideo is ok.");
155 // Prepare canvas.
156 gCanvas.width = gVideo.videoWidth;
157 gCanvas.height = gVideo.videoHeight;
158 gCtx.drawImage(gVideo, 0, 0);
159 ok(gCanvas, "[Prepare Sources] gCanvas is ok.");
160 ok(gCtx, "[Prepare Sources] gCtx is ok.");
162 // Prepare image.
163 gImage = document.createElement("img");
164 gImage.src = gCanvas.toDataURL();
165 var resolverImage;
166 var promiseImage = new Promise(function(resolve, reject) {
167 resolverImage = resolve;
169 gImage.onload = function() {
170 resolverImage(true);
173 // Prepare ImageData.
174 gImageData = gCtx.getImageData(0, 0, gCanvas.width, gCanvas.height);
175 ok(gImageData, "[Prepare Sources] gImageData is ok.");
177 // Prepapre PNG Blob.
178 var promisePNGBlob = new Promise(function(resolve, reject) {
179 gCanvas.toBlob(function(blob) {
180 gPNGBlob = blob;
181 ok(gPNGBlob, "[Prepare Sources] gPNGBlob is ok.");
182 resolve(true);
186 // Prepare JPEG Blob.
187 var promiseJPEGBlob = new Promise(function(resolve, reject) {
188 gCanvas.toBlob(function(blob) {
189 gJPEGBlob = blob;
190 ok(gJPEGBlob, "[Prepare Sources] gJPEGBlob is ok.");
191 resolve(true);
192 }, "image/jpeg", 0.95);
195 // Prepare ImageBitmap.
196 var promiseImageBitmap = new Promise(function(resolve, reject) {
197 var p = createImageBitmap(gVideo);
198 p.then(function(bitmap) {
199 gImageBitmap = bitmap;
200 ok(gImageBitmap, "[Prepare Sources] gImageBitmap is ok.");
201 resolve(true);
205 resolver(Promise.all([
206 promiseImage,
207 promisePNGBlob,
208 promiseJPEGBlob,
209 promiseImageBitmap
213 return promise;
216 function testCropping_randomTest(source) {
217 var canvasSrouce = document.createElement("canvas");
218 var ctxSource = canvasSrouce.getContext("2d");
220 var p = createImageBitmap(source);
221 p.then(function(bitmap) {
222 canvasSrouce.width = bitmap.width;
223 canvasSrouce.height = bitmap.height;
227 function testCropping(source) {
228 var canvas = document.createElement("canvas");
229 var ctx = canvas.getContext("2d");
230 document.body.appendChild(canvas);
232 function createBitmap(def) {
233 return createImageBitmap(source, def.croppingArea[0], def.croppingArea[1], def.croppingArea[2], def.croppingArea[3])
234 .then(function (bitmap) { def.bitmap = bitmap; }, failed);
237 var promise = new Promise(function(resolve, reject) {
238 resolve(Promise.all(TEST_BITMAPS.map(createBitmap)))
241 function testPixel(testedPixel) {
242 isPixel(ctx, testedPixel.pixel[0], testedPixel.pixel[1], testedPixel.expectedColor, testedPixel.tolerance);
245 return promise.then(function() {
246 TEST_BITMAPS.forEach(function (testCase) {
247 if (!testCase.bitmap) { return; }
248 ctx.clearRect(0, 0, canvas.width, canvas.height);
249 canvas.width = testCase.bitmap.width;
250 canvas.height = testCase.bitmap.height;
251 ctx.drawImage(testCase.bitmap, 0, 0);
252 testCase.testedPixels.forEach(testPixel);
257 function runTests() {
259 prepareSources().
260 then( function() { return Promise.all([testCropping(gImage),
261 testCropping(gVideo),
262 testCropping(gCanvas),
263 testCropping(gCtx),
264 testCropping(gImageData),
265 testCropping(gImageBitmap),
266 testCropping(gPNGBlob),
267 testCropping(gJPEGBlob)]); }).
268 then(SimpleTest.finish, function(ev) { failed(ev); SimpleTest.finish(); });
271 addLoadEvent(runTests);
273 </script>
274 </body>