OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 library canvas_rendering_context_2d_test; |
| 6 |
| 7 import 'dart:html'; |
| 8 import 'dart:math'; |
| 9 |
| 10 import 'package:unittest/html_individual_config.dart'; |
| 11 import 'package:unittest/unittest.dart'; |
| 12 |
| 13 // Some rounding errors in the browsers. |
| 14 checkPixel(List<int> pixel, List<int> expected) { |
| 15 expect(pixel[0], closeTo(expected[0], 2)); |
| 16 expect(pixel[1], closeTo(expected[1], 2)); |
| 17 expect(pixel[2], closeTo(expected[2], 2)); |
| 18 expect(pixel[3], closeTo(expected[3], 2)); |
| 19 } |
| 20 |
| 21 var canvas; |
| 22 var context; |
| 23 var otherCanvas; |
| 24 var otherContext; |
| 25 var video; |
| 26 |
| 27 void createCanvas() { |
| 28 canvas = new CanvasElement(); |
| 29 canvas.width = 100; |
| 30 canvas.height = 100; |
| 31 |
| 32 context = canvas.context2D; |
| 33 } |
| 34 |
| 35 void createOtherCanvas() { |
| 36 otherCanvas = new CanvasElement(); |
| 37 otherCanvas.width = 10; |
| 38 otherCanvas.height = 10; |
| 39 otherContext = otherCanvas.context2D; |
| 40 otherContext.fillStyle = "red"; |
| 41 otherContext.fillRect(0, 0, otherCanvas.width, otherCanvas.height); |
| 42 } |
| 43 |
| 44 void setupFunc() { |
| 45 createCanvas(); |
| 46 createOtherCanvas(); |
| 47 video = new VideoElement(); |
| 48 } |
| 49 |
| 50 void tearDownFunc() { |
| 51 canvas = null; |
| 52 context = null; |
| 53 otherCanvas = null; |
| 54 otherContext = null; |
| 55 video = null; |
| 56 } |
| 57 |
| 58 List<int> readPixel(int x, int y) { |
| 59 var imageData = context.getImageData(x, y, 1, 1); |
| 60 return imageData.data; |
| 61 } |
| 62 |
| 63 /// Returns true if the pixel has some data in it, false otherwise. |
| 64 bool isPixelFilled(int x, int y) => readPixel(x,y).any((p) => p != 0); |
| 65 |
| 66 String pixelDataToString(List<int> data, int x, int y) { |
| 67 return '[${data.join(", ")}]'; |
| 68 } |
| 69 |
| 70 String _filled(bool v) => v ? "filled" : "unfilled"; |
| 71 |
| 72 void expectPixelFilled(int x, int y, [bool filled = true]) { |
| 73 expect(isPixelFilled(x, y), filled, reason: |
| 74 'Pixel at ($x, $y) was expected to' |
| 75 ' be: <${_filled(filled)}> but was: <${_filled(!filled)}> with data: ' |
| 76 '${pixelDataToString(readPixel(x, y), x, y)}'); |
| 77 } |
| 78 |
| 79 void expectPixelUnfilled(int x, int y) { |
| 80 expectPixelFilled(x, y, false); |
| 81 } |
| 82 |
| 83 main() { |
| 84 useHtmlIndividualConfiguration(); |
| 85 |
| 86 group('pixel_manipulation', () { |
| 87 setUp(setupFunc); |
| 88 tearDown(tearDownFunc); |
| 89 |
| 90 test('setFillColorRgb', () { |
| 91 context.setFillColorRgb(255, 0, 255, 1); |
| 92 context.fillRect(0, 0, canvas.width, canvas.height); |
| 93 expect(readPixel(2, 2), [255, 0, 255, 255]); |
| 94 }); |
| 95 |
| 96 test('setFillColorHsl hue', () { |
| 97 context.setFillColorHsl(0, 100, 50); |
| 98 context.fillRect(0, 0, canvas.width, canvas.height); |
| 99 checkPixel(readPixel(2, 2), [255, 0, 0, 255]); |
| 100 }); |
| 101 |
| 102 test('setFillColorHsl hue 2', () { |
| 103 context.setFillColorHsl(240, 100, 50); |
| 104 context.fillRect(0, 0, canvas.width, canvas.height); |
| 105 checkPixel(readPixel(2, 2), [0, 0, 255, 255]); |
| 106 }); |
| 107 |
| 108 test('setFillColorHsl sat', () { |
| 109 context.setFillColorHsl(0, 0, 50); |
| 110 context.fillRect(0, 0, canvas.width, canvas.height); |
| 111 checkPixel(readPixel(2, 2), [127, 127, 127, 255]); |
| 112 }); |
| 113 |
| 114 test('setStrokeColorRgb', () { |
| 115 context.setStrokeColorRgb(255, 0, 255, 1); |
| 116 context.lineWidth = 10; |
| 117 context.strokeRect(0, 0, canvas.width, canvas.height); |
| 118 expect(readPixel(2, 2), [255, 0, 255, 255]); |
| 119 }); |
| 120 |
| 121 test('setStrokeColorHsl hue', () { |
| 122 context.setStrokeColorHsl(0, 100, 50); |
| 123 context.lineWidth = 10; |
| 124 context.strokeRect(0, 0, canvas.width, canvas.height); |
| 125 expect(readPixel(2, 2), [255, 0, 0, 255]); |
| 126 }); |
| 127 |
| 128 test('setStrokeColorHsl hue 2', () { |
| 129 context.setStrokeColorHsl(240, 100, 50); |
| 130 context.lineWidth = 10; |
| 131 context.strokeRect(0, 0, canvas.width, canvas.height); |
| 132 expect(readPixel(2, 2), [0, 0, 255, 255]); |
| 133 }); |
| 134 |
| 135 test('setStrokeColorHsl sat', () { |
| 136 context.setStrokeColorHsl(0, 0, 50); |
| 137 context.lineWidth = 10; |
| 138 context.strokeRect(0, 0, canvas.width, canvas.height); |
| 139 checkPixel(readPixel(2, 2), [127, 127, 127, 255]); |
| 140 }); |
| 141 |
| 142 test('fillStyle', () { |
| 143 context.fillStyle = "red"; |
| 144 context.fillRect(0, 0, canvas.width, canvas.height); |
| 145 checkPixel(readPixel(2, 2), [255, 0, 0, 255]); |
| 146 }); |
| 147 |
| 148 test('strokeStyle', () { |
| 149 context.strokeStyle = "blue"; |
| 150 context.lineWidth = 10; |
| 151 context.strokeRect(0, 0, canvas.width, canvas.height); |
| 152 expect(readPixel(2, 2), [0, 0, 255, 255]); |
| 153 }); |
| 154 |
| 155 test('fillStyle linearGradient', () { |
| 156 var gradient = context.createLinearGradient(0,0,20,20); |
| 157 gradient.addColorStop(0,'red'); |
| 158 gradient.addColorStop(1,'blue'); |
| 159 context.fillStyle = gradient; |
| 160 context.fillRect(0, 0, canvas.width, canvas.height); |
| 161 expect(context.fillStyle is CanvasGradient, isTrue); |
| 162 }); |
| 163 |
| 164 test('putImageData', () { |
| 165 context.fillStyle = 'green'; |
| 166 context.fillRect(0, 0, canvas.width, canvas.height); |
| 167 |
| 168 ImageData expectedData = context.getImageData(0, 0, 10, 10); |
| 169 expectedData.data[0] = 25; |
| 170 expectedData.data[1] = 65; |
| 171 expectedData.data[2] = 255; |
| 172 // Set alpha to 255 to make the pixels show up. |
| 173 expectedData.data[3] = 255; |
| 174 |
| 175 context.putImageData(expectedData, 0, 0); |
| 176 |
| 177 var resultingData = context.getImageData(0, 0, 10, 10); |
| 178 // Make sure that we read back what we wrote. |
| 179 expect(resultingData.data, expectedData.data); |
| 180 }); |
| 181 |
| 182 test('putImageData dirty rectangle', () { |
| 183 context.fillStyle = 'green'; |
| 184 context.fillRect(0, 0, canvas.width, canvas.height); |
| 185 |
| 186 ImageData drawnData = context.getImageData(0, 0, 10, 10); |
| 187 drawnData.data[0] = 25; |
| 188 drawnData.data[1] = 65; |
| 189 drawnData.data[2] = 255; |
| 190 drawnData.data[3] = 255; |
| 191 |
| 192 // Draw these pixels to the 2nd pixel. |
| 193 drawnData.data[2 * 4 + 0] = 25; |
| 194 drawnData.data[2 * 4 + 1] = 65; |
| 195 drawnData.data[2 * 4 + 2] = 255; |
| 196 drawnData.data[2 * 4 + 3] = 255; |
| 197 |
| 198 // Draw these pixels to the 8th pixel. |
| 199 drawnData.data[7 * 4 + 0] = 25; |
| 200 drawnData.data[7 * 4 + 1] = 65; |
| 201 drawnData.data[7 * 4 + 2] = 255; |
| 202 drawnData.data[7 * 4 + 3] = 255; |
| 203 |
| 204 // Use a dirty rectangle to limit what pixels are drawn. |
| 205 context.putImageData(drawnData, 0, 0, 1, 0, 5, 5); |
| 206 |
| 207 // Expect the data to be all green, as we skip all drawn pixels. |
| 208 ImageData expectedData = context.createImageData(10, 10); |
| 209 for (int i = 0; i < expectedData.data.length; i++) { |
| 210 switch (i % 4) { |
| 211 case 0: |
| 212 expectedData.data[i] = 0; |
| 213 break; |
| 214 case 1: |
| 215 expectedData.data[i] = 128; |
| 216 break; |
| 217 case 2: |
| 218 expectedData.data[i] = 0; |
| 219 break; |
| 220 case 3: |
| 221 expectedData.data[i] = 255; |
| 222 break; |
| 223 } |
| 224 } |
| 225 // Third pixel was copied. |
| 226 expectedData.data[2 * 4 + 0] = 25; |
| 227 expectedData.data[2 * 4 + 1] = 65; |
| 228 expectedData.data[2 * 4 + 2] = 255; |
| 229 expectedData.data[2 * 4 + 3] = 255; |
| 230 |
| 231 // Make sure that our data is all green. |
| 232 var resultingData = context.getImageData(0, 0, 10, 10); |
| 233 expect(resultingData.data, expectedData.data); |
| 234 }); |
| 235 |
| 236 test('putImageData throws with wrong number of arguments', () { |
| 237 ImageData expectedData = context.getImageData(0, 0, 10, 10); |
| 238 |
| 239 // TODO(antonm): in Dartium ArgumentError should be thrown too. |
| 240 expect(() => context.putImageData(expectedData, 0, 0, 1), |
| 241 throws); |
| 242 expect(() => context.putImageData(expectedData, 0, 0, 1, 1), |
| 243 throws); |
| 244 expect(() => context.putImageData(expectedData, 0, 0, 1, 1, 5), |
| 245 throws); |
| 246 }); |
| 247 }); |
| 248 |
| 249 group('arc', () { |
| 250 setUp(setupFunc); |
| 251 tearDown(tearDownFunc); |
| 252 |
| 253 test('default arc should be clockwise', () { |
| 254 context.beginPath(); |
| 255 final r = 10; |
| 256 |
| 257 // Center of arc. |
| 258 final cx = 20; |
| 259 final cy = 20; |
| 260 // Arc centered at (20, 20) with radius 10 will go clockwise |
| 261 // from (20 + r, 20) to (20, 20 + r), which is 1/4 of a circle. |
| 262 context.arc(cx, cy, r, 0, PI/2); |
| 263 |
| 264 context.strokeStyle = 'green'; |
| 265 context.lineWidth = 2; |
| 266 context.stroke(); |
| 267 |
| 268 // Center should not be filled. |
| 269 expectPixelUnfilled(cx, cy); |
| 270 |
| 271 // (cx + r, cy) should be filled. |
| 272 expectPixelFilled(cx + r, cy, true); |
| 273 // (cx, cy + r) should be filled. |
| 274 expectPixelFilled(cx, cy + r, true); |
| 275 // (cx - r, cy) should be empty. |
| 276 expectPixelFilled(cx - r, cy, false); |
| 277 // (cx, cy - r) should be empty. |
| 278 expectPixelFilled(cx, cy - r, false); |
| 279 |
| 280 // (cx + r/SQRT2, cy + r/SQRT2) should be filled. |
| 281 expectPixelFilled((cx + r/SQRT2).toInt(), (cy + r/SQRT2).toInt(), true); |
| 282 |
| 283 // (cx - r/SQRT2, cy - r/SQRT2) should be empty. |
| 284 expectPixelFilled((cx - r/SQRT2).toInt(), (cy + r/SQRT2).toInt(), false); |
| 285 |
| 286 // (cx + r/SQRT2, cy + r/SQRT2) should be empty. |
| 287 expectPixelFilled((cx - r/SQRT2).toInt(), (cy - r/SQRT2).toInt(), false); |
| 288 |
| 289 // (cx - r/SQRT2, cy - r/SQRT2) should be empty. |
| 290 expectPixelFilled((cx + r/SQRT2).toInt(), (cy - r/SQRT2).toInt(), false); |
| 291 }); |
| 292 |
| 293 test('arc anticlockwise', () { |
| 294 context.beginPath(); |
| 295 final r = 10; |
| 296 |
| 297 // Center of arc. |
| 298 final cx = 20; |
| 299 final cy = 20; |
| 300 // Arc centered at (20, 20) with radius 10 will go anticlockwise |
| 301 // from (20 + r, 20) to (20, 20 + r), which is 3/4 of a circle. |
| 302 // Because of the way arc work, when going anti-clockwise, the end points |
| 303 // are not included, so small values are added to radius to make a little |
| 304 // more than a 3/4 circle. |
| 305 context.arc(cx, cy, r, .1, PI/2 - .1, true); |
| 306 |
| 307 context.strokeStyle = 'green'; |
| 308 context.lineWidth = 2; |
| 309 context.stroke(); |
| 310 |
| 311 // Center should not be filled. |
| 312 expectPixelUnfilled(cx, cy); |
| 313 |
| 314 // (cx + r, cy) should be filled. |
| 315 expectPixelFilled(cx + r, cy, true); |
| 316 // (cx, cy + r) should be filled. |
| 317 expectPixelFilled(cx, cy + r, true); |
| 318 // (cx - r, cy) should be filled. |
| 319 expectPixelFilled(cx - r, cy, true); |
| 320 // (cx, cy - r) should be filled. |
| 321 expectPixelFilled(cx, cy - r, true); |
| 322 |
| 323 // (cx + r/SQRT2, cy + r/SQRT2) should be empty. |
| 324 expectPixelFilled((cx + r/SQRT2).toInt(), (cy + r/SQRT2).toInt(), false); |
| 325 |
| 326 // (cx - r/SQRT2, cy - r/SQRT2) should be filled. |
| 327 expectPixelFilled((cx - r/SQRT2).toInt(), (cy + r/SQRT2).toInt(), true); |
| 328 |
| 329 // (cx + r/SQRT2, cy + r/SQRT2) should be filled. |
| 330 expectPixelFilled((cx - r/SQRT2).toInt(), (cy - r/SQRT2).toInt(), true); |
| 331 |
| 332 // (cx - r/SQRT2, cy - r/SQRT2) should be filled. |
| 333 expectPixelFilled((cx + r/SQRT2).toInt(), (cy - r/SQRT2).toInt(), true); |
| 334 }); |
| 335 }); |
| 336 |
| 337 group('drawImage_image_element', () { |
| 338 setUp(setupFunc); |
| 339 tearDown(tearDownFunc); |
| 340 // Draw an image to the canvas from an image element. |
| 341 test('with 3 params', () { |
| 342 var dataUrl = otherCanvas.toDataUrl('image/gif'); |
| 343 var img = new ImageElement(); |
| 344 |
| 345 img.onLoad.listen(expectAsync((_) { |
| 346 context.drawImage(img, 50, 50); |
| 347 |
| 348 expectPixelFilled(50, 50); |
| 349 expectPixelFilled(55, 55); |
| 350 expectPixelFilled(59, 59); |
| 351 expectPixelUnfilled(60, 60); |
| 352 expectPixelUnfilled(0, 0); |
| 353 expectPixelUnfilled(70, 70); |
| 354 })); |
| 355 img.onError.listen((_) { |
| 356 fail('URL failed to load.'); |
| 357 }); |
| 358 img.src = dataUrl; |
| 359 }); |
| 360 |
| 361 // Draw an image to the canvas from an image element and scale it. |
| 362 test('with 5 params', () { |
| 363 var dataUrl = otherCanvas.toDataUrl('image/gif'); |
| 364 var img = new ImageElement(); |
| 365 |
| 366 img.onLoad.listen(expectAsync((_) { |
| 367 context.drawImageToRect(img, new Rectangle(50, 50, 20, 20)); |
| 368 |
| 369 expectPixelFilled(50, 50); |
| 370 expectPixelFilled(55, 55); |
| 371 expectPixelFilled(59, 59); |
| 372 expectPixelFilled(60, 60); |
| 373 expectPixelFilled(69, 69); |
| 374 expectPixelUnfilled(70, 70); |
| 375 expectPixelUnfilled(0, 0); |
| 376 expectPixelUnfilled(80, 80); |
| 377 })); |
| 378 img.onError.listen((_) { |
| 379 fail('URL failed to load.'); |
| 380 }); |
| 381 img.src = dataUrl; |
| 382 }); |
| 383 |
| 384 // Draw an image to the canvas from an image element and scale it. |
| 385 test('with 9 params', () { |
| 386 otherContext.fillStyle = "blue"; |
| 387 otherContext.fillRect(5, 5, 5, 5); |
| 388 var dataUrl = otherCanvas.toDataUrl('image/gif'); |
| 389 var img = new ImageElement(); |
| 390 |
| 391 img.onLoad.listen(expectAsync((_) { |
| 392 // This will take a 6x6 square from the first canvas from position 2,2 |
| 393 // and then scale it to a 20x20 square and place it to the second |
| 394 // canvas at 50,50. |
| 395 context.drawImageToRect(img, new Rectangle(50, 50, 20, 20), |
| 396 sourceRect: new Rectangle(2, 2, 6, 6)); |
| 397 |
| 398 checkPixel(readPixel(50, 50), [255, 0, 0, 255]); |
| 399 checkPixel(readPixel(55, 55), [255, 0, 0, 255]); |
| 400 checkPixel(readPixel(60, 50), [255, 0, 0, 255]); |
| 401 checkPixel(readPixel(65, 65), [0, 0, 255, 255]); |
| 402 checkPixel(readPixel(69, 69), [0, 0, 255, 255]); |
| 403 |
| 404 expectPixelFilled(50, 50); |
| 405 expectPixelFilled(55, 55); |
| 406 expectPixelFilled(59, 59); |
| 407 expectPixelFilled(60, 60); |
| 408 expectPixelFilled(69, 69); |
| 409 expectPixelUnfilled(70, 70); |
| 410 expectPixelUnfilled(0, 0); |
| 411 expectPixelUnfilled(80, 80); |
| 412 })); |
| 413 img.onError.listen((_) { |
| 414 fail('URL failed to load.'); |
| 415 }); |
| 416 img.src = dataUrl; |
| 417 }); |
| 418 }); |
| 419 |
| 420 // These videos and base64 strings are the same video, representing 2 |
| 421 // frames of 8x8 red pixels. |
| 422 // The videos were created with: |
| 423 // convert -size 8x8 xc:red blank1.jpg |
| 424 // convert -size 8x8 xc:red blank2.jpg |
| 425 // avconv -f image2 -i "blank%d.jpg" -c:v libx264 small.mp4 |
| 426 // avconv -i small.mp4 small.webm |
| 427 // python -m base64 -e small.mp4 |
| 428 // python -m base64 -e small.webm |
| 429 var mp4VideoUrl = '/root_dart/tests/html/small.mp4'; |
| 430 var webmVideoUrl = '/root_dart/tests/html/small.webm'; |
| 431 var mp4VideoDataUrl = |
| 432 'data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAA' |
| 433 'AIZnJlZQAAAsdtZGF0AAACmwYF//+X3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlID' |
| 434 'EyMCByMjE1MSBhM2Y0NDA3IC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZW' |
| 435 'Z0IDIwMDMtMjAxMSAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG' |
| 436 '9wdGlvbnM6IGNhYmFjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweD' |
| 437 'ExMSBtZT1oZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj' |
| 438 '0wIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MCBjcW09MC' |
| 439 'BkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aH' |
| 440 'JlYWRzPTE4IHNsaWNlZF90aHJlYWRzPTAgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZW' |
| 441 'Q9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYWluZWRfaW50cmE9MCBiZnJhbWVzPTMgYl' |
| 442 '9weXJhbWlkPTAgYl9hZGFwdD0xIGJfYmlhcz0wIGRpcmVjdD0xIHdlaWdodGI9MCBvcG' |
| 443 'VuX2dvcD0xIHdlaWdodHA9MiBrZXlpbnQ9MjUwIGtleWludF9taW49MjUgc2NlbmVjdX' |
| 444 'Q9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD00MCByYz1jcmYgbWJ0cmVlPT' |
| 445 'EgY3JmPTUxLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IGlwX3' |
| 446 'JhdGlvPTEuMjUgYXE9MToxLjAwAIAAAAARZYiEB//3aoK5/tP9+8yeuIEAAAAHQZoi2P' |
| 447 '/wgAAAAzxtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAAUAABAAABAAAAAAAAAA' |
| 448 'AAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAA' |
| 449 'AAAAAAAAAAAAAAAAAAAAACAAAAGGlvZHMAAAAAEICAgAcAT/////7/AAACUHRyYWsAAA' |
| 450 'BcdGtoZAAAAA8AAAAAAAAAAAAAAAEAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAQAAAA' |
| 451 'AAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAACAAAAAgAAAAAACRlZHRzAAAAHG' |
| 452 'Vsc3QAAAAAAAAAAQAAAFAAAAABAAEAAAAAAchtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAA' |
| 453 'AAAAAZAAAAAlXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSG' |
| 454 'FuZGxlcgAAAAFzbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZg' |
| 455 'AAAAAAAAABAAAADHVybCAAAAABAAABM3N0YmwAAACXc3RzZAAAAAAAAAABAAAAh2F2Yz' |
| 456 'EAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAACAAIAEgAAABIAAAAAAAAAAEAAAAAAAAAAA' |
| 457 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAxYXZjQwFNQAr/4QAYZ01ACuiPyy' |
| 458 '4C2QAAAwABAAADADIPEiUSAQAGaOvAZSyAAAAAGHN0dHMAAAAAAAAAAQAAAAIAAAABAA' |
| 459 'AAFHN0c3MAAAAAAAAAAQAAAAEAAAAYY3R0cwAAAAAAAAABAAAAAgAAAAEAAAAcc3RzYw' |
| 460 'AAAAAAAAABAAAAAQAAAAEAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAK0AAAACwAAAB' |
| 461 'hzdGNvAAAAAAAAAAIAAAAwAAAC5AAAAGB1ZHRhAAAAWG1ldGEAAAAAAAAAIWhkbHIAAA' |
| 462 'AAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAK2lsc3QAAAAjqXRvbwAAABtkYXRhAAAAAQ' |
| 463 'AAAABMYXZmNTMuMjEuMQ=='; |
| 464 var webmVideoDataUrl = |
| 465 'data:video/webm;base64,GkXfowEAAAAAAAAfQoaBAUL3gQFC8oEEQvOBCEKChHdlY' |
| 466 'm1Ch4ECQoWBAhhTgGcBAAAAAAAB/hFNm3RALE27i1OrhBVJqWZTrIHfTbuMU6uEFlSua' |
| 467 '1OsggEsTbuMU6uEHFO7a1OsggHk7AEAAAAAAACkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' |
| 468 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' |
| 469 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' |
| 470 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmAQAAAAAAA' |
| 471 'EEq17GDD0JATYCLTGF2ZjUzLjIxLjFXQYtMYXZmNTMuMjEuMXOkkJatuHwTJ7cvFLSzB' |
| 472 'Smxbp5EiYhAVAAAAAAAABZUrmsBAAAAAAAAR64BAAAAAAAAPteBAXPFgQGcgQAitZyDd' |
| 473 'W5khoVWX1ZQOIOBASPjg4QCYloA4AEAAAAAAAASsIEIuoEIVLCBCFS6gQhUsoEDH0O2d' |
| 474 'QEAAAAAAABZ54EAo72BAACA8AIAnQEqCAAIAABHCIWFiIWEiAICAnWqA/gD+gINTRgA/' |
| 475 'v0hRf/kb+PnRv/I4//8WE8DijI//FRAo5WBACgAsQEAARAQABgAGFgv9AAIAAAcU7trA' |
| 476 'QAAAAAAAA67jLOBALeH94EB8YIBfw=='; |
| 477 group('drawImage_video_element', () { |
| 478 setUp(setupFunc); |
| 479 tearDown(tearDownFunc); |
| 480 |
| 481 test('with 3 params', () { |
| 482 video.onCanPlay.listen(expectAsync((_) { |
| 483 context.drawImage(video, 50, 50); |
| 484 |
| 485 expectPixelFilled(50, 50); |
| 486 expectPixelFilled(54, 54); |
| 487 expectPixelFilled(57, 57); |
| 488 expectPixelUnfilled(58, 58); |
| 489 expectPixelUnfilled(0, 0); |
| 490 expectPixelUnfilled(70, 70); |
| 491 })); |
| 492 |
| 493 video.onError.listen((_) { |
| 494 fail('URL failed to load.'); |
| 495 }); |
| 496 |
| 497 if(video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') { |
| 498 video.src = webmVideoUrl; |
| 499 } else if(video.canPlayType('video/mp4; codecs="avc1.4D401E, mp4a.40.2"', |
| 500 null) != '') { |
| 501 video.src = mp4VideoUrl; |
| 502 } else { |
| 503 window.console.log('Video is not supported on this system.'); |
| 504 } |
| 505 }); |
| 506 |
| 507 test('with 5 params', () { |
| 508 video.onCanPlay.listen(expectAsync((_) { |
| 509 context.drawImageToRect(video, new Rectangle(50, 50, 20, 20)); |
| 510 |
| 511 expectPixelFilled(50, 50); |
| 512 expectPixelFilled(55, 55); |
| 513 expectPixelFilled(59, 59); |
| 514 expectPixelFilled(60, 60); |
| 515 expectPixelFilled(69, 69); |
| 516 expectPixelUnfilled(70, 70); |
| 517 expectPixelUnfilled(0, 0); |
| 518 expectPixelUnfilled(80, 80); |
| 519 })); |
| 520 video.onError.listen((_) { |
| 521 fail('URL failed to load.'); |
| 522 }); |
| 523 |
| 524 if(video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') { |
| 525 video.src = webmVideoUrl; |
| 526 } else if(video.canPlayType('video/mp4; codecs="avc1.4D401E, mp4a.40.2"', |
| 527 null) != '') { |
| 528 video.src = mp4VideoUrl; |
| 529 } else { |
| 530 // TODO(amouravski): Better fallback? |
| 531 window.console.log('Video is not supported on this system.'); |
| 532 } |
| 533 }); |
| 534 |
| 535 test('with 9 params', () { |
| 536 video.onCanPlay.listen(expectAsync((_) { |
| 537 context.drawImageToRect(video, new Rectangle(50, 50, 20, 20), |
| 538 sourceRect: new Rectangle(2, 2, 6, 6)); |
| 539 |
| 540 expectPixelFilled(50, 50); |
| 541 expectPixelFilled(55, 55); |
| 542 expectPixelFilled(59, 59); |
| 543 expectPixelFilled(60, 60); |
| 544 expectPixelFilled(69, 69); |
| 545 expectPixelUnfilled(70, 70); |
| 546 expectPixelUnfilled(0, 0); |
| 547 expectPixelUnfilled(80, 80); |
| 548 })); |
| 549 video.onError.listen((_) { |
| 550 fail('URL failed to load.'); |
| 551 }); |
| 552 |
| 553 if(video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') { |
| 554 video.src = webmVideoUrl; |
| 555 } else if(video.canPlayType('video/mp4; codecs="avc1.4D401E, mp4a.40.2"', |
| 556 null) != '') { |
| 557 video.src = mp4VideoUrl; |
| 558 } else { |
| 559 // TODO(amouravski): Better fallback? |
| 560 window.console.log('Video is not supported on this system.'); |
| 561 } |
| 562 }); |
| 563 }); |
| 564 |
| 565 group('drawImage_video_element_dataUrl', () { |
| 566 setUp(setupFunc); |
| 567 tearDown(tearDownFunc); |
| 568 |
| 569 test('with 9 params', () { |
| 570 video = new VideoElement(); |
| 571 canvas = new CanvasElement(); |
| 572 video.onCanPlay.listen(expectAsync((_) { |
| 573 context.drawImageToRect(video, new Rectangle(50, 50, 20, 20), |
| 574 sourceRect: new Rectangle(2, 2, 6, 6)); |
| 575 |
| 576 expectPixelFilled(50, 50); |
| 577 expectPixelFilled(55, 55); |
| 578 expectPixelFilled(59, 59); |
| 579 expectPixelFilled(60, 60); |
| 580 expectPixelFilled(69, 69); |
| 581 expectPixelUnfilled(70, 70); |
| 582 expectPixelUnfilled(0, 0); |
| 583 expectPixelUnfilled(80, 80); |
| 584 })); |
| 585 video.onError.listen((_) { |
| 586 fail('URL failed to load.'); |
| 587 }); |
| 588 |
| 589 if(video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') { |
| 590 video.src = webmVideoDataUrl; |
| 591 } else if(video.canPlayType('video/mp4; codecs="avc1.4D401E, mp4a.40.2"', |
| 592 null) != '') { |
| 593 video.src = mp4VideoDataUrl; |
| 594 } else { |
| 595 // TODO(amouravski): Better fallback? |
| 596 window.console.log('Video is not supported on this system.'); |
| 597 } |
| 598 }); |
| 599 }); |
| 600 |
| 601 group('drawImage_canvas_element', () { |
| 602 setUp(setupFunc); |
| 603 tearDown(tearDownFunc); |
| 604 |
| 605 test('with 3 params', () { |
| 606 // Draw an image to the canvas from a canvas element. |
| 607 context.drawImage(otherCanvas, 50, 50); |
| 608 |
| 609 expectPixelFilled(50, 50); |
| 610 expectPixelFilled(55, 55); |
| 611 expectPixelFilled(59, 59); |
| 612 expectPixelUnfilled(60, 60); |
| 613 expectPixelUnfilled(0, 0); |
| 614 expectPixelUnfilled(70, 70); |
| 615 }); |
| 616 test('with 5 params', () { |
| 617 // Draw an image to the canvas from a canvas element. |
| 618 context.drawImageToRect(otherCanvas, new Rectangle(50, 50, 20, 20)); |
| 619 |
| 620 expectPixelFilled(50, 50); |
| 621 expectPixelFilled(55, 55); |
| 622 expectPixelFilled(59, 59); |
| 623 expectPixelFilled(60, 60); |
| 624 expectPixelFilled(69, 69); |
| 625 expectPixelUnfilled(70, 70); |
| 626 expectPixelUnfilled(0, 0); |
| 627 expectPixelUnfilled(80, 80); |
| 628 }); |
| 629 test('with 9 params', () { |
| 630 // Draw an image to the canvas from a canvas element. |
| 631 otherContext.fillStyle = "blue"; |
| 632 otherContext.fillRect(5, 5, 5, 5); |
| 633 context.drawImageToRect(otherCanvas, new Rectangle(50, 50, 20, 20), |
| 634 sourceRect: new Rectangle(2, 2, 6, 6)); |
| 635 |
| 636 checkPixel(readPixel(50, 50), [255, 0, 0, 255]); |
| 637 checkPixel(readPixel(55, 55), [255, 0, 0, 255]); |
| 638 checkPixel(readPixel(60, 50), [255, 0, 0, 255]); |
| 639 checkPixel(readPixel(65, 65), [0, 0, 255, 255]); |
| 640 checkPixel(readPixel(69, 69), [0, 0, 255, 255]); |
| 641 expectPixelFilled(50, 50); |
| 642 expectPixelFilled(55, 55); |
| 643 expectPixelFilled(59, 59); |
| 644 expectPixelFilled(60, 60); |
| 645 expectPixelFilled(69, 69); |
| 646 expectPixelUnfilled(70, 70); |
| 647 expectPixelUnfilled(0, 0); |
| 648 expectPixelUnfilled(80, 80); |
| 649 }); |
| 650 |
| 651 test('createImageData', () { |
| 652 var imageData = context.createImageData(15, 15); |
| 653 expect(imageData.width, 15); |
| 654 expect(imageData.height, 15); |
| 655 |
| 656 var other = context.createImageDataFromImageData(imageData); |
| 657 expect(other.width, 15); |
| 658 expect(other.height, 15); |
| 659 }); |
| 660 |
| 661 test('createPattern', () { |
| 662 var pattern = context.createPattern(new CanvasElement(), ''); |
| 663 //var pattern2 = context.createPatternFromImage(new ImageElement(), ''); |
| 664 }); |
| 665 }); |
| 666 |
| 667 group('fillText', () { |
| 668 setUp(setupFunc); |
| 669 tearDown(tearDownFunc); |
| 670 |
| 671 final x = 20; |
| 672 final y = 20; |
| 673 |
| 674 test('without maxWidth', () { |
| 675 context.font = '40pt Garamond'; |
| 676 context.fillStyle = 'blue'; |
| 677 |
| 678 // Draw a blue box. |
| 679 context.fillText('█', x, y); |
| 680 |
| 681 var width = context.measureText('█').width.ceil(); |
| 682 |
| 683 checkPixel(readPixel(x, y), [0, 0, 255, 255]); |
| 684 checkPixel(readPixel(x + 10, y), [0, 0, 255, 255]); |
| 685 |
| 686 expectPixelUnfilled(x - 10, y); |
| 687 expectPixelFilled(x, y); |
| 688 expectPixelFilled(x + 10, y); |
| 689 |
| 690 // The box does not draw after `width` pixels. |
| 691 // Check -2 rather than -1 because this seems |
| 692 // to run into a rounding error on Mac bots. |
| 693 expectPixelFilled(x + width - 2, y); |
| 694 expectPixelUnfilled(x + width + 1, y); |
| 695 }); |
| 696 |
| 697 test('with maxWidth null', () { |
| 698 context.font = '40pt Garamond'; |
| 699 context.fillStyle = 'blue'; |
| 700 |
| 701 // Draw a blue box with null maxWidth. |
| 702 context.fillText('█', x, y, null); |
| 703 |
| 704 var width = context.measureText('█').width.ceil(); |
| 705 |
| 706 checkPixel(readPixel(x, y), [0, 0, 255, 255]); |
| 707 checkPixel(readPixel(x + 10, y), [0, 0, 255, 255]); |
| 708 |
| 709 expectPixelUnfilled(x - 10, y); |
| 710 expectPixelFilled(x, y); |
| 711 expectPixelFilled(x + 10, y); |
| 712 |
| 713 // The box does not draw after `width` pixels. |
| 714 // Check -2 rather than -1 because this seems |
| 715 // to run into a rounding error on Mac bots. |
| 716 expectPixelFilled(x + width - 2, y); |
| 717 expectPixelUnfilled(x + width + 1, y); |
| 718 }); |
| 719 |
| 720 test('with maxWidth defined', () { |
| 721 context.font = '40pt Garamond'; |
| 722 context.fillStyle = 'blue'; |
| 723 |
| 724 final maxWidth = 20; |
| 725 |
| 726 // Draw a blue box that's at most 20 pixels wide. |
| 727 context.fillText('█', x, y, maxWidth); |
| 728 |
| 729 checkPixel(readPixel(x, y), [0, 0, 255, 255]); |
| 730 checkPixel(readPixel(x + 10, y), [0, 0, 255, 255]); |
| 731 |
| 732 // The box does not draw after 20 pixels. |
| 733 expectPixelUnfilled(x - 10, y); |
| 734 expectPixelUnfilled(x + maxWidth + 1, y); |
| 735 expectPixelUnfilled(x + maxWidth + 20, y); |
| 736 expectPixelFilled(x, y); |
| 737 expectPixelFilled(x + 10, y); |
| 738 }); |
| 739 }); |
| 740 } |
OLD | NEW |