|
312 | 312 | desc: Check that layers are rendered even if not closed.
|
313 | 313 | size: [200, 200]
|
314 | 314 | code: |
|
315 |
| - ctx.fillStyle = 'purple'; |
316 |
| - ctx.fillRect(60, 60, 75, 50); |
317 |
| - ctx.globalAlpha = 0.5; |
| 315 | + {% set ns = namespace(ctx='ctx') %} |
| 316 | + {% if canvas_type == 'worker' %} |
| 317 | + // `transferToImageBitmap` is used to transfer the test result to the |
| 318 | + // worker's parent, but `transferToImageBitmap` can't be called on canvas |
| 319 | + // with unclosed layers. We can however draw to a separate offscreen canvas |
| 320 | + // and write it to the main canvas using `drawImage`. |
| 321 | + const canvas2 = new OffscreenCanvas({{ size[0] }}, {{ size[1] }}); |
| 322 | + const ctx2 = canvas2.getContext('2d'); |
| 323 | + {% set ns.ctx = 'ctx2' %} |
| 324 | + {% endif %} |
318 | 325 |
|
319 |
| - ctx.beginLayer({filter: {name: 'dropShadow', dx: -2, dy: 2}}); |
320 |
| - ctx.fillRect(40, 40, 75, 50); |
321 |
| - ctx.fillStyle = 'grey'; |
322 |
| - ctx.fillRect(50, 50, 75, 50); |
| 326 | + {{ ns.ctx }}.fillStyle = 'purple'; |
| 327 | + {{ ns.ctx }}.fillRect(60, 60, 75, 50); |
| 328 | + {{ ns.ctx }}.globalAlpha = 0.5; |
| 329 | +
|
| 330 | + {{ ns.ctx }}.beginLayer({filter: {name: 'dropShadow', dx: -2, dy: 2}}); |
| 331 | + {{ ns.ctx }}.fillRect(40, 40, 75, 50); |
| 332 | + {{ ns.ctx }}.fillStyle = 'grey'; |
| 333 | + {{ ns.ctx }}.fillRect(50, 50, 75, 50); |
| 334 | +
|
| 335 | + {% if canvas_type == 'worker' %} |
| 336 | + ctx.drawImage(canvas2, 0, 0); |
| 337 | + {% endif %} |
323 | 338 | reference: |
|
324 | 339 | ctx.fillStyle = 'purple';
|
325 | 340 | ctx.fillRect(60, 60, 75, 50);
|
|
336 | 351 | desc: Check that layers are rendered even if not closed.
|
337 | 352 | size: [200, 200]
|
338 | 353 | code: |
|
339 |
| - ctx.fillStyle = 'rgba(0, 0, 255, 1)'; |
340 |
| - ctx.fillRect(60, 60, 75, 50); |
341 |
| - ctx.globalAlpha = 0.5; |
| 354 | + {% set ns = namespace(ctx='ctx') %} |
| 355 | + {% if canvas_type == 'worker' %} |
| 356 | + // `transferToImageBitmap` is used to transfer the test result to the |
| 357 | + // worker's parent, but `transferToImageBitmap` can't be called on canvas |
| 358 | + // with unclosed layers. We can however draw to a separate offscreen canvas |
| 359 | + // and write it to the main canvas using `drawImage`. |
| 360 | + const canvas2 = new OffscreenCanvas({{ size[0] }}, {{ size[1] }}); |
| 361 | + const ctx2 = canvas2.getContext('2d'); |
| 362 | + {% set ns.ctx = 'ctx2' %} |
| 363 | + {% endif %} |
342 | 364 |
|
343 |
| - ctx.beginLayer(); |
344 |
| - ctx.fillStyle = 'rgba(225, 0, 0, 1)'; |
345 |
| - ctx.fillRect(50, 50, 75, 50); |
| 365 | + {{ ns.ctx }}.fillStyle = 'rgba(0, 0, 255, 1)'; |
| 366 | + {{ ns.ctx }}.fillRect(60, 60, 75, 50); |
| 367 | + {{ ns.ctx }}.globalAlpha = 0.5; |
346 | 368 |
|
347 |
| - ctx.beginLayer(); |
348 |
| - ctx.fillStyle = 'rgba(0, 255, 0, 1)'; |
349 |
| - ctx.fillRect(70, 70, 75, 50); |
| 369 | + {{ ns.ctx }}.beginLayer(); |
| 370 | + {{ ns.ctx }}.fillStyle = 'rgba(225, 0, 0, 1)'; |
| 371 | + {{ ns.ctx }}.fillRect(50, 50, 75, 50); |
350 | 372 |
|
351 |
| - ctx.endLayer(); |
352 |
| - // Missing ctx.endLayer() here. |
| 373 | + {{ ns.ctx }}.beginLayer(); |
| 374 | + {{ ns.ctx }}.fillStyle = 'rgba(0, 255, 0, 1)'; |
| 375 | + {{ ns.ctx }}.fillRect(70, 70, 75, 50); |
| 376 | +
|
| 377 | + {{ ns.ctx }}.endLayer(); |
| 378 | + // Missing {{ ns.ctx }}.endLayer() here. |
| 379 | +
|
| 380 | + {% if canvas_type == 'worker' %} |
| 381 | + ctx.drawImage(canvas2, 0, 0); |
| 382 | + {% endif %} |
353 | 383 | reference: |
|
354 | 384 | const canvas1 = document.createElement('canvas');
|
355 | 385 | const ctx1 = canvas1.getContext('2d');
|
|
443 | 473 | canvasType: ['HTMLCanvas']
|
444 | 474 | flush_canvas: canvas.toDataURL();
|
445 | 475 |
|
446 |
| - |
447 |
| -- name: 2d.layer.render-opportunities.transferToImageBitmap |
448 |
| - desc: Checks that transferToImageBitmap flushes and rebuilds the state stack. |
449 |
| - size: [200, 200] |
| 476 | +- name: 2d.layer.transferToImageBitmap |
| 477 | + desc: Check that calling transferToImageBitmap in a layer throws an exception. |
450 | 478 | canvasType: ['OffscreenCanvas', 'Worker']
|
451 | 479 | code: |
|
452 |
| - ctx.fillStyle = 'purple'; |
453 |
| - ctx.fillRect(60, 60, 75, 50); |
454 |
| - ctx.globalAlpha = 0.5; |
455 |
| -
|
456 |
| - ctx.beginLayer({filter: {name: 'dropShadow', dx: -2, dy: 2}}); |
457 |
| - ctx.fillRect(40, 40, 75, 50); |
458 |
| - ctx.fillStyle = 'grey'; |
459 |
| - ctx.fillRect(50, 50, 75, 50); |
460 |
| -
|
461 |
| - // Force a flush and restoration of the state stack. |
462 |
| - // `transferToImageBitmap` clears the frame but preserves render states. |
| 480 | + // `transferToImageBitmap` shouldn't throw on it's own. |
463 | 481 | canvas.transferToImageBitmap();
|
464 |
| -
|
465 |
| - ctx.fillRect(70, 70, 75, 50); |
466 |
| - ctx.fillStyle = 'orange'; |
467 |
| - ctx.fillRect(80, 80, 75, 50); |
468 |
| - ctx.endLayer(); |
469 |
| -
|
470 |
| - ctx.fillRect(80, 40, 75, 50); |
471 |
| - reference: | |
472 |
| - ctx.fillStyle = 'purple'; |
473 |
| - ctx.globalAlpha = 0.5; |
474 |
| -
|
475 |
| - ctx.beginLayer({filter: {name: 'dropShadow', dx: -2, dy: 2}}); |
476 |
| - ctx.fillStyle = 'grey'; |
477 |
| - ctx.fillRect(70, 70, 75, 50); |
478 |
| - ctx.fillStyle = 'orange'; |
479 |
| - ctx.fillRect(80, 80, 75, 50); |
480 |
| - ctx.endLayer(); |
481 |
| -
|
482 |
| - ctx.fillRect(80, 40, 75, 50); |
483 |
| -
|
| 482 | + // Make sure the exception isn't caused by calling the function twice. |
| 483 | + canvas.transferToImageBitmap(); |
| 484 | + // Calling again inside a layer should throw. |
| 485 | + ctx.beginLayer(); |
| 486 | + assert_throws_dom("InvalidStateError", |
| 487 | + () => canvas.transferToImageBitmap()); |
484 | 488 |
|
485 | 489 | - name: 2d.layer.several-complex
|
486 | 490 | desc: >-
|
|
0 commit comments