tor-browser

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

pixel-manipulation.yaml (43540B)


      1 - name: 2d.imageData.create2.basic
      2  desc: createImageData(sw, sh) exists and returns something
      3  code: |
      4    @assert ctx.createImageData(1, 1) !== null;
      5 
      6 - name: 2d.imageData.create1.basic
      7  desc: createImageData(imgdata) exists and returns something
      8  code: |
      9    @assert ctx.createImageData(ctx.createImageData(1, 1)) !== null;
     10 
     11 - name: 2d.imageData.create2.type
     12  desc: createImageData(sw, sh) returns an ImageData object containing a Uint8ClampedArray
     13    object
     14  canvas_types: ['HtmlCanvas']
     15  code: |
     16    @assert window.ImageData !== undefined;
     17    @assert window.Uint8ClampedArray !== undefined;
     18    window.ImageData.prototype.thisImplementsImageData = true;
     19    window.Uint8ClampedArray.prototype.thisImplementsUint8ClampedArray = true;
     20    var imgdata = ctx.createImageData(1, 1);
     21    @assert imgdata.thisImplementsImageData;
     22    @assert imgdata.data.thisImplementsUint8ClampedArray;
     23 
     24 - name: 2d.imageData.create1.type
     25  desc: createImageData(imgdata) returns an ImageData object containing a Uint8ClampedArray
     26    object
     27  canvas_types: ['HtmlCanvas']
     28  code: |
     29    @assert window.ImageData !== undefined;
     30    @assert window.Uint8ClampedArray !== undefined;
     31    window.ImageData.prototype.thisImplementsImageData = true;
     32    window.Uint8ClampedArray.prototype.thisImplementsUint8ClampedArray = true;
     33    var imgdata = ctx.createImageData(ctx.createImageData(1, 1));
     34    @assert imgdata.thisImplementsImageData;
     35    @assert imgdata.data.thisImplementsUint8ClampedArray;
     36 
     37 - name: 2d.imageData.create2.this
     38  desc: createImageData(sw, sh) should throw when called with the wrong |this|
     39  canvas_types: ['HtmlCanvas']
     40  notes: &bindings Defined in "Web IDL" (draft)
     41  code: |
     42    @assert throws TypeError CanvasRenderingContext2D.prototype.createImageData.call(null, 1, 1); @moz-todo
     43    @assert throws TypeError CanvasRenderingContext2D.prototype.createImageData.call(undefined, 1, 1); @moz-todo
     44    @assert throws TypeError CanvasRenderingContext2D.prototype.createImageData.call({}, 1, 1); @moz-todo
     45 
     46 - name: 2d.imageData.create1.this
     47  desc: createImageData(imgdata) should throw when called with the wrong |this|
     48  canvas_types: ['HtmlCanvas']
     49  notes: *bindings
     50  code: |
     51    var imgdata = ctx.createImageData(1, 1);
     52    @assert throws TypeError CanvasRenderingContext2D.prototype.createImageData.call(null, imgdata); @moz-todo
     53    @assert throws TypeError CanvasRenderingContext2D.prototype.createImageData.call(undefined, imgdata); @moz-todo
     54    @assert throws TypeError CanvasRenderingContext2D.prototype.createImageData.call({}, imgdata); @moz-todo
     55 
     56 - name: 2d.imageData.create2.initial
     57  desc: createImageData(sw, sh) returns transparent black data of the right size
     58  code: |
     59    var imgdata = ctx.createImageData(10, 20);
     60    @assert imgdata.data.length === imgdata.width*imgdata.height*4;
     61    @assert imgdata.width < imgdata.height;
     62    @assert imgdata.width > 0;
     63    var isTransparentBlack = true;
     64    for (var i = 0; i < imgdata.data.length; ++i)
     65        if (imgdata.data[i] !== 0)
     66            isTransparentBlack = false;
     67    @assert isTransparentBlack;
     68 
     69 - name: 2d.imageData.create1.initial
     70  desc: createImageData(imgdata) returns transparent black data of the right size
     71  code: |
     72    ctx.fillStyle = '#0f0';
     73    ctx.fillRect(0, 0, 100, 50);
     74    var imgdata1 = ctx.getImageData(0, 0, 10, 20);
     75    var imgdata2 = ctx.createImageData(imgdata1);
     76    @assert imgdata2.data.length === imgdata1.data.length;
     77    @assert imgdata2.width === imgdata1.width;
     78    @assert imgdata2.height === imgdata1.height;
     79    var isTransparentBlack = true;
     80    for (var i = 0; i < imgdata2.data.length; ++i)
     81        if (imgdata2.data[i] !== 0)
     82            isTransparentBlack = false;
     83    @assert isTransparentBlack;
     84 
     85 - name: 2d.imageData.create2.large
     86  desc: createImageData(sw, sh) works for sizes much larger than the canvas
     87  code: |
     88    var imgdata = ctx.createImageData(1000, 2000);
     89    @assert imgdata.data.length === imgdata.width*imgdata.height*4;
     90    @assert imgdata.width < imgdata.height;
     91    @assert imgdata.width > 0;
     92    var isTransparentBlack = true;
     93    for (var i = 0; i < imgdata.data.length; i += 7813) // check ~1024 points (assuming normal scaling)
     94        if (imgdata.data[i] !== 0)
     95            isTransparentBlack = false;
     96    @assert isTransparentBlack;
     97 
     98 - name: 2d.imageData.create2.negative
     99  desc: createImageData(sw, sh) takes the absolute magnitude of the size arguments
    100  code: |
    101    var imgdata1 = ctx.createImageData(10, 20);
    102    var imgdata2 = ctx.createImageData(-10, 20);
    103    var imgdata3 = ctx.createImageData(10, -20);
    104    var imgdata4 = ctx.createImageData(-10, -20);
    105    @assert imgdata1.data.length === imgdata2.data.length;
    106    @assert imgdata2.data.length === imgdata3.data.length;
    107    @assert imgdata3.data.length === imgdata4.data.length;
    108 
    109 - name: 2d.imageData.create2.zero
    110  desc: createImageData(sw, sh) throws INDEX_SIZE_ERR if size is zero
    111  code: |
    112    @assert throws INDEX_SIZE_ERR ctx.createImageData(10, 0);
    113    @assert throws INDEX_SIZE_ERR ctx.createImageData(0, 10);
    114    @assert throws INDEX_SIZE_ERR ctx.createImageData(0, 0);
    115    @assert throws INDEX_SIZE_ERR ctx.createImageData(0.99, 10);
    116    @assert throws INDEX_SIZE_ERR ctx.createImageData(10, 0.1);
    117 
    118 - name: 2d.imageData.create2.nonfinite
    119  desc: createImageData() throws TypeError if arguments are not finite
    120  notes: *bindings
    121  code: |
    122    @nonfinite @assert throws TypeError ctx.createImageData(<10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>);
    123    var posinfobj = { valueOf: function() { return Infinity; } },
    124        neginfobj = { valueOf: function() { return -Infinity; } },
    125        nanobj = { valueOf: function() { return -Infinity; } };
    126    @nonfinite @assert throws TypeError ctx.createImageData(<10 posinfobj neginfobj nanobj>, <10 posinfobj neginfobj nanobj>);
    127 
    128 - name: 2d.imageData.create1.zero
    129  desc: createImageData(null) throws TypeError
    130  code: |
    131    @assert throws TypeError ctx.createImageData(null);
    132 
    133 - name: 2d.imageData.create2.double
    134  desc: createImageData(w, h) double is converted to long
    135  code: |
    136    var imgdata1 = ctx.createImageData(10.01, 10.99);
    137    var imgdata2 = ctx.createImageData(-10.01, -10.99);
    138    @assert imgdata1.width === 10;
    139    @assert imgdata1.height === 10;
    140    @assert imgdata2.width === 10;
    141    @assert imgdata2.height === 10;
    142 
    143 - name: 2d.imageData.get.double
    144  desc: createImageData(w, h) double is converted to long
    145  code: |
    146    var imgdata1 = ctx.getImageData(0, 0, 10.01, 10.99);
    147    var imgdata2 = ctx.getImageData(0, 0, -10.01, -10.99);
    148    @assert imgdata1.width === 10;
    149    @assert imgdata1.height === 10;
    150    @assert imgdata2.width === 10;
    151    @assert imgdata2.height === 10;
    152 
    153 - name: 2d.imageData.create2.round
    154  desc: createImageData(w, h) is rounded the same as getImageData(0, 0, w, h)
    155  code: |
    156    var imgdata1 = ctx.createImageData(10.01, 10.99);
    157    var imgdata2 = ctx.getImageData(0, 0, 10.01, 10.99);
    158    @assert imgdata1.width === imgdata2.width;
    159    @assert imgdata1.height === imgdata2.height;
    160 
    161 - name: 2d.imageData.createImageBitmap.srgb.rgba.unorm8
    162  desc: Verify round-trip of 8-bit sRGB data ImageData through ImageBitmap
    163  attributes: '{colorSpace: "srgb", colorType:"float16"}'
    164  test_type: promise
    165  code: |
    166    const expectedColor = [ 32, 64, 128, 255 ];
    167    var imageData = new ImageData(10, 10, {colorSpace:"srgb", pixelFormat:"rgba-unorm8"});
    168    for (let y = 0; y < imageData.height; ++y) {
    169      for (let x = 0; x < imageData.width; ++x) {
    170        for (let c = 0; c < 4; ++c) {
    171          imageData.data[4*(x + y*imageData.width) + c] = expectedColor[c];
    172        }
    173      }
    174    }
    175    var bitmap = await createImageBitmap(imageData);
    176    ctx.drawImage(bitmap, 0, 0);
    177    var pixel = ctx.getImageData(0, 0, 1, 1, {colorSpace:"srgb", pixelFormat:"rgba-unorm8"});
    178    for (let c = 0; c < 4; ++c) {
    179      assert_approx_equals(pixel.data[c], expectedColor[c], 2);
    180    }
    181 
    182 - name: 2d.imageData.createImageBitmap.srgb.rgba.float16
    183  desc: Verify round-trip of 16-bit float sRGB data ImageData through ImageBitmap
    184  attributes: '{colorSpace: "srgb", colorType:"float16"}'
    185  test_type: promise
    186  code: |
    187    const expectedColor = [ 1.0, 2.0, -1.0, 1.0 ];
    188    var imageData = new ImageData(10, 10, {colorSpace:"srgb", pixelFormat:"rgba-float16"});
    189    for (let y = 0; y < imageData.height; ++y) {
    190      for (let x = 0; x < imageData.width; ++x) {
    191        for (let c = 0; c < 4; ++c) {
    192          imageData.data[4*(x + y*imageData.width) + c] = expectedColor[c];
    193        }
    194      }
    195    }
    196    var bitmap = await createImageBitmap(imageData);
    197    ctx.drawImage(bitmap, 0, 0);
    198    var pixel = ctx.getImageData(0, 0, 1, 1, {colorSpace:"srgb", pixelFormat:"rgba-float16"});
    199    for (let c = 0; c < 4; ++c) {
    200      assert_approx_equals(pixel.data[c], expectedColor[c], 0.01);
    201    }
    202 
    203 - name: 2d.imageData.createImageBitmap.p3.rgba.unorm8
    204  desc: Verify round-trip of 8-bit P3 data ImageData through ImageBitmap
    205  attributes: '{colorSpace: "srgb", colorType:"float16"}'
    206  test_type: promise
    207  code: |
    208    const expectedColor = [ 255, 0, 0, 255 ];
    209    var imageData = new ImageData(10, 10, {colorSpace:"display-p3", pixelFormat:"rgba-unorm8"});
    210    for (let y = 0; y < imageData.height; ++y) {
    211      for (let x = 0; x < imageData.width; ++x) {
    212        for (let c = 0; c < 4; ++c) {
    213          imageData.data[4*(x + y*imageData.width) + c] = expectedColor[c];
    214        }
    215      }
    216    }
    217    var bitmap = await createImageBitmap(imageData);
    218    ctx.drawImage(bitmap, 0, 0);
    219    var pixel = ctx.getImageData(0, 0, 1, 1, {colorSpace:"display-p3", pixelFormat:"rgba-unorm8"});
    220    for (let c = 0; c < 4; ++c) {
    221      assert_approx_equals(pixel.data[c], expectedColor[c], 2);
    222    }
    223 
    224 - name: 2d.imageData.create.and.resize
    225  desc: Verify no crash when resizing an image bitmap to zero.
    226  canvas_types: ['HtmlCanvas']
    227  images:
    228  - red.png
    229  code: |
    230    var image = new Image();
    231    image.onload = t.step_func(function() {
    232      var options = { resizeHeight: 0 };
    233      var p1 = createImageBitmap(image, options);
    234      p1.catch(function(error){});
    235      t.done();
    236    });
    237    image.src = 'red.png';
    238 
    239 - name: 2d.imageData.get.basic
    240  desc: getImageData() exists and returns something
    241  code: |
    242    @assert ctx.getImageData(0, 0, 100, 50) !== null;
    243 
    244 - name: 2d.imageData.get.type
    245  canvas_types: ['HtmlCanvas']
    246  desc: getImageData() returns an ImageData object containing a Uint8ClampedArray
    247    object
    248  code: |
    249    @assert window.ImageData !== undefined;
    250    @assert window.Uint8ClampedArray !== undefined;
    251    window.ImageData.prototype.thisImplementsImageData = true;
    252    window.Uint8ClampedArray.prototype.thisImplementsUint8ClampedArray = true;
    253    var imgdata = ctx.getImageData(0, 0, 1, 1);
    254    @assert imgdata.thisImplementsImageData;
    255    @assert imgdata.data.thisImplementsUint8ClampedArray;
    256 
    257 - name: 2d.imageData.get.zero
    258  desc: getImageData() throws INDEX_SIZE_ERR if size is zero
    259  code: |
    260    @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, 10, 0);
    261    @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, 0, 10);
    262    @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, 0, 0);
    263    @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, 0.1, 10);
    264    @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, 10, 0.99);
    265    @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, -0.1, 10);
    266    @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, 10, -0.99);
    267 
    268 - name: 2d.imageData.get.nonfinite
    269  desc: getImageData() throws TypeError if arguments are not finite
    270  notes: *bindings
    271  code: |
    272    @nonfinite @assert throws TypeError ctx.getImageData(<10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>);
    273    var posinfobj = { valueOf: function() { return Infinity; } },
    274        neginfobj = { valueOf: function() { return -Infinity; } },
    275        nanobj = { valueOf: function() { return -Infinity; } };
    276    @nonfinite @assert throws TypeError ctx.getImageData(<10 posinfobj neginfobj nanobj>, <10 posinfobj neginfobj nanobj>, <10 posinfobj neginfobj nanobj>, <10 posinfobj neginfobj nanobj>);
    277 
    278 - name: 2d.imageData.get.source.outside
    279  desc: getImageData() returns transparent black outside the canvas
    280  code: |
    281    ctx.fillStyle = '#08f';
    282    ctx.fillRect(0, 0, 100, 50);
    283 
    284    var imgdata1 = ctx.getImageData(-10, 5, 1, 1);
    285    @assert imgdata1.data[0] === 0;
    286    @assert imgdata1.data[1] === 0;
    287    @assert imgdata1.data[2] === 0;
    288    @assert imgdata1.data[3] === 0;
    289 
    290    var imgdata2 = ctx.getImageData(10, -5, 1, 1);
    291    @assert imgdata2.data[0] === 0;
    292    @assert imgdata2.data[1] === 0;
    293    @assert imgdata2.data[2] === 0;
    294    @assert imgdata2.data[3] === 0;
    295 
    296    var imgdata3 = ctx.getImageData(200, 5, 1, 1);
    297    @assert imgdata3.data[0] === 0;
    298    @assert imgdata3.data[1] === 0;
    299    @assert imgdata3.data[2] === 0;
    300    @assert imgdata3.data[3] === 0;
    301 
    302    var imgdata4 = ctx.getImageData(10, 60, 1, 1);
    303    @assert imgdata4.data[0] === 0;
    304    @assert imgdata4.data[1] === 0;
    305    @assert imgdata4.data[2] === 0;
    306    @assert imgdata4.data[3] === 0;
    307 
    308    var imgdata5 = ctx.getImageData(100, 10, 1, 1);
    309    @assert imgdata5.data[0] === 0;
    310    @assert imgdata5.data[1] === 0;
    311    @assert imgdata5.data[2] === 0;
    312    @assert imgdata5.data[3] === 0;
    313 
    314    var imgdata6 = ctx.getImageData(0, 10, 1, 1);
    315    @assert imgdata6.data[0] === 0;
    316    @assert imgdata6.data[1] === 136;
    317    @assert imgdata6.data[2] === 255;
    318    @assert imgdata6.data[3] === 255;
    319 
    320    var imgdata7 = ctx.getImageData(-10, 10, 20, 20);
    321    @assert imgdata7.data[ 0*4+0] === 0;
    322    @assert imgdata7.data[ 0*4+1] === 0;
    323    @assert imgdata7.data[ 0*4+2] === 0;
    324    @assert imgdata7.data[ 0*4+3] === 0;
    325    @assert imgdata7.data[ 9*4+0] === 0;
    326    @assert imgdata7.data[ 9*4+1] === 0;
    327    @assert imgdata7.data[ 9*4+2] === 0;
    328    @assert imgdata7.data[ 9*4+3] === 0;
    329    @assert imgdata7.data[10*4+0] === 0;
    330    @assert imgdata7.data[10*4+1] === 136;
    331    @assert imgdata7.data[10*4+2] === 255;
    332    @assert imgdata7.data[10*4+3] === 255;
    333    @assert imgdata7.data[19*4+0] === 0;
    334    @assert imgdata7.data[19*4+1] === 136;
    335    @assert imgdata7.data[19*4+2] === 255;
    336    @assert imgdata7.data[19*4+3] === 255;
    337    @assert imgdata7.data[20*4+0] === 0;
    338    @assert imgdata7.data[20*4+1] === 0;
    339    @assert imgdata7.data[20*4+2] === 0;
    340    @assert imgdata7.data[20*4+3] === 0;
    341 
    342 - name: 2d.imageData.get.source.negative
    343  desc: getImageData() works with negative width and height, and returns top-to-bottom
    344    left-to-right
    345  code: |
    346    ctx.fillStyle = '#000';
    347    ctx.fillRect(0, 0, 100, 50);
    348    ctx.fillStyle = '#fff';
    349    ctx.fillRect(20, 10, 60, 10);
    350 
    351    var imgdata1 = ctx.getImageData(85, 25, -10, -10);
    352    @assert imgdata1.data[0] === 255;
    353    @assert imgdata1.data[1] === 255;
    354    @assert imgdata1.data[2] === 255;
    355    @assert imgdata1.data[3] === 255;
    356    @assert imgdata1.data[imgdata1.data.length-4+0] === 0;
    357    @assert imgdata1.data[imgdata1.data.length-4+1] === 0;
    358    @assert imgdata1.data[imgdata1.data.length-4+2] === 0;
    359    @assert imgdata1.data[imgdata1.data.length-4+3] === 255;
    360 
    361    var imgdata2 = ctx.getImageData(0, 0, -1, -1);
    362    @assert imgdata2.data[0] === 0;
    363    @assert imgdata2.data[1] === 0;
    364    @assert imgdata2.data[2] === 0;
    365    @assert imgdata2.data[3] === 0;
    366 
    367 - name: 2d.imageData.get.source.size
    368  desc: getImageData() returns bigger ImageData for bigger source rectangle
    369  code: |
    370    var imgdata1 = ctx.getImageData(0, 0, 10, 10);
    371    var imgdata2 = ctx.getImageData(0, 0, 20, 20);
    372    @assert imgdata2.width > imgdata1.width;
    373    @assert imgdata2.height > imgdata1.height;
    374 
    375 - name: 2d.imageData.get.nonpremul
    376  desc: getImageData() returns non-premultiplied colors
    377  code: |
    378    ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
    379    ctx.fillRect(0, 0, 100, 50);
    380    var imgdata = ctx.getImageData(10, 10, 10, 10);
    381    @assert imgdata.data[0] > 200;
    382    @assert imgdata.data[1] > 200;
    383    @assert imgdata.data[2] > 200;
    384    @assert imgdata.data[3] > 100;
    385    @assert imgdata.data[3] < 200;
    386 
    387 - name: 2d.imageData.get.range
    388  desc: getImageData() returns values in the range [0, 255]
    389  code: |
    390    ctx.fillStyle = '#000';
    391    ctx.fillRect(0, 0, 100, 50);
    392    ctx.fillStyle = '#fff';
    393    ctx.fillRect(20, 10, 60, 10);
    394    var imgdata1 = ctx.getImageData(10, 5, 1, 1);
    395    @assert imgdata1.data[0] === 0;
    396    var imgdata2 = ctx.getImageData(30, 15, 1, 1);
    397    @assert imgdata2.data[0] === 255;
    398 
    399 - name: 2d.imageData.get.clamp
    400  desc: getImageData() clamps colors to the range [0, 255]
    401  code: |
    402    ctx.fillStyle = 'rgb(-100, -200, -300)';
    403    ctx.fillRect(0, 0, 100, 50);
    404    ctx.fillStyle = 'rgb(256, 300, 400)';
    405    ctx.fillRect(20, 10, 60, 10);
    406    var imgdata1 = ctx.getImageData(10, 5, 1, 1);
    407    @assert imgdata1.data[0] === 0;
    408    @assert imgdata1.data[1] === 0;
    409    @assert imgdata1.data[2] === 0;
    410    var imgdata2 = ctx.getImageData(30, 15, 1, 1);
    411    @assert imgdata2.data[0] === 255;
    412    @assert imgdata2.data[1] === 255;
    413    @assert imgdata2.data[2] === 255;
    414 
    415 - name: 2d.imageData.get.length
    416  desc: getImageData() returns a correctly-sized Uint8ClampedArray
    417  code: |
    418    var imgdata = ctx.getImageData(0, 0, 10, 10);
    419    @assert imgdata.data.length === imgdata.width*imgdata.height*4;
    420 
    421 - name: 2d.imageData.get.order.cols
    422  desc: getImageData() returns leftmost columns first
    423  code: |
    424    ctx.fillStyle = '#fff';
    425    ctx.fillRect(0, 0, 100, 50);
    426    ctx.fillStyle = '#000';
    427    ctx.fillRect(0, 0, 2, 50);
    428    var imgdata = ctx.getImageData(0, 0, 10, 10);
    429    @assert imgdata.data[0] === 0;
    430    @assert imgdata.data[Math.round(imgdata.width/2*4)] === 255;
    431    @assert imgdata.data[Math.round((imgdata.height/2)*imgdata.width*4)] === 0;
    432 
    433 - name: 2d.imageData.get.order.rows
    434  desc: getImageData() returns topmost rows first
    435  code: |
    436    ctx.fillStyle = '#fff';
    437    ctx.fillRect(0, 0, 100, 50);
    438    ctx.fillStyle = '#000';
    439    ctx.fillRect(0, 0, 100, 2);
    440    var imgdata = ctx.getImageData(0, 0, 10, 10);
    441    @assert imgdata.data[0] === 0;
    442    @assert imgdata.data[Math.floor(imgdata.width/2*4)] === 0;
    443    @assert imgdata.data[(imgdata.height/2)*imgdata.width*4] === 255;
    444 
    445 - name: 2d.imageData.get.order.rgb
    446  desc: getImageData() returns R then G then B
    447  code: |
    448    ctx.fillStyle = '#48c';
    449    ctx.fillRect(0, 0, 100, 50);
    450    var imgdata = ctx.getImageData(0, 0, 10, 10);
    451    @assert imgdata.data[0] === 0x44;
    452    @assert imgdata.data[1] === 0x88;
    453    @assert imgdata.data[2] === 0xCC;
    454    @assert imgdata.data[3] === 255;
    455    @assert imgdata.data[4] === 0x44;
    456    @assert imgdata.data[5] === 0x88;
    457    @assert imgdata.data[6] === 0xCC;
    458    @assert imgdata.data[7] === 255;
    459 
    460 - name: 2d.imageData.get.order.alpha
    461  desc: getImageData() returns A in the fourth component
    462  code: |
    463    ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
    464    ctx.fillRect(0, 0, 100, 50);
    465    var imgdata = ctx.getImageData(0, 0, 10, 10);
    466    @assert imgdata.data[3] < 200;
    467    @assert imgdata.data[3] > 100;
    468 
    469 - name: 2d.imageData.get.unaffected
    470  desc: getImageData() is not affected by context state
    471  code: |
    472    ctx.fillStyle = '#0f0';
    473    ctx.fillRect(0, 0, 50, 50)
    474    ctx.fillStyle = '#f00';
    475    ctx.fillRect(50, 0, 50, 50)
    476    ctx.save();
    477    ctx.translate(50, 0);
    478    ctx.globalAlpha = 0.1;
    479    ctx.globalCompositeOperation = 'destination-atop';
    480    ctx.shadowColor = '#f00';
    481    ctx.rect(0, 0, 5, 5);
    482    ctx.clip();
    483    var imgdata = ctx.getImageData(0, 0, 50, 50);
    484    ctx.restore();
    485    ctx.putImageData(imgdata, 50, 0);
    486    @assert pixel 25,25 ==~ 0,255,0,255;
    487    @assert pixel 75,25 ==~ 0,255,0,255;
    488  expected: green
    489 
    490 - name: 2d.imageData.get.large.crash
    491  desc: Test that canvas crash when image data cannot be allocated.
    492  code: |
    493    @assert throws TypeError ctx.getImageData(10, 0xffffffff, 2147483647, 10);
    494 
    495 - name: 2d.imageData.get.rounding
    496  desc: Test the handling of non-integer source coordinates in getImageData().
    497  code: |
    498    function testDimensions(sx, sy, sw, sh, width, height)
    499    {
    500        imageData = ctx.getImageData(sx, sy, sw, sh);
    501        @assert imageData.width == width;
    502        @assert imageData.height == height;
    503    }
    504 
    505    testDimensions(0, 0, 20, 10, 20, 10);
    506 
    507    testDimensions(.1, .2, 20, 10, 20, 10);
    508    testDimensions(.9, .8, 20, 10, 20, 10);
    509 
    510    testDimensions(0, 0, 20.9, 10.9, 20, 10);
    511    testDimensions(0, 0, 20.1, 10.1, 20, 10);
    512 
    513    testDimensions(-1, -1, 20, 10, 20, 10);
    514 
    515    testDimensions(-1.1, 0, 20, 10, 20, 10);
    516    testDimensions(-1.9,  0, 20, 10, 20, 10);
    517 
    518 - name: 2d.imageData.get.invalid
    519  desc: Verify getImageData() behavior in invalid cases.
    520  code: |
    521    imageData = ctx.getImageData(0,0,2,2);
    522    var testValues = [NaN, true, false, "\"garbage\"", "-1",
    523                      "0", "1", "2", Infinity, -Infinity,
    524                      -5, -0.5, 0, 0.5, 5,
    525                      5.4, 255, 256, null, undefined];
    526    var testResults = [0, 1, 0, 0, 0,
    527                       0, 1, 2, 255, 0,
    528                       0, 0, 0, 0, 5,
    529                       5, 255, 255, 0, 0];
    530    for (var i = 0; i < testValues.length; i++) {
    531        imageData.data[0] = testValues[i];
    532        @assert imageData.data[0] == testResults[i];
    533    }
    534    imageData.data['foo']='garbage';
    535    @assert imageData.data['foo'] == 'garbage';
    536    imageData.data[-1]='garbage';
    537    @assert imageData.data[-1] == undefined;
    538    imageData.data[17]='garbage';
    539    @assert imageData.data[17] == undefined;
    540 
    541 - name: 2d.imageData.object.properties
    542  desc: ImageData objects have the right properties
    543  code: |
    544    var imgdata = ctx.getImageData(0, 0, 10, 10);
    545    @assert typeof(imgdata.width) === 'number';
    546    @assert typeof(imgdata.height) === 'number';
    547    @assert typeof(imgdata.data) === 'object';
    548    @assert typeof(imgdata.colorSpace) === 'string';
    549    @assert typeof(imgdata.pixelFormat) === 'string';
    550 
    551 - name: 2d.imageData.object.readonly
    552  desc: ImageData objects properties are read-only
    553  code: |
    554    var imgdata = ctx.getImageData(0, 0, 10, 10);
    555    var w = imgdata.width;
    556    var h = imgdata.height;
    557    var d = imgdata.data;
    558    imgdata.width = 123;
    559    imgdata.height = 123;
    560    imgdata.data = [100,100,100,100];
    561    @assert imgdata.width === w;
    562    @assert imgdata.height === h;
    563    @assert imgdata.data === d;
    564    @assert imgdata.data[0] === 0;
    565    @assert imgdata.data[1] === 0;
    566    @assert imgdata.data[2] === 0;
    567    @assert imgdata.data[3] === 0;
    568 
    569 - name: 2d.imageData.object.ctor.size
    570  canvas_types: ['HtmlCanvas']
    571  desc: ImageData has a usable constructor
    572  code: |
    573    @assert window.ImageData !== undefined;
    574 
    575    var imgdata = new window.ImageData(2, 3);
    576    @assert imgdata.width === 2;
    577    @assert imgdata.height === 3;
    578    @assert imgdata.data.length === 2 * 3 * 4;
    579    for (var i = 0; i < imgdata.data.length; ++i) {
    580      @assert imgdata.data[i] === 0;
    581    }
    582 
    583 - name: 2d.imageData.object.ctor.basics
    584  canvas_types: ['HtmlCanvas']
    585  desc: Testing different type of ImageData constructor
    586  code: |
    587    function setRGBA(imageData, i, rgba)
    588    {
    589        var s = i * 4;
    590        imageData[s] = rgba[0];
    591        imageData[s + 1] = rgba[1];
    592        imageData[s + 2] = rgba[2];
    593        imageData[s + 3] = rgba[3];
    594    }
    595 
    596    function getRGBA(imageData, i)
    597    {
    598        var result = [];
    599        var s = i * 4;
    600        for (var j = 0; j < 4; j++) {
    601            result[j] = imageData[s + j];
    602        }
    603        return result;
    604    }
    605 
    606    function assertArrayEquals(actual, expected)
    607    {
    608        @assert typeof actual === "object";
    609        @assert actual !== null;
    610        @assert "length" in actual === true;
    611        @assert actual.length === expected.length;
    612        for (var i = 0; i < actual.length; i++) {
    613            @assert actual.hasOwnProperty(i) === expected.hasOwnProperty(i);
    614            @assert actual[i] === expected[i];
    615        }
    616    }
    617 
    618    @assert ImageData !== undefined;
    619    imageData = new ImageData(100, 50);
    620 
    621    @assert imageData !== null;
    622    @assert imageData.data !== null;
    623    @assert imageData.width === 100;
    624    @assert imageData.height === 50;
    625    assertArrayEquals(getRGBA(imageData.data, 4), [0, 0, 0, 0]);
    626 
    627    var testColor = [0, 255, 255, 128];
    628    setRGBA(imageData.data, 4, testColor);
    629    assertArrayEquals(getRGBA(imageData.data, 4), testColor);
    630 
    631    @assert throws TypeError ImageData(1, 1);
    632    @assert throws TypeError new ImageData(10);
    633    @assert throws INDEX_SIZE_ERR new ImageData(0, 10);
    634    @assert throws INDEX_SIZE_ERR new ImageData(10, 0);
    635    @assert throws INDEX_SIZE_ERR new ImageData('width', 'height');
    636    @assert throws INDEX_SIZE_ERR new ImageData(1 << 31, 1 << 31);
    637    @assert throws TypeError new ImageData(new Uint8ClampedArray(0));
    638    @assert throws INDEX_SIZE_ERR new ImageData(new Uint8Array(100), 25);
    639    @assert throws INVALID_STATE_ERR new ImageData(new Uint8ClampedArray(27), 2);
    640    @assert throws INDEX_SIZE_ERR new ImageData(new Uint8ClampedArray(28), 7, 0);
    641    @assert throws INDEX_SIZE_ERR new ImageData(new Uint8ClampedArray(104), 14);
    642    @assert throws INDEX_SIZE_ERR new ImageData(new Uint8ClampedArray([12, 34, 168, 65328]), 1, 151);
    643    @assert throws TypeError new ImageData(self, 4, 4);
    644    @assert throws TypeError new ImageData(null, 4, 4);
    645    @assert throws INDEX_SIZE_ERR new ImageData(imageData.data, 0);
    646    @assert throws INDEX_SIZE_ERR new ImageData(imageData.data, 13);
    647    @assert throws INDEX_SIZE_ERR new ImageData(imageData.data, 1 << 31);
    648    @assert throws INDEX_SIZE_ERR new ImageData(imageData.data, 'biggish');
    649    @assert throws INDEX_SIZE_ERR new ImageData(imageData.data, 1 << 24, 1 << 31);
    650    @assert new ImageData(new Uint8ClampedArray(28), 7).height === 1;
    651 
    652    imageDataFromData = new ImageData(imageData.data, 100);
    653    @assert imageDataFromData.width === 100;
    654    @assert imageDataFromData.height === 50;
    655    @assert imageDataFromData.data === imageData.data;
    656    assertArrayEquals(getRGBA(imageDataFromData.data, 10), getRGBA(imageData.data, 10));
    657    setRGBA(imageData.data, 10, testColor);
    658    assertArrayEquals(getRGBA(imageDataFromData.data, 10), getRGBA(imageData.data, 10));
    659 
    660    var data = new Uint8ClampedArray(400);
    661    data[22] = 129;
    662    imageDataFromData = new ImageData(data, 20, 5);
    663    @assert imageDataFromData.width === 20;
    664    @assert imageDataFromData.height === 5;
    665    @assert imageDataFromData.data === data;
    666    assertArrayEquals(getRGBA(imageDataFromData.data, 2), getRGBA(data, 2));
    667    setRGBA(imageDataFromData.data, 2, testColor);
    668    assertArrayEquals(getRGBA(imageDataFromData.data, 2), getRGBA(data, 2));
    669 
    670    if (window.SharedArrayBuffer) {
    671        @assert throws TypeError new ImageData(new Uint16Array(new SharedArrayBuffer(32)), 4, 2);
    672    }
    673 
    674 - name: 2d.imageData.object.ctor.pixelFormat
    675  canvas_types: ['HtmlCanvas']
    676  desc: Testing ImageData constructor pixelFormat behaviors
    677  code: |
    678    function setRGBA(imageData, i, rgba)
    679    {
    680        var s = i * 4;
    681        imageData[s] = rgba[0];
    682        imageData[s + 1] = rgba[1];
    683        imageData[s + 2] = rgba[2];
    684        imageData[s + 3] = rgba[3];
    685    }
    686 
    687    function getRGBA(imageData, i)
    688    {
    689        var result = [];
    690        var s = i * 4;
    691        for (var j = 0; j < 4; j++) {
    692            result[j] = imageData[s + j];
    693        }
    694        return result;
    695    }
    696 
    697    function assertArrayEquals(actual, expected)
    698    {
    699        @assert typeof actual === "object";
    700        @assert actual !== null;
    701        @assert "length" in actual === true;
    702        @assert actual.length === expected.length;
    703        for (var i = 0; i < actual.length; i++) {
    704            @assert actual.hasOwnProperty(i) === expected.hasOwnProperty(i);
    705            @assert actual[i] === expected[i];
    706        }
    707    }
    708 
    709    @assert ImageData !== undefined;
    710    imageData = new ImageData(100, 50);
    711    @assert imageData.pixelFormat === "rgba-unorm8";
    712 
    713    imageData = new ImageData(100, 50, {pixelFormat:"rgba-float16"});
    714    @assert imageData.pixelFormat === "rgba-float16";
    715    var testColor = [0, -1, 0.5, 1024];
    716    setRGBA(imageData.data, 4, testColor);
    717    assertArrayEquals(getRGBA(imageData.data, 4), testColor);
    718 
    719    data = new Float16Array(200);
    720    imageData = new ImageData(data, 10, 5, {pixelFormat:"rgba-float16"});
    721    @assert imageData.pixelFormat === "rgba-float16";
    722    @assert imageData.data === data;
    723    @assert throws INVALID_STATE_ERR new ImageData(data, 10, 5, {pixelFormat:"rgba-unorm8"});
    724    @assert throws INVALID_STATE_ERR new ImageData(data, 10, 5);
    725 
    726    data = new Uint8ClampedArray(200);
    727    imageData = new ImageData(data, 10, 5);
    728    @assert imageData.pixelFormat === "rgba-unorm8";
    729    @assert imageData.data === data;
    730    @assert throws INVALID_STATE_ERR new ImageData(data, 10, 5, {pixelFormat:"rgba-float16"});
    731 
    732    @assert throws TypeError new ImageData(data, 10, 5, {pixelFormat:"unorm8"});
    733    @assert throws TypeError new ImageData(data, 10, 5, {pixelFormat:"float16"});
    734    @assert throws TypeError new ImageData(data, 10, 5, {pixelFormat:"rgba8unorm"});
    735    @assert throws TypeError new ImageData(data, 10, 5, {pixelFormat:"rgba16float"});
    736 
    737 - name: 2d.imageData.object.ctor.array
    738  desc: ImageData has a usable constructor
    739  canvas_types: ['HtmlCanvas']
    740  code: |
    741    @assert window.ImageData !== undefined;
    742 
    743    var array = new Uint8ClampedArray(8);
    744    var imgdata = new window.ImageData(array, 1, 2);
    745    @assert imgdata.width === 1;
    746    @assert imgdata.height === 2;
    747    @assert imgdata.data === array;
    748 
    749 - name: 2d.imageData.object.ctor.array.bounds
    750  desc: ImageData has a usable constructor
    751  canvas_types: ['HtmlCanvas']
    752  code: |
    753    @assert window.ImageData !== undefined;
    754 
    755    @assert throws INVALID_STATE_ERR new ImageData(new Uint8ClampedArray(0), 1);
    756    @assert throws INVALID_STATE_ERR new ImageData(new Uint8ClampedArray(3), 1);
    757    @assert throws INDEX_SIZE_ERR new ImageData(new Uint8ClampedArray(4), 0);
    758    @assert throws INDEX_SIZE_ERR new ImageData(new Uint8ClampedArray(4), 1, 2);
    759    @assert throws TypeError new ImageData(new Uint8Array(8), 1, 2);
    760    @assert throws TypeError new ImageData(new Int8Array(8), 1, 2);
    761 
    762 - name: 2d.imageData.object.set
    763  desc: ImageData.data can be modified
    764  code: |
    765    var imgdata = ctx.getImageData(0, 0, 10, 10);
    766    imgdata.data[0] = 100;
    767    @assert imgdata.data[0] === 100;
    768    imgdata.data[0] = 200;
    769    @assert imgdata.data[0] === 200;
    770 
    771 - name: 2d.imageData.object.undefined
    772  desc: ImageData.data converts undefined to 0
    773  webidl:
    774  - es-octet
    775  code: |
    776    var imgdata = ctx.getImageData(0, 0, 10, 10);
    777    imgdata.data[0] = 100;
    778    imgdata.data[0] = undefined;
    779    @assert imgdata.data[0] === 0;
    780 
    781 - name: 2d.imageData.object.nan
    782  desc: ImageData.data converts NaN to 0
    783  webidl:
    784  - es-octet
    785  code: |
    786    var imgdata = ctx.getImageData(0, 0, 10, 10);
    787    imgdata.data[0] = 100;
    788    imgdata.data[0] = NaN;
    789    @assert imgdata.data[0] === 0;
    790    imgdata.data[0] = 100;
    791    imgdata.data[0] = "cheese";
    792    @assert imgdata.data[0] === 0;
    793 
    794 - name: 2d.imageData.object.string
    795  desc: ImageData.data converts strings to numbers with ToNumber
    796  webidl:
    797  - es-octet
    798  code: |
    799    var imgdata = ctx.getImageData(0, 0, 10, 10);
    800    imgdata.data[0] = 100;
    801    imgdata.data[0] = "110";
    802    @assert imgdata.data[0] === 110;
    803    imgdata.data[0] = 100;
    804    imgdata.data[0] = "0x78";
    805    @assert imgdata.data[0] === 120;
    806    imgdata.data[0] = 100;
    807    imgdata.data[0] = " +130e0 ";
    808    @assert imgdata.data[0] === 130;
    809 
    810 - name: 2d.imageData.object.clamp
    811  desc: ImageData.data clamps numbers to [0, 255]
    812  webidl:
    813  - es-octet
    814  code: |
    815    var imgdata = ctx.getImageData(0, 0, 10, 10);
    816 
    817    imgdata.data[0] = 100;
    818    imgdata.data[0] = 300;
    819    @assert imgdata.data[0] === 255;
    820    imgdata.data[0] = 100;
    821    imgdata.data[0] = -100;
    822    @assert imgdata.data[0] === 0;
    823 
    824    imgdata.data[0] = 100;
    825    imgdata.data[0] = 200+Math.pow(2, 32);
    826    @assert imgdata.data[0] === 255;
    827    imgdata.data[0] = 100;
    828    imgdata.data[0] = -200-Math.pow(2, 32);
    829    @assert imgdata.data[0] === 0;
    830 
    831    imgdata.data[0] = 100;
    832    imgdata.data[0] = Math.pow(10, 39);
    833    @assert imgdata.data[0] === 255;
    834    imgdata.data[0] = 100;
    835    imgdata.data[0] = -Math.pow(10, 39);
    836    @assert imgdata.data[0] === 0;
    837 
    838    imgdata.data[0] = 100;
    839    imgdata.data[0] = -Infinity;
    840    @assert imgdata.data[0] === 0;
    841    imgdata.data[0] = 100;
    842    imgdata.data[0] = Infinity;
    843    @assert imgdata.data[0] === 255;
    844 
    845 - name: 2d.imageData.object.round
    846  desc: ImageData.data rounds numbers with round-to-zero
    847  webidl:
    848  - es-octet
    849  code: |
    850    var imgdata = ctx.getImageData(0, 0, 10, 10);
    851    imgdata.data[0] = 0.499;
    852    @assert imgdata.data[0] === 0;
    853    imgdata.data[0] = 0.5;
    854    @assert imgdata.data[0] === 0;
    855    imgdata.data[0] = 0.501;
    856    @assert imgdata.data[0] === 1;
    857    imgdata.data[0] = 1.499;
    858    @assert imgdata.data[0] === 1;
    859    imgdata.data[0] = 1.5;
    860    @assert imgdata.data[0] === 2;
    861    imgdata.data[0] = 1.501;
    862    @assert imgdata.data[0] === 2;
    863    imgdata.data[0] = 2.5;
    864    @assert imgdata.data[0] === 2;
    865    imgdata.data[0] = 3.5;
    866    @assert imgdata.data[0] === 4;
    867    imgdata.data[0] = 252.5;
    868    @assert imgdata.data[0] === 252;
    869    imgdata.data[0] = 253.5;
    870    @assert imgdata.data[0] === 254;
    871    imgdata.data[0] = 254.5;
    872    @assert imgdata.data[0] === 254;
    873    imgdata.data[0] = 256.5;
    874    @assert imgdata.data[0] === 255;
    875    imgdata.data[0] = -0.5;
    876    @assert imgdata.data[0] === 0;
    877    imgdata.data[0] = -1.5;
    878    @assert imgdata.data[0] === 0;
    879 
    880 
    881 
    882 - name: 2d.imageData.put.null
    883  desc: putImageData() with null imagedata throws TypeError
    884  code: |
    885    @assert throws TypeError ctx.putImageData(null, 0, 0);
    886 
    887 - name: 2d.imageData.put.nonfinite
    888  desc: putImageData() throws TypeError if arguments are not finite
    889  notes: *bindings
    890  code: |
    891    var imgdata = ctx.getImageData(0, 0, 10, 10);
    892    @nonfinite @assert throws TypeError ctx.putImageData(<imgdata>, <10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>);
    893    @nonfinite @assert throws TypeError ctx.putImageData(<imgdata>, <10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>);
    894 
    895 - name: 2d.imageData.put.basic
    896  desc: putImageData() puts image data from getImageData() onto the canvas
    897  code: |
    898    ctx.fillStyle = '#0f0';
    899    ctx.fillRect(0, 0, 100, 50)
    900    var imgdata = ctx.getImageData(0, 0, 100, 50);
    901    ctx.fillStyle = '#f00';
    902    ctx.fillRect(0, 0, 100, 50)
    903    ctx.putImageData(imgdata, 0, 0);
    904    @assert pixel 50,25 ==~ 0,255,0,255;
    905  expected: green
    906 
    907 - name: 2d.imageData.put.basic.rgba.float16
    908  desc: putImageData() puts 16-bit floating point image data from getImageData() onto the canvas
    909  attributes: '{colorSpace: "srgb", colorType: "float16"}'
    910  code: |
    911    ctx.fillStyle = 'color(display-p3 1 0 0)';
    912    ctx.fillRect(0, 0, 100, 50)
    913    var imgdata = ctx.getImageData(0, 0, 100, 50, {colorSpace:"srgb", pixelFormat:"rgba-float16"});
    914    ctx.fillStyle = '#f00';
    915    ctx.fillRect(0, 0, 100, 50)
    916    ctx.putImageData(imgdata, 0, 0);
    917    var pixel = ctx.getImageData(0, 0, 1, 1, {colorSpace:"display-p3", pixelFormat:"rgba-float16"});
    918    assert_approx_equals(pixel.data[0], 1, 0.01);
    919    assert_approx_equals(pixel.data[1], 0, 0.01);
    920    assert_approx_equals(pixel.data[2], 0, 0.01);
    921    assert_approx_equals(pixel.data[3], 1, 0.01);
    922 
    923 - name: 2d.imageData.put.created
    924  desc: putImageData() puts image data from createImageData() onto the canvas
    925  code: |
    926    var imgdata = ctx.createImageData(100, 50);
    927    for (var i = 0; i < imgdata.data.length; i += 4) {
    928        imgdata.data[i] = 0;
    929        imgdata.data[i+1] = 255;
    930        imgdata.data[i+2] = 0;
    931        imgdata.data[i+3] = 255;
    932    }
    933    ctx.fillStyle = '#f00';
    934    ctx.fillRect(0, 0, 100, 50)
    935    ctx.putImageData(imgdata, 0, 0);
    936    @assert pixel 50,25 ==~ 0,255,0,255;
    937  expected: green
    938 
    939 - name: 2d.imageData.put.wrongtype
    940  desc: putImageData() does not accept non-ImageData objects
    941  code: |
    942    var imgdata = { width: 1, height: 1, data: [255, 0, 0, 255] };
    943    @assert throws TypeError ctx.putImageData(imgdata, 0, 0);
    944    @assert throws TypeError ctx.putImageData("cheese", 0, 0);
    945    @assert throws TypeError ctx.putImageData(42, 0, 0);
    946  expected: green
    947 
    948 - name: 2d.imageData.put.cross
    949  desc: putImageData() accepts image data got from a different canvas
    950  canvas_types: ['HtmlCanvas']
    951  code: |
    952    var canvas2 = document.createElement('canvas');
    953    var ctx2 = canvas2.getContext('2d');
    954    ctx2.fillStyle = '#0f0';
    955    ctx2.fillRect(0, 0, 100, 50)
    956    var imgdata = ctx2.getImageData(0, 0, 100, 50);
    957    ctx.fillStyle = '#f00';
    958    ctx.fillRect(0, 0, 100, 50)
    959    ctx.putImageData(imgdata, 0, 0);
    960    @assert pixel 50,25 ==~ 0,255,0,255;
    961  expected: green
    962 
    963 - name: 2d.imageData.put.cross
    964  desc: putImageData() accepts image data got from a different canvas
    965  canvas_types: ['OffscreenCanvas', 'Worker']
    966  code: |
    967    var offscreenCanvas2 = new OffscreenCanvas(100, 50);
    968    var ctx2 = offscreenCanvas2.getContext('2d');
    969    ctx2.fillStyle = '#0f0';
    970    ctx2.fillRect(0, 0, 100, 50)
    971    var imgdata = ctx2.getImageData(0, 0, 100, 50);
    972    ctx.fillStyle = '#f00';
    973    ctx.fillRect(0, 0, 100, 50)
    974    ctx.putImageData(imgdata, 0, 0);
    975    @assert pixel 50,25 ==~ 0,255,0,255;
    976  expected: green
    977 
    978 - name: 2d.imageData.put.alpha
    979  desc: putImageData() puts non-solid image data correctly
    980  code: |
    981    ctx.fillStyle = 'rgba(0, 255, 0, 0.25)';
    982    ctx.fillRect(0, 0, 100, 50)
    983    var imgdata = ctx.getImageData(0, 0, 100, 50);
    984    ctx.fillStyle = '#f00';
    985    ctx.fillRect(0, 0, 100, 50)
    986    ctx.putImageData(imgdata, 0, 0);
    987    @assert pixel 50,25 ==~ 0,255,0,64;
    988  expected: |
    989    size 100 50
    990    cr.set_source_rgba(0, 1, 0, 0.25)
    991    cr.rectangle(0, 0, 100, 50)
    992    cr.fill()
    993 
    994 - name: 2d.imageData.put.modified
    995  desc: putImageData() puts modified image data correctly
    996  code: |
    997    ctx.fillStyle = '#0f0';
    998    ctx.fillRect(0, 0, 100, 50)
    999    ctx.fillStyle = '#f00';
   1000    ctx.fillRect(45, 20, 10, 10)
   1001    var imgdata = ctx.getImageData(45, 20, 10, 10);
   1002    for (var i = 0, len = imgdata.width*imgdata.height*4; i < len; i += 4)
   1003    {
   1004        imgdata.data[i] = 0;
   1005        imgdata.data[i+1] = 255;
   1006    }
   1007    ctx.putImageData(imgdata, 45, 20);
   1008    @assert pixel 50,25 ==~ 0,255,0,255;
   1009  expected: green
   1010 
   1011 - name: 2d.imageData.put.dirty.zero
   1012  desc: putImageData() with zero-sized dirty rectangle puts nothing
   1013  code: |
   1014    ctx.fillStyle = '#f00';
   1015    ctx.fillRect(0, 0, 100, 50)
   1016    var imgdata = ctx.getImageData(0, 0, 100, 50);
   1017    ctx.fillStyle = '#0f0';
   1018    ctx.fillRect(0, 0, 100, 50)
   1019    ctx.putImageData(imgdata, 0, 0, 0, 0, 0, 0);
   1020    @assert pixel 50,25 ==~ 0,255,0,255;
   1021  expected: green
   1022 
   1023 - name: 2d.imageData.put.dirty.rect1
   1024  desc: putImageData() only modifies areas inside the dirty rectangle, using width
   1025    and height
   1026  code: |
   1027    ctx.fillStyle = '#f00';
   1028    ctx.fillRect(0, 0, 100, 50)
   1029    ctx.fillStyle = '#0f0';
   1030    ctx.fillRect(0, 0, 20, 20)
   1031 
   1032    var imgdata = ctx.getImageData(0, 0, 100, 50);
   1033 
   1034    ctx.fillStyle = '#0f0';
   1035    ctx.fillRect(0, 0, 100, 50)
   1036    ctx.fillStyle = '#f00';
   1037    ctx.fillRect(40, 20, 20, 20)
   1038    ctx.putImageData(imgdata, 40, 20, 0, 0, 20, 20);
   1039 
   1040    @assert pixel 50,25 ==~ 0,255,0,255;
   1041    @assert pixel 35,25 ==~ 0,255,0,255;
   1042    @assert pixel 65,25 ==~ 0,255,0,255;
   1043    @assert pixel 50,15 ==~ 0,255,0,255;
   1044    @assert pixel 50,45 ==~ 0,255,0,255;
   1045  expected: green
   1046 
   1047 - name: 2d.imageData.put.dirty.rect2
   1048  desc: putImageData() only modifies areas inside the dirty rectangle, using x and
   1049    y
   1050  code: |
   1051    ctx.fillStyle = '#f00';
   1052    ctx.fillRect(0, 0, 100, 50)
   1053    ctx.fillStyle = '#0f0';
   1054    ctx.fillRect(60, 30, 20, 20)
   1055 
   1056    var imgdata = ctx.getImageData(0, 0, 100, 50);
   1057 
   1058    ctx.fillStyle = '#0f0';
   1059    ctx.fillRect(0, 0, 100, 50)
   1060    ctx.fillStyle = '#f00';
   1061    ctx.fillRect(40, 20, 20, 20)
   1062    ctx.putImageData(imgdata, -20, -10, 60, 30, 20, 20);
   1063 
   1064    @assert pixel 50,25 ==~ 0,255,0,255;
   1065    @assert pixel 35,25 ==~ 0,255,0,255;
   1066    @assert pixel 65,25 ==~ 0,255,0,255;
   1067    @assert pixel 50,15 ==~ 0,255,0,255;
   1068    @assert pixel 50,45 ==~ 0,255,0,255;
   1069  expected: green
   1070 
   1071 - name: 2d.imageData.put.dirty.negative
   1072  desc: putImageData() handles negative-sized dirty rectangles correctly
   1073  code: |
   1074    ctx.fillStyle = '#f00';
   1075    ctx.fillRect(0, 0, 100, 50)
   1076    ctx.fillStyle = '#0f0';
   1077    ctx.fillRect(0, 0, 20, 20)
   1078 
   1079    var imgdata = ctx.getImageData(0, 0, 100, 50);
   1080 
   1081    ctx.fillStyle = '#0f0';
   1082    ctx.fillRect(0, 0, 100, 50)
   1083    ctx.fillStyle = '#f00';
   1084    ctx.fillRect(40, 20, 20, 20)
   1085    ctx.putImageData(imgdata, 40, 20, 20, 20, -20, -20);
   1086 
   1087    @assert pixel 50,25 ==~ 0,255,0,255;
   1088    @assert pixel 35,25 ==~ 0,255,0,255;
   1089    @assert pixel 65,25 ==~ 0,255,0,255;
   1090    @assert pixel 50,15 ==~ 0,255,0,255;
   1091    @assert pixel 50,45 ==~ 0,255,0,255;
   1092  expected: green
   1093 
   1094 - name: 2d.imageData.put.dirty.outside
   1095  desc: putImageData() handles dirty rectangles outside the canvas correctly
   1096  code: |
   1097    ctx.fillStyle = '#f00';
   1098    ctx.fillRect(0, 0, 100, 50)
   1099 
   1100    var imgdata = ctx.getImageData(0, 0, 100, 50);
   1101 
   1102    ctx.fillStyle = '#0f0';
   1103    ctx.fillRect(0, 0, 100, 50)
   1104 
   1105    ctx.putImageData(imgdata, 100, 20, 20, 20, -20, -20);
   1106    ctx.putImageData(imgdata, 200, 200, 0, 0, 100, 50);
   1107    ctx.putImageData(imgdata, 40, 20, -30, -20, 30, 20);
   1108    ctx.putImageData(imgdata, -30, 20, 0, 0, 30, 20);
   1109 
   1110    @assert pixel 50,25 ==~ 0,255,0,255;
   1111    @assert pixel 98,15 ==~ 0,255,0,255;
   1112    @assert pixel 98,25 ==~ 0,255,0,255;
   1113    @assert pixel 98,45 ==~ 0,255,0,255;
   1114    @assert pixel 1,5 ==~ 0,255,0,255;
   1115    @assert pixel 1,25 ==~ 0,255,0,255;
   1116    @assert pixel 1,45 ==~ 0,255,0,255;
   1117  expected: green
   1118 
   1119 - name: 2d.imageData.put.unchanged
   1120  desc: putImageData(getImageData(...), ...) has no effect
   1121  code: |
   1122    var i = 0;
   1123    for (var y = 0; y < 16; ++y) {
   1124        for (var x = 0; x < 16; ++x, ++i) {
   1125            ctx.fillStyle = 'rgba(' + i + ',' + (Math.floor(i*1.5) % 256) + ',' + (Math.floor(i*23.3) % 256) + ',' + (i/256) + ')';
   1126            ctx.fillRect(x, y, 1, 1);
   1127        }
   1128    }
   1129    var imgdata1 = ctx.getImageData(0.1, 0.2, 15.8, 15.9);
   1130    var olddata = [];
   1131    for (var i = 0; i < imgdata1.data.length; ++i)
   1132        olddata[i] = imgdata1.data[i];
   1133 
   1134    ctx.putImageData(imgdata1, 0.1, 0.2);
   1135 
   1136    var imgdata2 = ctx.getImageData(0.1, 0.2, 15.8, 15.9);
   1137    for (var i = 0; i < imgdata2.data.length; ++i) {
   1138        @assert olddata[i] === imgdata2.data[i];
   1139    }
   1140 
   1141 - name: 2d.imageData.put.unaffected
   1142  desc: putImageData() is not affected by context state
   1143  code: |
   1144    ctx.fillStyle = '#0f0';
   1145    ctx.fillRect(0, 0, 100, 50)
   1146    var imgdata = ctx.getImageData(0, 0, 100, 50);
   1147    ctx.fillStyle = '#f00';
   1148    ctx.fillRect(0, 0, 100, 50)
   1149    ctx.globalAlpha = 0.1;
   1150    ctx.globalCompositeOperation = 'destination-atop';
   1151    ctx.shadowColor = '#f00';
   1152    ctx.shadowBlur = 1;
   1153    ctx.translate(100, 50);
   1154    ctx.scale(0.1, 0.1);
   1155    ctx.putImageData(imgdata, 0, 0);
   1156    @assert pixel 50,25 ==~ 0,255,0,255;
   1157  expected: green
   1158 
   1159 - name: 2d.imageData.put.clip
   1160  desc: putImageData() is not affected by clipping regions
   1161  code: |
   1162    ctx.fillStyle = '#0f0';
   1163    ctx.fillRect(0, 0, 100, 50)
   1164    var imgdata = ctx.getImageData(0, 0, 100, 50);
   1165    ctx.fillStyle = '#f00';
   1166    ctx.fillRect(0, 0, 100, 50)
   1167    ctx.beginPath();
   1168    ctx.rect(0, 0, 50, 50);
   1169    ctx.clip();
   1170    ctx.putImageData(imgdata, 0, 0);
   1171    @assert pixel 25,25 ==~ 0,255,0,255;
   1172    @assert pixel 75,25 ==~ 0,255,0,255;
   1173  expected: green
   1174 
   1175 - name: 2d.imageData.put.path
   1176  desc: putImageData() does not affect the current path
   1177  code: |
   1178    ctx.fillStyle = '#f00';
   1179    ctx.fillRect(0, 0, 100, 50)
   1180    ctx.rect(0, 0, 100, 50);
   1181    var imgdata = ctx.getImageData(0, 0, 100, 50);
   1182    ctx.putImageData(imgdata, 0, 0);
   1183    ctx.fillStyle = '#0f0';
   1184    ctx.fill();
   1185    @assert pixel 50,25 ==~ 0,255,0,255;
   1186  expected: green