tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

shadows.yaml (30799B)


      1 - name: 2d.shadow.attributes.shadowBlur.initial
      2  code: |
      3    @assert ctx.shadowBlur === 0;
      4 
      5 - name: 2d.shadow.attributes.shadowBlur.valid
      6  code: |
      7    ctx.shadowBlur = 1;
      8    @assert ctx.shadowBlur === 1;
      9 
     10    ctx.shadowBlur = 0.5;
     11    @assert ctx.shadowBlur === 0.5;
     12 
     13    ctx.shadowBlur = 1e6;
     14    @assert ctx.shadowBlur === 1e6;
     15 
     16    ctx.shadowBlur = 0;
     17    @assert ctx.shadowBlur === 0;
     18 
     19 - name: 2d.shadow.attributes.shadowBlur.invalid
     20  code: |
     21    ctx.shadowBlur = 1;
     22    ctx.shadowBlur = -2;
     23    @assert ctx.shadowBlur === 1;
     24 
     25    ctx.shadowBlur = 1;
     26    ctx.shadowBlur = Infinity;
     27    @assert ctx.shadowBlur === 1;
     28 
     29    ctx.shadowBlur = 1;
     30    ctx.shadowBlur = -Infinity;
     31    @assert ctx.shadowBlur === 1;
     32 
     33    ctx.shadowBlur = 1;
     34    ctx.shadowBlur = NaN;
     35    @assert ctx.shadowBlur === 1;
     36 
     37    ctx.shadowBlur = 1;
     38    ctx.shadowBlur = 'string';
     39    @assert ctx.shadowBlur === 1;
     40 
     41    ctx.shadowBlur = 1;
     42    ctx.shadowBlur = true;
     43    @assert ctx.shadowBlur === 1;
     44 
     45    ctx.shadowBlur = 1;
     46    ctx.shadowBlur = false;
     47    @assert ctx.shadowBlur === 0;
     48 
     49 - name: 2d.shadow.attributes.shadowOffset.initial
     50  code: |
     51    @assert ctx.shadowOffsetX === 0;
     52    @assert ctx.shadowOffsetY === 0;
     53 
     54 - name: 2d.shadow.attributes.shadowOffset.valid
     55  code: |
     56    ctx.shadowOffsetX = 1;
     57    ctx.shadowOffsetY = 2;
     58    @assert ctx.shadowOffsetX === 1;
     59    @assert ctx.shadowOffsetY === 2;
     60 
     61    ctx.shadowOffsetX = 0.5;
     62    ctx.shadowOffsetY = 0.25;
     63    @assert ctx.shadowOffsetX === 0.5;
     64    @assert ctx.shadowOffsetY === 0.25;
     65 
     66    ctx.shadowOffsetX = -0.5;
     67    ctx.shadowOffsetY = -0.25;
     68    @assert ctx.shadowOffsetX === -0.5;
     69    @assert ctx.shadowOffsetY === -0.25;
     70 
     71    ctx.shadowOffsetX = 0;
     72    ctx.shadowOffsetY = 0;
     73    @assert ctx.shadowOffsetX === 0;
     74    @assert ctx.shadowOffsetY === 0;
     75 
     76    ctx.shadowOffsetX = 1e6;
     77    ctx.shadowOffsetY = 1e6;
     78    @assert ctx.shadowOffsetX === 1e6;
     79    @assert ctx.shadowOffsetY === 1e6;
     80 
     81 - name: 2d.shadow.attributes.shadowOffset.invalid
     82  code: |
     83    ctx.shadowOffsetX = 1;
     84    ctx.shadowOffsetY = 2;
     85    ctx.shadowOffsetX = Infinity;
     86    ctx.shadowOffsetY = Infinity;
     87    @assert ctx.shadowOffsetX === 1;
     88    @assert ctx.shadowOffsetY === 2;
     89 
     90    ctx.shadowOffsetX = 1;
     91    ctx.shadowOffsetY = 2;
     92    ctx.shadowOffsetX = -Infinity;
     93    ctx.shadowOffsetY = -Infinity;
     94    @assert ctx.shadowOffsetX === 1;
     95    @assert ctx.shadowOffsetY === 2;
     96 
     97    ctx.shadowOffsetX = 1;
     98    ctx.shadowOffsetY = 2;
     99    ctx.shadowOffsetX = NaN;
    100    ctx.shadowOffsetY = NaN;
    101    @assert ctx.shadowOffsetX === 1;
    102    @assert ctx.shadowOffsetY === 2;
    103 
    104    ctx.shadowOffsetX = 1;
    105    ctx.shadowOffsetY = 2;
    106    ctx.shadowOffsetX = 'string';
    107    ctx.shadowOffsetY = 'string';
    108    @assert ctx.shadowOffsetX === 1;
    109    @assert ctx.shadowOffsetY === 2;
    110 
    111    ctx.shadowOffsetX = 1;
    112    ctx.shadowOffsetY = 2;
    113    ctx.shadowOffsetX = true;
    114    ctx.shadowOffsetY = true;
    115    @assert ctx.shadowOffsetX === 1;
    116    @assert ctx.shadowOffsetY === 1;
    117 
    118    ctx.shadowOffsetX = 1;
    119    ctx.shadowOffsetY = 2;
    120    ctx.shadowOffsetX = false;
    121    ctx.shadowOffsetY = false;
    122    @assert ctx.shadowOffsetX === 0;
    123    @assert ctx.shadowOffsetY === 0;
    124 
    125 - name: 2d.shadow.attributes.shadowColor.initial
    126  code: |
    127    @assert ctx.shadowColor === 'rgba(0, 0, 0, 0)';
    128 
    129 - name: 2d.shadow.attributes.shadowColor.valid
    130  code: |
    131    ctx.shadowColor = 'lime';
    132    @assert ctx.shadowColor === '#00ff00';
    133 
    134    ctx.shadowColor = 'RGBA(0,255, 0,0)';
    135    @assert ctx.shadowColor === 'rgba(0, 255, 0, 0)';
    136 
    137 - name: 2d.shadow.attributes.shadowColor.current.basic
    138  desc: currentColor is computed from the canvas element
    139  canvas_types: ['HtmlCanvas']
    140  code: |
    141    canvas.style.color = '#0f0';
    142    ctx.shadowColor = 'currentColor';
    143    @assert ctx.shadowColor === '#00ff00';
    144 
    145 - name: 2d.shadow.attributes.shadowColor.current.changed
    146  desc: currentColor is computed when the attribute is set, not when it is painted
    147  canvas_types: ['HtmlCanvas']
    148  code: |
    149    canvas.style.color = '#0f0';
    150    ctx.shadowColor = 'currentColor';
    151    canvas.style.color = '#f00';
    152    @assert ctx.shadowColor === '#00ff00';
    153 
    154 - name: 2d.shadow.attributes.shadowColor.current.removed
    155  desc: currentColor is solid black when the canvas element is not in a document
    156  canvas_types: ['HtmlCanvas']
    157  code: |
    158    // Try not to let it undetectably incorrectly pick up opaque-black
    159    // from other parts of the document:
    160    document.documentElement.style.color = '#f00';
    161    document.body.style.color = '#f00';
    162    canvas.style.color = '#f00';
    163 
    164    canvas.remove();
    165    ctx.shadowColor = 'currentColor';
    166    @assert ctx.shadowColor === '#000000';
    167 
    168 - name: 2d.shadow.attributes.shadowColor.invalid
    169  code: |
    170    ctx.shadowColor = '#00ff00';
    171    ctx.shadowColor = 'bogus';
    172    @assert ctx.shadowColor === '#00ff00';
    173 
    174    ctx.shadowColor = '#00ff00';
    175    ctx.shadowColor = 'red bogus';
    176    @assert ctx.shadowColor === '#00ff00';
    177 
    178    ctx.shadowColor = '#00ff00';
    179    ctx.shadowColor = ctx;
    180    @assert ctx.shadowColor === '#00ff00';
    181 
    182    ctx.shadowColor = '#00ff00';
    183    ctx.shadowColor = undefined;
    184    @assert ctx.shadowColor === '#00ff00';
    185 
    186 - name: 2d.shadow.enable.off.1
    187  desc: Shadows are not drawn when only shadowColor is set
    188  code: |
    189    ctx.shadowColor = '#f00';
    190    ctx.fillStyle = '#0f0';
    191    ctx.fillRect(0, 0, 100, 50);
    192    @assert pixel 50,25 == 0,255,0,255;
    193  expected: green
    194 
    195 - name: 2d.shadow.enable.off.2
    196  desc: Shadows are not drawn when only shadowColor is set
    197  code: |
    198    ctx.globalCompositeOperation = 'destination-atop';
    199    ctx.shadowColor = '#f00';
    200    ctx.fillStyle = '#0f0';
    201    ctx.fillRect(0, 0, 100, 50);
    202    @assert pixel 50,25 == 0,255,0,255;
    203  expected: green
    204 
    205 - name: 2d.shadow.enable.blur
    206  desc: Shadows are drawn if shadowBlur is set
    207  code: |
    208    ctx.globalCompositeOperation = 'destination-atop';
    209    ctx.shadowColor = '#0f0';
    210    ctx.shadowBlur = 0.1;
    211    ctx.fillStyle = '#f00';
    212    ctx.fillRect(0, 0, 100, 50);
    213    @assert pixel 50,25 == 0,255,0,255;
    214  expected: green
    215 
    216 - name: 2d.shadow.enable.x
    217  desc: Shadows are drawn if shadowOffsetX is set
    218  code: |
    219    ctx.globalCompositeOperation = 'destination-atop';
    220    ctx.shadowColor = '#0f0';
    221    ctx.shadowOffsetX = 0.1;
    222    ctx.fillStyle = '#f00';
    223    ctx.fillRect(0, 0, 100, 50);
    224    @assert pixel 50,25 == 0,255,0,255;
    225  expected: green
    226 
    227 - name: 2d.shadow.enable.y
    228  desc: Shadows are drawn if shadowOffsetY is set
    229  code: |
    230    ctx.globalCompositeOperation = 'destination-atop';
    231    ctx.shadowColor = '#0f0';
    232    ctx.shadowOffsetY = 0.1;
    233    ctx.fillStyle = '#f00';
    234    ctx.fillRect(0, 0, 100, 50);
    235    @assert pixel 50,25 == 0,255,0,255;
    236  expected: green
    237 
    238 - name: 2d.shadow.offset.positiveX
    239  desc: Shadows can be offset with positive x
    240  code: |
    241    ctx.fillStyle = '#f00';
    242    ctx.fillRect(0, 0, 100, 50);
    243    ctx.fillStyle = '#0f0';
    244    ctx.shadowColor = '#0f0';
    245    ctx.shadowOffsetX = 50;
    246    ctx.fillRect(0, 0, 50, 50);
    247    @assert pixel 25,25 == 0,255,0,255;
    248    @assert pixel 75,25 == 0,255,0,255;
    249  expected: green
    250 
    251 - name: 2d.shadow.offset.negativeX
    252  desc: Shadows can be offset with negative x
    253  code: |
    254    ctx.fillStyle = '#f00';
    255    ctx.fillRect(0, 0, 100, 50);
    256    ctx.fillStyle = '#0f0';
    257    ctx.shadowColor = '#0f0';
    258    ctx.shadowOffsetX = -50;
    259    ctx.fillRect(50, 0, 50, 50);
    260    @assert pixel 25,25 == 0,255,0,255;
    261    @assert pixel 75,25 == 0,255,0,255;
    262  expected: green
    263 
    264 - name: 2d.shadow.offset.positiveY
    265  desc: Shadows can be offset with positive y
    266  code: |
    267    ctx.fillStyle = '#f00';
    268    ctx.fillRect(0, 0, 100, 50);
    269    ctx.fillStyle = '#0f0';
    270    ctx.shadowColor = '#0f0';
    271    ctx.shadowOffsetY = 25;
    272    ctx.fillRect(0, 0, 100, 25);
    273    @assert pixel 50,12 == 0,255,0,255;
    274    @assert pixel 50,37 == 0,255,0,255;
    275  expected: green
    276 
    277 - name: 2d.shadow.offset.negativeY
    278  desc: Shadows can be offset with negative y
    279  code: |
    280    ctx.fillStyle = '#f00';
    281    ctx.fillRect(0, 0, 100, 50);
    282    ctx.fillStyle = '#0f0';
    283    ctx.shadowColor = '#0f0';
    284    ctx.shadowOffsetY = -25;
    285    ctx.fillRect(0, 25, 100, 25);
    286    @assert pixel 50,12 == 0,255,0,255;
    287    @assert pixel 50,37 == 0,255,0,255;
    288  expected: green
    289 
    290 - name: 2d.shadow.outside
    291  desc: Shadows of shapes outside the visible area can be offset onto the visible
    292    area
    293  code: |
    294    ctx.fillStyle = '#f00';
    295    ctx.fillRect(0, 0, 100, 50);
    296    ctx.shadowColor = '#0f0';
    297    ctx.shadowOffsetX = 100;
    298    ctx.fillRect(-100, 0, 25, 50);
    299    ctx.shadowOffsetX = -100;
    300    ctx.fillRect(175, 0, 25, 50);
    301    ctx.shadowOffsetX = 0;
    302    ctx.shadowOffsetY = 100;
    303    ctx.fillRect(25, -100, 50, 25);
    304    ctx.shadowOffsetY = -100;
    305    ctx.fillRect(25, 125, 50, 25);
    306    @assert pixel 12,25 == 0,255,0,255;
    307    @assert pixel 87,25 == 0,255,0,255;
    308    @assert pixel 50,12 == 0,255,0,255;
    309    @assert pixel 50,37 == 0,255,0,255;
    310  expected: green
    311 
    312 - name: 2d.shadow.clip.1
    313  desc: Shadows of clipped shapes are still drawn within the clipping region
    314  code: |
    315    ctx.fillStyle = '#0f0';
    316    ctx.fillRect(0, 0, 50, 50);
    317    ctx.fillStyle = '#f00';
    318    ctx.fillRect(50, 0, 50, 50);
    319 
    320    ctx.save();
    321    ctx.beginPath();
    322    ctx.rect(50, 0, 50, 50);
    323    ctx.clip();
    324    ctx.shadowColor = '#0f0';
    325    ctx.shadowOffsetX = 50;
    326    ctx.fillRect(0, 0, 50, 50);
    327    ctx.restore();
    328 
    329    @assert pixel 25,25 == 0,255,0,255;
    330    @assert pixel 75,25 == 0,255,0,255;
    331  expected: green
    332 
    333 - name: 2d.shadow.clip.2
    334  desc: Shadows are not drawn outside the clipping region
    335  code: |
    336    ctx.fillStyle = '#f00';
    337    ctx.fillRect(0, 0, 50, 50);
    338    ctx.fillStyle = '#0f0';
    339    ctx.fillRect(50, 0, 50, 50);
    340 
    341    ctx.save();
    342    ctx.beginPath();
    343    ctx.rect(0, 0, 50, 50);
    344    ctx.clip();
    345    ctx.shadowColor = '#f00';
    346    ctx.shadowOffsetX = 50;
    347    ctx.fillRect(0, 0, 50, 50);
    348    ctx.restore();
    349 
    350    @assert pixel 25,25 == 0,255,0,255;
    351    @assert pixel 75,25 == 0,255,0,255;
    352  expected: green
    353 
    354 - name: 2d.shadow.clip.3
    355  desc: Shadows of clipped shapes are still drawn within the clipping region
    356  code: |
    357    ctx.fillStyle = '#f00';
    358    ctx.fillRect(0, 0, 50, 50);
    359    ctx.fillStyle = '#0f0';
    360    ctx.fillRect(50, 0, 50, 50);
    361 
    362    ctx.save();
    363    ctx.beginPath();
    364    ctx.rect(0, 0, 50, 50);
    365    ctx.clip();
    366    ctx.fillStyle = '#f00';
    367    ctx.shadowColor = '#0f0';
    368    ctx.shadowOffsetX = 50;
    369    ctx.fillRect(-50, 0, 50, 50);
    370    ctx.restore();
    371 
    372    @assert pixel 25,25 == 0,255,0,255;
    373    @assert pixel 75,25 == 0,255,0,255;
    374  expected: green
    375 
    376 - name: 2d.shadow.stroke.basic
    377  desc: Shadows are drawn for strokes
    378  code: |
    379    ctx.fillStyle = '#f00';
    380    ctx.fillRect(0, 0, 100, 50);
    381    ctx.strokeStyle = '#f00';
    382    ctx.shadowColor = '#0f0';
    383    ctx.shadowOffsetY = 50;
    384    ctx.beginPath();
    385    ctx.lineWidth = 50;
    386    ctx.moveTo(0, -25);
    387    ctx.lineTo(100, -25);
    388    ctx.stroke();
    389 
    390    @assert pixel 1,25 == 0,255,0,255;
    391    @assert pixel 50,25 == 0,255,0,255;
    392    @assert pixel 98,25 == 0,255,0,255;
    393  expected: green
    394 
    395 - name: 2d.shadow.stroke.cap.1
    396  desc: Shadows are not drawn for areas outside stroke caps
    397  code: |
    398    ctx.fillStyle = '#0f0';
    399    ctx.fillRect(0, 0, 100, 50);
    400    ctx.strokeStyle = '#f00';
    401    ctx.shadowColor = '#f00';
    402    ctx.shadowOffsetY = 50;
    403    ctx.beginPath();
    404    ctx.lineWidth = 50;
    405    ctx.lineCap = 'butt';
    406    ctx.moveTo(-50, -25);
    407    ctx.lineTo(0, -25);
    408    ctx.moveTo(100, -25);
    409    ctx.lineTo(150, -25);
    410    ctx.stroke();
    411 
    412    @assert pixel 1,25 == 0,255,0,255;
    413    @assert pixel 50,25 == 0,255,0,255;
    414    @assert pixel 98,25 == 0,255,0,255;
    415  expected: green
    416 
    417 - name: 2d.shadow.stroke.cap.2
    418  desc: Shadows are drawn for stroke caps
    419  code: |
    420    ctx.fillStyle = '#f00';
    421    ctx.fillRect(0, 0, 100, 50);
    422    ctx.strokeStyle = '#f00';
    423    ctx.shadowColor = '#0f0';
    424    ctx.shadowOffsetY = 50;
    425    ctx.beginPath();
    426    ctx.lineWidth = 50;
    427    ctx.lineCap = 'square';
    428    ctx.moveTo(25, -25);
    429    ctx.lineTo(75, -25);
    430    ctx.stroke();
    431 
    432    @assert pixel 1,25 == 0,255,0,255;
    433    @assert pixel 50,25 == 0,255,0,255;
    434    @assert pixel 98,25 == 0,255,0,255;
    435  expected: green
    436 
    437 - name: 2d.shadow.stroke.join.1
    438  desc: Shadows are not drawn for areas outside stroke joins
    439  code: |
    440    ctx.fillStyle = '#0f0';
    441    ctx.fillRect(0, 0, 100, 50);
    442    ctx.strokeStyle = '#f00';
    443    ctx.shadowColor = '#f00';
    444    ctx.shadowOffsetX = 100;
    445    ctx.lineWidth = 200;
    446    ctx.lineJoin = 'bevel';
    447    ctx.beginPath();
    448    ctx.moveTo(-200, -50);
    449    ctx.lineTo(-150, -50);
    450    ctx.lineTo(-151, -100);
    451    ctx.stroke();
    452 
    453    @assert pixel 1,1 == 0,255,0,255;
    454    @assert pixel 48,48 == 0,255,0,255;
    455    @assert pixel 50,25 == 0,255,0,255;
    456    @assert pixel 98,48 == 0,255,0,255;
    457  expected: green
    458 
    459 - name: 2d.shadow.stroke.join.2
    460  desc: Shadows are drawn for stroke joins
    461  code: |
    462    ctx.fillStyle = '#f00';
    463    ctx.fillRect(0, 0, 50, 50);
    464    ctx.fillStyle = '#0f0';
    465    ctx.fillRect(50, 0, 50, 50);
    466    ctx.strokeStyle = '#f00';
    467    ctx.shadowColor = '#0f0';
    468    ctx.shadowOffsetX = 100;
    469    ctx.lineWidth = 200;
    470    ctx.lineJoin = 'miter';
    471    ctx.beginPath();
    472    ctx.moveTo(-200, -50);
    473    ctx.lineTo(-150, -50);
    474    ctx.lineTo(-151, -100);
    475    ctx.stroke();
    476 
    477    @assert pixel 1,1 == 0,255,0,255;
    478    @assert pixel 48,48 == 0,255,0,255;
    479    @assert pixel 50,25 == 0,255,0,255;
    480    @assert pixel 98,48 == 0,255,0,255;
    481  expected: green
    482 
    483 - name: 2d.shadow.stroke.join.3
    484  desc: Shadows are drawn for stroke joins respecting miter limit
    485  code: |
    486    ctx.fillStyle = '#0f0';
    487    ctx.fillRect(0, 0, 100, 50);
    488    ctx.strokeStyle = '#f00';
    489    ctx.shadowColor = '#f00';
    490    ctx.shadowOffsetX = 100;
    491    ctx.lineWidth = 200;
    492    ctx.lineJoin = 'miter';
    493    ctx.miterLimit = 0.1;
    494    ctx.beginPath();
    495    ctx.moveTo(-200, -50);
    496    ctx.lineTo(-150, -50);
    497    ctx.lineTo(-151, -100); // (not an exact right angle, to avoid some other bug in Firefox 3)
    498    ctx.stroke();
    499 
    500    @assert pixel 1,1 == 0,255,0,255;
    501    @assert pixel 48,48 == 0,255,0,255;
    502    @assert pixel 50,25 == 0,255,0,255;
    503    @assert pixel 98,48 == 0,255,0,255;
    504  expected: green
    505 
    506 - name: 2d.shadow.image.basic
    507  desc: Shadows are drawn for images
    508  images:
    509  - red.png
    510  code: |
    511    ctx.fillStyle = '#f00';
    512    ctx.fillRect(0, 0, 100, 50);
    513    ctx.shadowColor = '#0f0';
    514    ctx.shadowOffsetY = 50;
    515    {{ load_image }}
    516    ctx.drawImage(img, 0, -50);
    517 
    518    @assert pixel 50,25 == 0,255,0,255;
    519  expected: green
    520  variants: &load-image-variant-definition
    521  - HtmlCanvas:
    522      append_variants_to_name: false
    523      canvas_types: ['HtmlCanvas']
    524      load_image: var img = document.getElementById('{{ images[0] }}');
    525    OffscreenCanvas:
    526      append_variants_to_name: false
    527      canvas_types: ['OffscreenCanvas', 'Worker']
    528      test_type: promise
    529      load_image: |-
    530        var response = await fetch('/images/{{ images[0] }}')
    531        var blob = await response.blob();
    532        var img = await createImageBitmap(blob);
    533 
    534 - name: 2d.shadow.image.transparent.1
    535  desc: Shadows are not drawn for transparent images
    536  images:
    537  - transparent.png
    538  code: |
    539    ctx.fillStyle = '#0f0';
    540    ctx.fillRect(0, 0, 100, 50);
    541    ctx.shadowColor = '#f00';
    542    ctx.shadowOffsetY = 50;
    543    {{ load_image }}
    544    ctx.drawImage(img, 0, -50);
    545 
    546    @assert pixel 50,25 == 0,255,0,255;
    547  expected: green
    548  variants: *load-image-variant-definition
    549 
    550 - name: 2d.shadow.image.transparent.2
    551  desc: Shadows are not drawn for transparent parts of images
    552  images:
    553  - redtransparent.png
    554  code: |
    555    ctx.fillStyle = '#0f0';
    556    ctx.fillRect(0, 0, 50, 50);
    557    ctx.fillStyle = '#f00';
    558    ctx.fillRect(50, 0, 50, 50);
    559    ctx.shadowOffsetY = 50;
    560    ctx.shadowColor = '#0f0';
    561    {{ load_image }}
    562    ctx.drawImage(img, 50, -50);
    563    ctx.shadowColor = '#f00';
    564    ctx.drawImage(img, -50, -50);
    565 
    566    @assert pixel 25,25 == 0,255,0,255;
    567    @assert pixel 50,25 == 0,255,0,255;
    568    @assert pixel 75,25 == 0,255,0,255;
    569  expected: green
    570  variants: *load-image-variant-definition
    571 
    572 - name: 2d.shadow.image.alpha
    573  desc: Shadows are drawn correctly for partially-transparent images
    574  images:
    575  - transparent50.png
    576  code: |
    577    ctx.fillStyle = '#f00';
    578    ctx.fillRect(0, 0, 100, 50);
    579    ctx.shadowOffsetY = 50;
    580    ctx.shadowColor = '#00f';
    581    {{ load_image }}
    582    ctx.drawImage(img, 0, -50);
    583 
    584    @assert pixel 50,25 ==~ 127,0,127,255;
    585  expected: |
    586    size 100 50
    587    cr.set_source_rgb(0.5, 0, 0.5)
    588    cr.rectangle(0, 0, 100, 50)
    589    cr.fill()
    590  variants: *load-image-variant-definition
    591 
    592 - name: 2d.shadow.image.section
    593  desc: Shadows are not drawn for areas outside image source rectangles
    594  images:
    595  - redtransparent.png
    596  code: |
    597    ctx.fillStyle = '#0f0';
    598    ctx.fillRect(0, 0, 100, 50);
    599    ctx.shadowOffsetY = 50;
    600    ctx.shadowColor = '#f00';
    601    {{ load_image }}
    602    ctx.drawImage(img, 50, 0, 50, 50, 0, -50, 50, 50);
    603 
    604    @assert pixel 25,25 ==~ 0,255,0,255;
    605    @assert pixel 50,25 ==~ 0,255,0,255;
    606    @assert pixel 75,25 ==~ 0,255,0,255;
    607  expected: green
    608  variants: *load-image-variant-definition
    609 
    610 - name: 2d.shadow.image.scale
    611  desc: Shadows are drawn correctly for scaled images
    612  images:
    613  - redtransparent.png
    614  code: |
    615    ctx.fillStyle = '#f00';
    616    ctx.fillRect(0, 0, 100, 50);
    617    ctx.shadowOffsetY = 50;
    618    ctx.shadowColor = '#0f0';
    619    {{ load_image }}
    620    ctx.drawImage(img, 0, 0, 100, 50, -10, -50, 240, 50);
    621 
    622    @assert pixel 25,25 ==~ 0,255,0,255;
    623    @assert pixel 50,25 ==~ 0,255,0,255;
    624    @assert pixel 75,25 ==~ 0,255,0,255;
    625  expected: green
    626  variants: *load-image-variant-definition
    627 
    628 - name: 2d.shadow.canvas.basic
    629  desc: Shadows are drawn for canvases
    630  code: |
    631    {{ create_canvas2 }}
    632    var ctx2 = canvas2.getContext('2d');
    633    ctx2.fillStyle = '#f00';
    634    ctx2.fillRect(0, 0, 100, 50);
    635 
    636    ctx.fillStyle = '#f00';
    637    ctx.fillRect(0, 0, 100, 50);
    638    ctx.shadowColor = '#0f0';
    639    ctx.shadowOffsetY = 50;
    640    ctx.drawImage(canvas2, 0, -50);
    641 
    642    @assert pixel 50,25 == 0,255,0,255;
    643  expected: green
    644  variants: &create-canvas2-variant-definition
    645  - HtmlCanvas:
    646      append_variants_to_name: false
    647      canvas_types: ['HtmlCanvas']
    648      create_canvas2: |-
    649        var canvas2 = document.createElement('canvas');
    650        canvas2.width = 100;
    651        canvas2.height = 50;
    652    OffscreenCanvas:
    653      append_variants_to_name: false
    654      canvas_types: ['OffscreenCanvas', 'Worker']
    655      create_canvas2: |-
    656        var canvas2 = new OffscreenCanvas(100, 50);
    657 
    658 - name: 2d.shadow.canvas.transparent.1
    659  desc: Shadows are not drawn for transparent canvases
    660  code: |
    661    {{ create_canvas2 }}
    662    var ctx2 = canvas2.getContext('2d');
    663 
    664    ctx.fillStyle = '#0f0';
    665    ctx.fillRect(0, 0, 100, 50);
    666    ctx.shadowColor = '#f00';
    667    ctx.shadowOffsetY = 50;
    668    ctx.drawImage(canvas2, 0, -50);
    669 
    670    @assert pixel 50,25 == 0,255,0,255;
    671  expected: green
    672  variants: *create-canvas2-variant-definition
    673 
    674 - name: 2d.shadow.canvas.transparent.2
    675  desc: Shadows are not drawn for transparent parts of canvases
    676  code: |
    677    {{ create_canvas2 }}
    678    var ctx2 = canvas2.getContext('2d');
    679    ctx2.fillStyle = '#f00';
    680    ctx2.fillRect(0, 0, 50, 50);
    681 
    682    ctx.fillStyle = '#0f0';
    683    ctx.fillRect(0, 0, 50, 50);
    684    ctx.fillStyle = '#f00';
    685    ctx.fillRect(50, 0, 50, 50);
    686    ctx.shadowOffsetY = 50;
    687    ctx.shadowColor = '#0f0';
    688    ctx.drawImage(canvas2, 50, -50);
    689    ctx.shadowColor = '#f00';
    690    ctx.drawImage(canvas2, -50, -50);
    691 
    692    @assert pixel 25,25 == 0,255,0,255;
    693    @assert pixel 50,25 == 0,255,0,255;
    694    @assert pixel 75,25 == 0,255,0,255;
    695  expected: green
    696  variants: *create-canvas2-variant-definition
    697 
    698 - name: 2d.shadow.canvas.alpha
    699  desc: Shadows are drawn correctly for partially-transparent canvases
    700  code: |
    701    {{ create_canvas2 }}
    702    var ctx2 = canvas2.getContext('2d');
    703    ctx2.fillStyle = 'rgba(255, 0, 0, 0.5)';
    704    ctx2.fillRect(0, 0, 100, 50);
    705 
    706    ctx.fillStyle = '#f00';
    707    ctx.fillRect(0, 0, 100, 50);
    708    ctx.shadowOffsetY = 50;
    709    ctx.shadowColor = '#00f';
    710    ctx.drawImage(canvas2, 0, -50);
    711 
    712    @assert pixel 50,25 ==~ 127,0,127,255;
    713  expected: |
    714    size 100 50
    715    cr.set_source_rgb(0.5, 0, 0.5)
    716    cr.rectangle(0, 0, 100, 50)
    717    cr.fill()
    718  variants: *create-canvas2-variant-definition
    719 
    720 - name: 2d.shadow.pattern.basic
    721  desc: Shadows are drawn for fill patterns
    722  # http://bugs.webkit.org/show_bug.cgi?id=15266
    723  images:
    724  - red.png
    725  code: |
    726    {{ load_image }}
    727    var pattern = ctx.createPattern(img, 'repeat');
    728    ctx.fillStyle = '#f00';
    729    ctx.fillRect(0, 0, 100, 50);
    730    ctx.shadowColor = '#0f0';
    731    ctx.shadowOffsetY = 50;
    732    ctx.fillStyle = pattern;
    733    ctx.fillRect(0, -50, 100, 50);
    734 
    735    @assert pixel 50,25 == 0,255,0,255;
    736  expected: green
    737  variants: *load-image-variant-definition
    738 
    739 - name: 2d.shadow.pattern.transparent.1
    740  desc: Shadows are not drawn for transparent fill patterns
    741  # http://bugs.webkit.org/show_bug.cgi?id=15266
    742  images:
    743  - transparent.png
    744  code: |
    745    {{ load_image }}
    746    var pattern = ctx.createPattern(img, 'repeat');
    747    ctx.fillStyle = '#0f0';
    748    ctx.fillRect(0, 0, 100, 50);
    749    ctx.shadowColor = '#f00';
    750    ctx.shadowOffsetY = 50;
    751    ctx.fillStyle = pattern;
    752    ctx.fillRect(0, -50, 100, 50);
    753 
    754    @assert pixel 50,25 == 0,255,0,255;
    755  expected: green
    756  variants: *load-image-variant-definition
    757 
    758 - name: 2d.shadow.pattern.transparent.2
    759  desc: Shadows are not drawn for transparent parts of fill patterns
    760  # http://bugs.webkit.org/show_bug.cgi?id=15266
    761  images:
    762  - redtransparent.png
    763  code: |
    764    {{ load_image }}
    765    var pattern = ctx.createPattern(img, 'repeat');
    766    ctx.fillStyle = '#f00';
    767    ctx.fillRect(0, 0, 50, 50);
    768    ctx.fillStyle = '#0f0';
    769    ctx.fillRect(50, 0, 50, 50);
    770    ctx.shadowOffsetY = 50;
    771    ctx.shadowColor = '#0f0';
    772    ctx.fillStyle = pattern;
    773    ctx.fillRect(0, -50, 100, 50);
    774 
    775    @assert pixel 25,25 == 0,255,0,255;
    776    @assert pixel 50,25 == 0,255,0,255;
    777    @assert pixel 75,25 == 0,255,0,255;
    778  expected: green
    779  variants: *load-image-variant-definition
    780 
    781 - name: 2d.shadow.pattern.alpha
    782  desc: Shadows are drawn correctly for partially-transparent fill patterns
    783  # http://bugs.webkit.org/show_bug.cgi?id=15266
    784  images:
    785  - transparent50.png
    786  code: |
    787    {{ load_image }}
    788    var pattern = ctx.createPattern(img, 'repeat');
    789    ctx.fillStyle = '#f00';
    790    ctx.fillRect(0, 0, 100, 50);
    791    ctx.shadowOffsetY = 50;
    792    ctx.shadowColor = '#00f';
    793    ctx.fillStyle = pattern;
    794    ctx.fillRect(0, -50, 100, 50);
    795 
    796    @assert pixel 50,25 ==~ 127,0,127,255;
    797  expected: |
    798    size 100 50
    799    cr.set_source_rgb(0.5, 0, 0.5)
    800    cr.rectangle(0, 0, 100, 50)
    801    cr.fill()
    802  variants: *load-image-variant-definition
    803 
    804 - name: 2d.shadow.gradient.basic
    805  desc: Shadows are drawn for gradient fills
    806  # http://bugs.webkit.org/show_bug.cgi?id=15266
    807  code: |
    808    var gradient = ctx.createLinearGradient(0, 0, 100, 0);
    809    gradient.addColorStop(0, '#f00');
    810    gradient.addColorStop(1, '#f00');
    811    ctx.fillStyle = '#f00';
    812    ctx.fillRect(0, 0, 100, 50);
    813    ctx.shadowColor = '#0f0';
    814    ctx.shadowOffsetY = 50;
    815    ctx.fillStyle = gradient;
    816    ctx.fillRect(0, -50, 100, 50);
    817 
    818    @assert pixel 50,25 == 0,255,0,255;
    819  expected: green
    820 
    821 - name: 2d.shadow.gradient.transparent.1
    822  desc: Shadows are not drawn for transparent gradient fills
    823  # http://bugs.webkit.org/show_bug.cgi?id=15266
    824  code: |
    825    var gradient = ctx.createLinearGradient(0, 0, 100, 0);
    826    gradient.addColorStop(0, 'rgba(0,0,0,0)');
    827    gradient.addColorStop(1, 'rgba(0,0,0,0)');
    828    ctx.fillStyle = '#0f0';
    829    ctx.fillRect(0, 0, 100, 50);
    830    ctx.shadowColor = '#f00';
    831    ctx.shadowOffsetY = 50;
    832    ctx.fillStyle = gradient;
    833    ctx.fillRect(0, -50, 100, 50);
    834 
    835    @assert pixel 50,25 == 0,255,0,255;
    836  expected: green
    837 
    838 - name: 2d.shadow.gradient.transparent.2
    839  desc: Shadows are not drawn for transparent parts of gradient fills
    840  # http://bugs.webkit.org/show_bug.cgi?id=15266
    841  code: |
    842    var gradient = ctx.createLinearGradient(0, 0, 100, 0);
    843    gradient.addColorStop(0, '#f00');
    844    gradient.addColorStop(0.499, '#f00');
    845    gradient.addColorStop(0.5, 'rgba(0,0,0,0)');
    846    gradient.addColorStop(1, 'rgba(0,0,0,0)');
    847    ctx.fillStyle = '#f00';
    848    ctx.fillRect(0, 0, 50, 50);
    849    ctx.fillStyle = '#0f0';
    850    ctx.fillRect(50, 0, 50, 50);
    851    ctx.shadowOffsetY = 50;
    852    ctx.shadowColor = '#0f0';
    853    ctx.fillStyle = gradient;
    854    ctx.fillRect(0, -50, 100, 50);
    855 
    856    @assert pixel 25,25 == 0,255,0,255;
    857    @assert pixel 50,25 == 0,255,0,255;
    858    @assert pixel 75,25 == 0,255,0,255;
    859  expected: green
    860 
    861 - name: 2d.shadow.gradient.alpha
    862  desc: Shadows are drawn correctly for partially-transparent gradient fills
    863  # http://bugs.webkit.org/show_bug.cgi?id=15266
    864  code: |
    865    var gradient = ctx.createLinearGradient(0, 0, 100, 0);
    866    gradient.addColorStop(0, 'rgba(255,0,0,0.5)');
    867    gradient.addColorStop(1, 'rgba(255,0,0,0.5)');
    868    ctx.fillStyle = '#f00';
    869    ctx.fillRect(0, 0, 100, 50);
    870    ctx.shadowOffsetY = 50;
    871    ctx.shadowColor = '#00f';
    872    ctx.fillStyle = gradient;
    873    ctx.fillRect(0, -50, 100, 50);
    874 
    875    @assert pixel 50,25 ==~ 127,0,127,255;
    876  expected: |
    877    size 100 50
    878    cr.set_source_rgb(0.5, 0, 0.5)
    879    cr.rectangle(0, 0, 100, 50)
    880    cr.fill()
    881 
    882 - name: 2d.shadow.transform.1
    883  desc: Shadows take account of transformations
    884  code: |
    885    ctx.fillStyle = '#f00';
    886    ctx.fillRect(0, 0, 100, 50);
    887    ctx.shadowOffsetY = 50;
    888    ctx.shadowColor = '#0f0';
    889    ctx.translate(100, 100);
    890    ctx.fillRect(-100, -150, 100, 50);
    891 
    892    @assert pixel 50,25 == 0,255,0,255;
    893  expected: green
    894 
    895 - name: 2d.shadow.transform.2
    896  desc: Shadow offsets are not affected by transformations
    897  code: |
    898    ctx.fillStyle = '#f00';
    899    ctx.fillRect(0, 0, 100, 50);
    900    ctx.shadowOffsetY = 50;
    901    ctx.shadowColor = '#0f0';
    902    ctx.rotate(Math.PI)
    903    ctx.fillRect(-100, 0, 100, 50);
    904 
    905    @assert pixel 50,25 == 0,255,0,255;
    906  expected: green
    907 
    908 - name: 2d.shadow.blur.low
    909  desc: Shadows look correct for small blurs
    910  manual:
    911  code: |
    912    ctx.fillStyle = '#ff0';
    913    ctx.fillRect(0, 0, 100, 50);
    914    ctx.shadowColor = '#00f';
    915    ctx.shadowOffsetY = 25;
    916    for (var x = 0; x < 100; ++x) {
    917        ctx.save();
    918        ctx.beginPath();
    919        ctx.rect(x, 0, 1, 50);
    920        ctx.clip();
    921        ctx.shadowBlur = x;
    922        ctx.fillRect(-200, -200, 500, 200);
    923        ctx.restore();
    924    }
    925  expected: |
    926    size 100 50
    927    import math
    928    cr.set_source_rgb(0, 0, 1)
    929    cr.rectangle(0, 0, 1, 25)
    930    cr.fill()
    931    cr.set_source_rgb(1, 1, 0)
    932    cr.rectangle(0, 25, 1, 25)
    933    cr.fill()
    934    for x in range(1, 100):
    935        sigma = x/2.0
    936        filter = []
    937        for i in range(-24, 26):
    938            filter.append(math.exp(-i*i / (2*sigma*sigma)) / (math.sqrt(2*math.pi)*sigma))
    939        accum = [0]
    940        for f in filter:
    941            accum.append(accum[-1] + f)
    942        for y in range(0, 50):
    943            cr.set_source_rgb(accum[y], accum[y], 1-accum[y])
    944            cr.rectangle(x, y, 1, 1)
    945            cr.fill()
    946 
    947 - name: 2d.shadow.blur.high
    948  desc: Shadows look correct for large blurs
    949  manual:
    950  code: |
    951    ctx.fillStyle = '#ff0';
    952    ctx.fillRect(0, 0, 100, 50);
    953    ctx.shadowColor = '#00f';
    954    ctx.shadowOffsetY = 0;
    955    ctx.shadowBlur = 100;
    956    ctx.fillRect(-200, -200, 200, 400);
    957  expected: |
    958    size 100 50
    959    import math
    960    sigma = 100.0/2
    961    filter = []
    962    for i in range(-200, 100):
    963        filter.append(math.exp(-i*i / (2*sigma*sigma)) / (math.sqrt(2*math.pi)*sigma))
    964    accum = [0]
    965    for f in filter:
    966        accum.append(accum[-1] + f)
    967    for x in range(0, 100):
    968        cr.set_source_rgb(accum[x+200], accum[x+200], 1-accum[x+200])
    969        cr.rectangle(x, 0, 1, 50)
    970        cr.fill()
    971 
    972 - name: 2d.shadow.alpha.1
    973  desc: Shadow color alpha components are used
    974  code: |
    975    ctx.fillStyle = '#0f0';
    976    ctx.fillRect(0, 0, 100, 50);
    977    ctx.shadowColor = 'rgba(255, 0, 0, 0.01)';
    978    ctx.shadowOffsetY = 50;
    979    ctx.fillRect(0, -50, 100, 50);
    980 
    981    @assert pixel 50,25 ==~ 0,255,0,255 +/- 4;
    982  expected: green
    983 
    984 - name: 2d.shadow.alpha.2
    985  desc: Shadow color alpha components are used
    986  code: |
    987    ctx.fillStyle = '#f00';
    988    ctx.fillRect(0, 0, 100, 50);
    989    ctx.shadowColor = 'rgba(0, 0, 255, 0.5)';
    990    ctx.shadowOffsetY = 50;
    991    ctx.fillRect(0, -50, 100, 50);
    992 
    993    @assert pixel 50,25 ==~ 127,0,127,255;
    994  expected: |
    995    size 100 50
    996    cr.set_source_rgb(0.5, 0, 0.5)
    997    cr.rectangle(0, 0, 100, 50)
    998    cr.fill()
    999 
   1000 - name: 2d.shadow.alpha.3
   1001  desc: Shadows are affected by globalAlpha
   1002  code: |
   1003    ctx.fillStyle = '#f00';
   1004    ctx.fillRect(0, 0, 100, 50);
   1005    ctx.fillStyle = '#f00'; // (work around broken Firefox globalAlpha caching)
   1006    ctx.shadowColor = '#00f';
   1007    ctx.shadowOffsetY = 50;
   1008    ctx.globalAlpha = 0.5;
   1009    ctx.fillRect(0, -50, 100, 50);
   1010 
   1011    @assert pixel 50,25 ==~ 127,0,127,255;
   1012  expected: |
   1013    size 100 50
   1014    cr.set_source_rgb(0.5, 0, 0.5)
   1015    cr.rectangle(0, 0, 100, 50)
   1016    cr.fill()
   1017 
   1018 - name: 2d.shadow.alpha.4
   1019  desc: Shadows with alpha components are correctly affected by globalAlpha
   1020  code: |
   1021    ctx.fillStyle = '#f00';
   1022    ctx.fillRect(0, 0, 100, 50);
   1023    ctx.fillStyle = '#f00'; // (work around broken Firefox globalAlpha caching)
   1024    ctx.shadowColor = 'rgba(0, 0, 255, 0.707)';
   1025    ctx.shadowOffsetY = 50;
   1026    ctx.globalAlpha = 0.707;
   1027    ctx.fillRect(0, -50, 100, 50);
   1028 
   1029    @assert pixel 50,25 ==~ 127,0,127,255;
   1030  expected: |
   1031    size 100 50
   1032    cr.set_source_rgb(0.5, 0, 0.5)
   1033    cr.rectangle(0, 0, 100, 50)
   1034    cr.fill()
   1035 
   1036 - name: 2d.shadow.alpha.5
   1037  desc: Shadows of shapes with alpha components are drawn correctly
   1038  code: |
   1039    ctx.fillStyle = '#f00';
   1040    ctx.fillRect(0, 0, 100, 50);
   1041    ctx.fillStyle = 'rgba(64, 0, 0, 0.5)';
   1042    ctx.shadowColor = '#00f';
   1043    ctx.shadowOffsetY = 50;
   1044    ctx.fillRect(0, -50, 100, 50);
   1045 
   1046    @assert pixel 50,25 ==~ 127,0,127,255;
   1047  expected: |
   1048    size 100 50
   1049    cr.set_source_rgb(0.5, 0, 0.5)
   1050    cr.rectangle(0, 0, 100, 50)
   1051    cr.fill()
   1052 
   1053 - name: 2d.shadow.composite.1
   1054  desc: Shadows are drawn using globalCompositeOperation
   1055  code: |
   1056    ctx.fillStyle = '#f00';
   1057    ctx.fillRect(0, 0, 100, 50);
   1058    ctx.globalCompositeOperation = 'xor';
   1059    ctx.shadowColor = '#f00';
   1060    ctx.shadowOffsetX = 100;
   1061    ctx.fillStyle = '#0f0';
   1062    ctx.fillRect(-100, 0, 200, 50);
   1063 
   1064    @assert pixel 50,25 ==~ 0,255,0,255;
   1065  expected: green
   1066 
   1067 - name: 2d.shadow.composite.2
   1068  desc: Shadows are drawn using globalCompositeOperation
   1069  code: |
   1070    ctx.fillStyle = '#f00';
   1071    ctx.fillRect(0, 0, 100, 50);
   1072    ctx.globalCompositeOperation = 'xor';
   1073    ctx.shadowColor = '#f00';
   1074    ctx.shadowBlur = 1;
   1075    ctx.fillStyle = '#0f0';
   1076    ctx.fillRect(-10, -10, 120, 70);
   1077 
   1078    @assert pixel 50,25 ==~ 0,255,0,255;
   1079  expected: green
   1080 
   1081 - name: 2d.shadow.composite.3
   1082  desc: Areas outside shadows are drawn correctly with destination-out
   1083  code: |
   1084    ctx.fillStyle = '#0f0';
   1085    ctx.fillRect(0, 0, 100, 50);
   1086    ctx.globalCompositeOperation = 'destination-out';
   1087    ctx.shadowColor = '#f00';
   1088    ctx.shadowBlur = 10;
   1089    ctx.fillStyle = '#f00';
   1090    ctx.fillRect(200, 0, 100, 50);
   1091 
   1092    @assert pixel 5,5 ==~ 0,255,0,255;
   1093    @assert pixel 50,25 ==~ 0,255,0,255;
   1094  expected: green