OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library url_test; | 5 library canvas_rendering_context_2d_test; |
6 import '../../pkg/unittest/lib/unittest.dart'; | 6 import '../../pkg/unittest/lib/unittest.dart'; |
7 import '../../pkg/unittest/lib/html_config.dart'; | 7 import '../../pkg/unittest/lib/html_config.dart'; |
8 import 'dart:html'; | 8 import 'dart:html'; |
9 import 'dart:math'; | 9 import 'dart:math'; |
10 | 10 |
11 // Some rounding errors in the browsers. | 11 // Some rounding errors in the browsers. |
12 checkPixel(List<int> pixel, List<int> expected) { | 12 checkPixel(List<int> pixel, List<int> expected) { |
13 expect(pixel[0], closeTo(expected[0], 2)); | 13 expect(pixel[0], closeTo(expected[0], 2)); |
14 expect(pixel[1], closeTo(expected[1], 2)); | 14 expect(pixel[1], closeTo(expected[1], 2)); |
15 expect(pixel[2], closeTo(expected[2], 2)); | 15 expect(pixel[2], closeTo(expected[2], 2)); |
16 expect(pixel[3], closeTo(expected[3], 2)); | 16 expect(pixel[3], closeTo(expected[3], 2)); |
17 } | 17 } |
18 | 18 |
19 main() { | 19 main() { |
20 useHtmlConfiguration(); | 20 useHtmlConfiguration(); |
21 | 21 |
22 group('canvasRenderingContext2d', () { | 22 group('canvasRenderingContext2d', () { |
23 var canvas; | 23 var canvas; |
24 var context; | 24 var context; |
| 25 var otherCanvas; |
| 26 var otherContext; |
| 27 |
| 28 void createOtherCanvas() { |
| 29 otherCanvas = new CanvasElement(); |
| 30 otherCanvas.width = 10; |
| 31 otherCanvas.height = 10; |
| 32 otherContext = otherCanvas.context2d; |
| 33 otherContext.fillStyle = "red"; |
| 34 otherContext.fillRect(0, 0, otherCanvas.width, otherCanvas.height); |
| 35 } |
25 | 36 |
26 setUp(() { | 37 setUp(() { |
27 canvas = new CanvasElement(); | 38 canvas = new CanvasElement(); |
28 canvas.width = 100; | 39 canvas.width = 100; |
29 canvas.height = 100; | 40 canvas.height = 100; |
30 | 41 |
31 context = canvas.context2d; | 42 context = canvas.context2d; |
| 43 |
| 44 createOtherCanvas(); |
32 }); | 45 }); |
33 | 46 |
34 tearDown(() { | 47 tearDown(() { |
35 canvas = null; | 48 canvas = null; |
36 context = null; | 49 context = null; |
| 50 otherCanvas = null; |
| 51 otherContext = null; |
37 }); | 52 }); |
38 | 53 |
39 List<int> readPixel(int x, int y) { | 54 List<int> readPixel(int x, int y) { |
40 var imageData = context.getImageData(x, y, 1, 1); | 55 var imageData = context.getImageData(x, y, 1, 1); |
41 return imageData.data; | 56 return imageData.data; |
42 } | 57 } |
43 | 58 |
44 /// Returns true if the pixel has some data in it, false otherwise. | 59 /// Returns true if the pixel has some data in it, false otherwise. |
45 bool isPixelFilled(int x, int y) => readPixel(x,y).any((p) => p != 0); | 60 bool isPixelFilled(int x, int y) => readPixel(x,y).any((p) => p != 0); |
46 | 61 |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 | 245 |
231 // (cx - r/SQRT2, cy - r/SQRT2) should be filled. | 246 // (cx - r/SQRT2, cy - r/SQRT2) should be filled. |
232 expectPixelFilled((cx - r/SQRT2).toInt(), (cy + r/SQRT2).toInt(), true); | 247 expectPixelFilled((cx - r/SQRT2).toInt(), (cy + r/SQRT2).toInt(), true); |
233 | 248 |
234 // (cx + r/SQRT2, cy + r/SQRT2) should be filled. | 249 // (cx + r/SQRT2, cy + r/SQRT2) should be filled. |
235 expectPixelFilled((cx - r/SQRT2).toInt(), (cy - r/SQRT2).toInt(), true); | 250 expectPixelFilled((cx - r/SQRT2).toInt(), (cy - r/SQRT2).toInt(), true); |
236 | 251 |
237 // (cx - r/SQRT2, cy - r/SQRT2) should be filled. | 252 // (cx - r/SQRT2, cy - r/SQRT2) should be filled. |
238 expectPixelFilled((cx + r/SQRT2).toInt(), (cy - r/SQRT2).toInt(), true); | 253 expectPixelFilled((cx + r/SQRT2).toInt(), (cy - r/SQRT2).toInt(), true); |
239 }); | 254 }); |
| 255 |
| 256 // Draw an image to the canvas from an image element. |
| 257 test('drawImage from img element with 3 params', () { |
| 258 var dataUrl = otherCanvas.toDataUrl('image/gif'); |
| 259 var img = new ImageElement(); |
| 260 |
| 261 img.onLoad.listen(expectAsync1((_) { |
| 262 context.drawImage(img, 50, 50); |
| 263 |
| 264 expectPixelFilled(50, 50); |
| 265 expectPixelFilled(55, 55); |
| 266 expectPixelFilled(59, 59); |
| 267 expectPixelUnfilled(60, 60); |
| 268 expectPixelUnfilled(0, 0); |
| 269 expectPixelUnfilled(70, 70); |
| 270 })); |
| 271 img.onError.listen((_) { |
| 272 guardAsync(() { |
| 273 fail('URL failed to load.'); |
| 274 }); |
| 275 }); |
| 276 img.src = dataUrl; |
| 277 }); |
| 278 |
| 279 // Draw an image to the canvas from an image element and scale it. |
| 280 test('drawImage from img element with 5 params', () { |
| 281 var dataUrl = otherCanvas.toDataUrl('image/gif'); |
| 282 var img = new ImageElement(); |
| 283 |
| 284 img.onLoad.listen(expectAsync1((_) { |
| 285 context.drawImageAtScale(img, new Rect(50, 50, 20, 20)); |
| 286 |
| 287 expectPixelFilled(50, 50); |
| 288 expectPixelFilled(55, 55); |
| 289 expectPixelFilled(59, 59); |
| 290 expectPixelFilled(60, 60); |
| 291 expectPixelFilled(69, 69); |
| 292 expectPixelUnfilled(70, 70); |
| 293 expectPixelUnfilled(0, 0); |
| 294 expectPixelUnfilled(80, 80); |
| 295 })); |
| 296 img.onError.listen((_) { |
| 297 guardAsync(() { |
| 298 fail('URL failed to load.'); |
| 299 }); |
| 300 }); |
| 301 img.src = dataUrl; |
| 302 }); |
| 303 |
| 304 // Draw an image to the canvas from an image element and scale it. |
| 305 test('drawImage from img element with 9 params', () { |
| 306 otherContext.fillStyle = "blue"; |
| 307 otherContext.fillRect(5, 5, 5, 5); |
| 308 var dataUrl = otherCanvas.toDataUrl('image/gif'); |
| 309 var img = new ImageElement(); |
| 310 |
| 311 img.onLoad.listen(expectAsync1((_) { |
| 312 // This will take a 6x6 square from the first canvas from position 2,2 |
| 313 // and then scale it to a 20x20 square and place it to the second canvas |
| 314 // at 50,50. |
| 315 context.drawImageAtScale(img, new Rect(50, 50, 20, 20), |
| 316 sourceRect: new Rect(2, 2, 6, 6)); |
| 317 |
| 318 checkPixel(readPixel(50, 50), [255, 0, 0, 255]); |
| 319 checkPixel(readPixel(55, 55), [255, 0, 0, 255]); |
| 320 checkPixel(readPixel(60, 50), [255, 0, 0, 255]); |
| 321 checkPixel(readPixel(65, 65), [0, 0, 255, 255]); |
| 322 checkPixel(readPixel(69, 69), [0, 0, 255, 255]); |
| 323 |
| 324 expectPixelFilled(50, 50); |
| 325 expectPixelFilled(55, 55); |
| 326 expectPixelFilled(59, 59); |
| 327 expectPixelFilled(60, 60); |
| 328 expectPixelFilled(69, 69); |
| 329 expectPixelUnfilled(70, 70); |
| 330 expectPixelUnfilled(0, 0); |
| 331 expectPixelUnfilled(80, 80); |
| 332 })); |
| 333 img.onError.listen((_) { |
| 334 guardAsync(() { |
| 335 fail('URL failed to load.'); |
| 336 }); |
| 337 }); |
| 338 img.src = dataUrl; |
| 339 }); |
| 340 |
| 341 // These base64 strings are the same video, representing 2 frames of 8x8 red |
| 342 // pixels. |
| 343 // The videos were created with: |
| 344 // convert -size 8x8 xc:red blank1.jpg |
| 345 // convert -size 8x8 xc:red blank2.jpg |
| 346 // avconv -f image2 -i "blank%d.jpg" -c:v libx264 small.mp4 |
| 347 // python -m base64 -e small.mp4 |
| 348 // avconv -i small.mp4 small.webm |
| 349 // python -m base64 -e small.webm |
| 350 var mp4VideoUrl = |
| 351 'data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZn' |
| 352 'JlZQAAAsdtZGF0AAACmwYF//+X3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDEyMCByMj' |
| 353 'E1MSBhM2Y0NDA3IC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMj' |
| 354 'AxMSAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYm' |
| 355 'FjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibW' |
| 356 'U9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0wIG1lX3JhbmdlPTE2IGNocm' |
| 357 '9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3' |
| 358 'Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aHJlYWRzPTE4IHNsaWNlZF90aHJlYWRzPT' |
| 359 'AgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZWQ9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYW' |
| 360 'luZWRfaW50cmE9MCBiZnJhbWVzPTMgYl9weXJhbWlkPTAgYl9hZGFwdD0xIGJfYmlhcz0wIG' |
| 361 'RpcmVjdD0xIHdlaWdodGI9MCBvcGVuX2dvcD0xIHdlaWdodHA9MiBrZXlpbnQ9MjUwIGtleW' |
| 362 'ludF9taW49MjUgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD00MC' |
| 363 'ByYz1jcmYgbWJ0cmVlPTEgY3JmPTUxLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IH' |
| 364 'Fwc3RlcD00IGlwX3JhdGlvPTEuMjUgYXE9MToxLjAwAIAAAAARZYiEB//3aoK5/tP9+8yeuI' |
| 365 'EAAAAHQZoi2P/wgAAAAzxtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAAUAABAAABAA' |
| 366 'AAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAA' |
| 367 'AAAAAAAAAAAAAAAAAAAAAAAAACAAAAGGlvZHMAAAAAEICAgAcAT/////7/AAACUHRyYWsAAA' |
| 368 'BcdGtoZAAAAA8AAAAAAAAAAAAAAAEAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAA' |
| 369 'AAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAACAAAAAgAAAAAACRlZHRzAAAAHGVsc3QAAA' |
| 370 'AAAAAAAQAAAFAAAAABAAEAAAAAAchtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAAAZAAAAAl' |
| 371 'XEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAFzbW' |
| 372 'luZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybC' |
| 373 'AAAAABAAABM3N0YmwAAACXc3RzZAAAAAAAAAABAAAAh2F2YzEAAAAAAAAAAQAAAAAAAAAAAA' |
| 374 'AAAAAAAAAACAAIAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' |
| 375 'AAAAAY//8AAAAxYXZjQwFNQAr/4QAYZ01ACuiPyy4C2QAAAwABAAADADIPEiUSAQAGaOvAZS' |
| 376 'yAAAAAGHN0dHMAAAAAAAAAAQAAAAIAAAABAAAAFHN0c3MAAAAAAAAAAQAAAAEAAAAYY3R0cw' |
| 377 'AAAAAAAAABAAAAAgAAAAEAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAEAAAABAAAAHHN0c3oAAA' |
| 378 'AAAAAAAAAAAAIAAAK0AAAACwAAABhzdGNvAAAAAAAAAAIAAAAwAAAC5AAAAGB1ZHRhAAAAWG' |
| 379 '1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAK2lsc3QAAAAjqX' |
| 380 'RvbwAAABtkYXRhAAAAAQAAAABMYXZmNTMuMjEuMQ=='; |
| 381 var webmVideoUrl = |
| 382 'data:video/webm;base64,GkXfowEAAAAAAAAfQoaBAUL3gQFC8oEEQvOBCEKChHdlYm1Ch' |
| 383 '4ECQoWBAhhTgGcBAAAAAAAB/hFNm3RALE27i1OrhBVJqWZTrIHfTbuMU6uEFlSua1OsggEsT' |
| 384 'buMU6uEHFO7a1OsggHk7AEAAAAAAACkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' |
| 385 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' |
| 386 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' |
| 387 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmAQAAAAAAAEEq17GDD0JATYCLTGF2ZjUzL' |
| 388 'jIxLjFXQYtMYXZmNTMuMjEuMXOkkJatuHwTJ7cvFLSzBSmxbp5EiYhAVAAAAAAAABZUrmsBA' |
| 389 'AAAAAAAR64BAAAAAAAAPteBAXPFgQGcgQAitZyDdW5khoVWX1ZQOIOBASPjg4QCYloA4AEAA' |
| 390 'AAAAAASsIEIuoEIVLCBCFS6gQhUsoEDH0O2dQEAAAAAAABZ54EAo72BAACA8AIAnQEqCAAIA' |
| 391 'ABHCIWFiIWEiAICAnWqA/gD+gINTRgA/v0hRf/kb+PnRv/I4//8WE8DijI//FRAo5WBACgAs' |
| 392 'QEAARAQABgAGFgv9AAIAAAcU7trAQAAAAAAAA67jLOBALeH94EB8YIBfw=='; |
| 393 |
| 394 test('drawImage from video element with 3 params', () { |
| 395 var video = new VideoElement(); |
| 396 |
| 397 video.onLoadedData.listen(expectAsync1((_) { |
| 398 context.drawImage(video, 50, 50); |
| 399 |
| 400 expectPixelFilled(50, 50); |
| 401 expectPixelFilled(54, 54); |
| 402 expectPixelFilled(57, 57); |
| 403 expectPixelUnfilled(58, 58); |
| 404 expectPixelUnfilled(0, 0); |
| 405 expectPixelUnfilled(70, 70); |
| 406 })); |
| 407 video.onError.listen((_) { |
| 408 guardAsync(() { |
| 409 fail('URL failed to load.'); |
| 410 }); |
| 411 }); |
| 412 |
| 413 if(video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') { |
| 414 video.src = webmVideoUrl; |
| 415 } else if(video.canPlayType('video/mp4; codecs="avc1.4D401E, mp4a.40.2"', |
| 416 null) != '') { |
| 417 video.src = mp4VideoUrl; |
| 418 } else { |
| 419 logMessage('Video is not supported on this system.'); |
| 420 } |
| 421 }); |
| 422 |
| 423 test('drawImage from video element with 5 params', () { |
| 424 var video = new VideoElement(); |
| 425 |
| 426 video.onLoadedData.listen(expectAsync1((_) { |
| 427 context.drawImageAtScale(video, new Rect(50, 50, 20, 20)); |
| 428 |
| 429 expectPixelFilled(50, 50); |
| 430 expectPixelFilled(55, 55); |
| 431 expectPixelFilled(59, 59); |
| 432 expectPixelFilled(60, 60); |
| 433 expectPixelFilled(69, 69); |
| 434 expectPixelUnfilled(70, 70); |
| 435 expectPixelUnfilled(0, 0); |
| 436 expectPixelUnfilled(80, 80); |
| 437 })); |
| 438 video.onError.listen((_) { |
| 439 guardAsync(() { |
| 440 fail('URL failed to load.'); |
| 441 }); |
| 442 }); |
| 443 |
| 444 if(video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') { |
| 445 video.src = webmVideoUrl; |
| 446 } else if(video.canPlayType('video/mp4; codecs="avc1.4D401E, mp4a.40.2"', |
| 447 null) != '') { |
| 448 video.src = mp4VideoUrl; |
| 449 } else { |
| 450 // TODO(amouravski): Better fallback? |
| 451 logMessage('Video is not supported on this system.'); |
| 452 } |
| 453 }); |
| 454 |
| 455 test('drawImage from video element with 9 params', () { |
| 456 var video = new VideoElement(); |
| 457 |
| 458 video.onLoadedData.listen(expectAsync1((_) { |
| 459 context.drawImageAtScale(video, new Rect(50, 50, 20, 20), |
| 460 sourceRect: new Rect(2, 2, 6, 6)); |
| 461 |
| 462 expectPixelFilled(50, 50); |
| 463 expectPixelFilled(55, 55); |
| 464 expectPixelFilled(59, 59); |
| 465 expectPixelFilled(60, 60); |
| 466 expectPixelFilled(69, 69); |
| 467 expectPixelUnfilled(70, 70); |
| 468 expectPixelUnfilled(0, 0); |
| 469 expectPixelUnfilled(80, 80); |
| 470 })); |
| 471 video.onError.listen((_) { |
| 472 guardAsync(() { |
| 473 fail('URL failed to load.'); |
| 474 }); |
| 475 }); |
| 476 |
| 477 if(video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') { |
| 478 video.src = webmVideoUrl; |
| 479 } else if(video.canPlayType('video/mp4; codecs="avc1.4D401E, mp4a.40.2"', |
| 480 null) != '') { |
| 481 video.src = mp4VideoUrl; |
| 482 } else { |
| 483 // TODO(amouravski): Better fallback? |
| 484 logMessage('Video is not supported on this system.'); |
| 485 } |
| 486 }); |
| 487 |
| 488 test('drawImage from canvas element with 3 params', () { |
| 489 // Draw an image to the canvas from a canvas element. |
| 490 context.drawImage(otherCanvas, 50, 50); |
| 491 |
| 492 expectPixelFilled(50, 50); |
| 493 expectPixelFilled(55, 55); |
| 494 expectPixelFilled(59, 59); |
| 495 expectPixelUnfilled(60, 60); |
| 496 expectPixelUnfilled(0, 0); |
| 497 expectPixelUnfilled(70, 70); |
| 498 }); |
| 499 test('drawImage from canvas element with 5 params', () { |
| 500 // Draw an image to the canvas from a canvas element. |
| 501 context.drawImageAtScale(otherCanvas, new Rect(50, 50, 20, 20)); |
| 502 |
| 503 expectPixelFilled(50, 50); |
| 504 expectPixelFilled(55, 55); |
| 505 expectPixelFilled(59, 59); |
| 506 expectPixelFilled(60, 60); |
| 507 expectPixelFilled(69, 69); |
| 508 expectPixelUnfilled(70, 70); |
| 509 expectPixelUnfilled(0, 0); |
| 510 expectPixelUnfilled(80, 80); |
| 511 }); |
| 512 test('drawImage from canvas element with 9 params', () { |
| 513 // Draw an image to the canvas from a canvas element. |
| 514 otherContext.fillStyle = "blue"; |
| 515 otherContext.fillRect(5, 5, 5, 5); |
| 516 context.drawImageAtScale(otherCanvas, new Rect(50, 50, 20, 20), |
| 517 sourceRect: new Rect(2, 2, 6, 6)); |
| 518 |
| 519 checkPixel(readPixel(50, 50), [255, 0, 0, 255]); |
| 520 checkPixel(readPixel(55, 55), [255, 0, 0, 255]); |
| 521 checkPixel(readPixel(60, 50), [255, 0, 0, 255]); |
| 522 checkPixel(readPixel(65, 65), [0, 0, 255, 255]); |
| 523 checkPixel(readPixel(69, 69), [0, 0, 255, 255]); |
| 524 expectPixelFilled(50, 50); |
| 525 expectPixelFilled(55, 55); |
| 526 expectPixelFilled(59, 59); |
| 527 expectPixelFilled(60, 60); |
| 528 expectPixelFilled(69, 69); |
| 529 expectPixelUnfilled(70, 70); |
| 530 expectPixelUnfilled(0, 0); |
| 531 expectPixelUnfilled(80, 80); |
| 532 }); |
240 }); | 533 }); |
241 } | 534 } |
OLD | NEW |