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