test_canvas_path.html (13291B)
1 <!DOCTYPE HTML> 2 <title>Canvas Tests</title> 3 <script src="/tests/SimpleTest/SimpleTest.js"></script> 4 <link rel="stylesheet" href="/tests/SimpleTest/test.css"> 5 <body> 6 <script> 7 8 SimpleTest.waitForExplicitFinish(); 9 const Cc = SpecialPowers.Cc; 10 const Cr = SpecialPowers.Cr; 11 12 function isPixel(ctx, x,y, c, d) { 13 var pos = x + "," + y; 14 var color = c[0] + "," + c[1] + "," + c[2] + "," + c[3]; 15 var pixel = ctx.getImageData(x, y, 1, 1); 16 var pr = pixel.data[0], 17 pg = pixel.data[1], 18 pb = pixel.data[2], 19 pa = pixel.data[3]; 20 ok(c[0]-d <= pr && pr <= c[0]+d && 21 c[1]-d <= pg && pg <= c[1]+d && 22 c[2]-d <= pb && pb <= c[2]+d && 23 c[3]-d <= pa && pa <= c[3]+d, 24 "pixel "+pos+" of "+ctx.canvas.id+" is "+pr+","+pg+","+pb+","+pa+"; expected "+color+" +/- "+d); 25 } 26 </script> 27 28 <p>Canvas test: test_drawClipPath_canvas</p> 29 <canvas id="c1" class="output" width="100" height="100">+ 30 </canvas> 31 <script type="text/javascript"> 32 function test_drawClipPath_canvas() { 33 var c = document.getElementById("c1"); 34 var ctx = c.getContext("2d"); 35 36 var path = new Path2D(); 37 path.rect(0, 0, 100, 100); 38 path.rect(25, 25, 50, 50); 39 40 ctx.fillStyle = 'rgb(255,0,0)'; 41 ctx.beginPath(); 42 ctx.fillRect(0, 0, 100, 100); 43 ctx.fillStyle = 'rgb(0,255,0)'; 44 ctx.save(); 45 ctx.clip(path); 46 47 ctx.fillRect(0, 0, 100, 100); 48 isPixel(ctx, 50, 50, [0, 255, 0, 255], 5); 49 ctx.restore(); 50 51 ctx.fillStyle = 'rgb(255,0,0)'; 52 ctx.beginPath(); 53 ctx.fillRect(0, 0, 100, 100); 54 ctx.fillStyle = 'rgb(0,255,0)'; 55 ctx.save(); 56 ctx.clip(path, 'nonzero'); 57 58 ctx.fillRect(0, 0, 100, 100); 59 isPixel(ctx, 50, 50, [0, 255, 0, 255], 5); 60 ctx.restore(); 61 62 ctx.fillStyle = 'rgb(255,0,0)'; 63 ctx.beginPath(); 64 ctx.fillRect(0, 0, 100, 100); 65 ctx.fillStyle = 'rgb(0,255,0)'; 66 ctx.save(); 67 ctx.clip(path, 'evenodd'); 68 69 ctx.fillRect(0, 0, 100, 100); 70 isPixel(ctx, 50, 50, [255, 0, 0, 255], 5); 71 ctx.restore(); 72 } 73 </script> 74 75 <p>Canvas test: test_drawFillPath_canvas</p> 76 <canvas id="c2" class="output" width="100" height="100">+ 77 </canvas> 78 <script type="text/javascript"> 79 function test_drawFillPath_canvas() { 80 var c = document.getElementById("c2"); 81 var ctx = c.getContext("2d"); 82 83 var path = new Path2D(); 84 path.rect(0, 0, 100, 100); 85 path.rect(25, 25, 50, 50); 86 87 ctx.fillStyle = 'rgb(255,0,0)'; 88 ctx.fillRect(0, 0, 100, 100); 89 ctx.fillStyle = 'rgb(0,255,0)'; 90 ctx.fill(path); 91 isPixel(ctx, 50, 50, [0, 255, 0, 255], 5); 92 93 ctx.fillStyle = 'rgb(255,0,0)'; 94 ctx.fillRect(0, 0, 100, 100); 95 ctx.fillStyle = 'rgb(0,255,0)'; 96 ctx.fill(path, 'nonzero'); 97 isPixel(ctx, 50, 50, [0, 255, 0, 255], 5); 98 99 ctx.fillStyle = 'rgb(255,0,0)'; 100 ctx.fillRect(0, 0, 100, 100); 101 ctx.fillStyle = 'rgb(0,255,0)'; 102 ctx.fill(path, 'evenodd'); 103 isPixel(ctx, 50, 50, [255, 0, 0, 255], 5); 104 } 105 </script> 106 107 <p>Canvas test: test_drawStrokePath_canvas</p> 108 <canvas id="c3" class="output" width="100" height="100">+ 109 </canvas> 110 <script type="text/javascript"> 111 function test_drawStrokePath_canvas() { 112 var c = document.getElementById("c3"); 113 var ctx = c.getContext("2d"); 114 115 var path = new Path2D(); 116 path.rect(0, 0, 100, 100); 117 path.rect(25, 25, 50, 50); 118 119 ctx.fillStyle = 'rgb(255,0,0)'; 120 ctx.fillRect(0, 0, 100, 100); 121 ctx.strokeStyle = 'rgb(0,255,0)'; 122 ctx.lineWidth = 5; 123 ctx.stroke(path); 124 isPixel(ctx, 0, 0, [0, 255, 0, 255], 5); 125 isPixel(ctx, 25, 25, [0, 255, 0, 255], 5); 126 isPixel(ctx, 10, 10, [255, 0, 0, 255], 5); 127 } 128 </script> 129 130 <p>Canvas test: test_large_canvas</p> 131 <canvas id="c4" class="output" width="10000" height="100">+ 132 </canvas> 133 <script type="text/javascript"> 134 function test_large_canvas() { 135 // test paths on large canvases. On certain platforms this will 136 // trigger retargeting of the backend 137 var c = document.getElementById("c4"); 138 var ctx = c.getContext("2d"); 139 140 var path = new Path2D(); 141 path.rect(0, 0, 100, 100); 142 path.rect(25, 25, 50, 50); 143 144 ctx.fillStyle = 'rgb(255,0,0)'; 145 ctx.fillRect(0, 0, 100, 100); 146 ctx.fillStyle = 'rgb(0,255,0)'; 147 ctx.fill(path); 148 isPixel(ctx, 50, 50, [0, 255, 0, 255], 5); 149 150 ctx.fillStyle = 'rgb(255,0,0)'; 151 ctx.fillRect(0, 0, 100, 100); 152 ctx.fillStyle = 'rgb(0,255,0)'; 153 ctx.fill(path, 'nonzero'); 154 isPixel(ctx, 50, 50, [0, 255, 0, 255], 5); 155 156 ctx.fillStyle = 'rgb(255,0,0)'; 157 ctx.fillRect(0, 0, 100, 100); 158 ctx.fillStyle = 'rgb(0,255,0)'; 159 ctx.fill(path, 'evenodd'); 160 isPixel(ctx, 50, 50, [255, 0, 0, 255], 5); 161 } 162 </script> 163 164 <p>Canvas test: test_isPointInPath_canvas</p> 165 <canvas id="c5" class="output" width="100" height="100">+ 166 </canvas> 167 <script type="text/javascript"> 168 169 function shouldThrow(ctx, s) { 170 var _ok = false; 171 try { 172 // eslint-disable-next-line no-eval 173 eval(s); 174 } catch(e) { 175 _ok = true; 176 } 177 ok(_ok, s); 178 } 179 180 function shouldBeTrue(ctx, path, s) { 181 // eslint-disable-next-line no-eval 182 var _ok = eval(s); 183 ok(_ok, s); 184 } 185 function shouldBeFalse(ctx, path, s) { 186 // eslint-disable-next-line no-eval 187 var _ok = !eval(s); 188 ok(_ok, s); 189 } 190 191 function test_isPointInPath_canvas() { 192 var c = document.getElementById("c5"); 193 var ctx = c.getContext("2d"); 194 195 var path = new Path2D(); 196 path.rect(0, 0, 100, 100); 197 path.rect(25, 25, 50, 50); 198 shouldBeTrue(ctx, path, "ctx.isPointInPath(path, 50, 50)"); 199 shouldBeFalse(ctx, path, "ctx.isPointInPath(path, NaN, 50)"); 200 shouldBeFalse(ctx, path, "ctx.isPointInPath(path, 50, NaN)"); 201 202 path = new Path2D(); 203 path.rect(0, 0, 100, 100); 204 path.rect(25, 25, 50, 50); 205 shouldBeTrue(ctx, path, "ctx.isPointInPath(path, 50, 50, 'nonzero')"); 206 207 path = new Path2D(); 208 path.rect(0, 0, 100, 100); 209 path.rect(25, 25, 50, 50); 210 shouldBeFalse(ctx, path, "ctx.isPointInPath(path, 50, 50, 'evenodd')"); 211 212 shouldThrow(ctx, "ctx.isPointInPath(null, 50, 50)"); 213 shouldThrow(ctx, "ctx.isPointInPath(null, 50, 50, 'nonzero')"); 214 shouldThrow(ctx, "ctx.isPointInPath(null, 50, 50, 'evenodd')"); 215 shouldThrow(ctx, "ctx.isPointInPath(path, 50, 50)"); 216 shouldThrow(ctx, "ctx.isPointInPath(path, 50, 50, 'nonzero')"); 217 shouldThrow(ctx, "ctx.isPointInPath(path, 50, 50, 'evenodd')"); 218 219 shouldThrow(ctx, "ctx.isPointInPath([], 50, 50)"); 220 shouldThrow(ctx, "ctx.isPointInPath([], 50, 50, 'nonzero')"); 221 shouldThrow(ctx, "ctx.isPointInPath([], 50, 50, 'evenodd')"); 222 shouldThrow(ctx, "ctx.isPointInPath({}, 50, 50)"); 223 shouldThrow(ctx, "ctx.isPointInPath({}, 50, 50, 'nonzero')"); 224 shouldThrow(ctx, "ctx.isPointInPath({}, 50, 50, 'evenodd')"); 225 } 226 </script> 227 228 <p>Canvas test: test_isPointInStroke_canvas</p> 229 <canvas id="c6" class="output" width="100" height="100">+ 230 </canvas> 231 <script type="text/javascript"> 232 233 function test_isPointInStroke_canvas() { 234 var c = document.getElementById("c6"); 235 var ctx = c.getContext("2d"); 236 237 ctx.strokeStyle = '#0ff'; 238 239 var path = new Path2D(); 240 path.rect(20,20,100,100); 241 242 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,20,20)"); 243 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,120,20)"); 244 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,20,120)"); 245 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,120,120)"); 246 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,70,20)"); 247 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,20,70)"); 248 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,120,70)"); 249 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,70,120)"); 250 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,22,22)"); 251 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,118,22)"); 252 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,22,118)"); 253 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,118,118)"); 254 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,70,18)"); 255 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,122,70)"); 256 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,70,122)"); 257 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,18,70)"); 258 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,NaN,122)"); 259 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,18,NaN)"); 260 261 shouldThrow(ctx, "ctx.isPointInStroke(null,70,20)"); 262 shouldThrow(ctx, "ctx.isPointInStroke([],20,70)"); 263 shouldThrow(ctx, "ctx.isPointInStroke({},120,70)"); 264 265 ctx.lineWidth = 10; 266 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,22,22)"); 267 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,118,22)"); 268 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,22,118)"); 269 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,118,118)"); 270 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,70,18)"); 271 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,122,70)"); 272 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,70,122)"); 273 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,18,70)"); 274 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,26,70)"); 275 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,70,26)"); 276 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,70,114)"); 277 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,114,70)"); 278 279 path = new Path2D(); 280 path.moveTo(10,10); 281 path.lineTo(110,20); 282 path.lineTo(10,30); 283 ctx.lineJoin = "bevel"; 284 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,113,20)"); 285 286 ctx.miterLimit = 40.0; 287 ctx.lineJoin = "miter"; 288 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,113,20)"); 289 290 ctx.miterLimit = 2.0; 291 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,113,20)"); 292 293 path = new Path2D(); 294 path.moveTo(10,10); 295 path.lineTo(110,10); 296 ctx.lineCap = "butt"; 297 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,112,10)"); 298 299 ctx.lineCap = "round"; 300 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,112,10)"); 301 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,117,10)"); 302 303 ctx.lineCap = "square"; 304 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,112,10)"); 305 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,117,10)"); 306 307 ctx.lineCap = "butt"; 308 ctx.setLineDash([10,10]); 309 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,15,10)"); 310 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,25,10)"); 311 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,35,10)"); 312 313 ctx.lineDashOffset = 10; 314 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,15,10)"); 315 shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,25,10)"); 316 shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,35,10)"); 317 } 318 </script> 319 320 <p>Canvas test: test_pathconstructor_canvas</p> 321 <canvas id="c7" class="output" width="200" height="100">+ 322 </canvas> 323 <script type="text/javascript"> 324 325 function test_pathconstructor_canvas() { 326 var c = document.getElementById("c7"); 327 var ctx = c.getContext("2d"); 328 329 var p = new Path2D("M100,0L200,0L200,100L100,100z"); 330 ctx.fillStyle = 'blue'; 331 ctx.fill(p); 332 isPixel(ctx, 105, 5, [0, 0, 255, 255], 0); 333 isPixel(ctx, 5, 5, [0, 0, 0, 0], 0); 334 335 // copy constructor. This should not crash. 336 var p1 = new Path2D(); 337 var _p2 = new Path2D(p1); 338 p1.arcTo(0, 0, 1, 1, 2); 339 } 340 </script> 341 342 <p>Canvas test: test_addpath_canvas</p> 343 <canvas id="c8" class="output" width="200" height="200">+ 344 </canvas> 345 <script type="text/javascript"> 346 347 function test_addpath_canvas() { 348 var c = document.getElementById("c8"); 349 var ctx = c.getContext("2d"); 350 ctx.beginPath(); 351 var p1 = new Path2D(); 352 p1.rect(0,0,100,100); 353 var p2 = new Path2D(); 354 p2.rect(0,100,100,100); 355 var m = ctx.currentTransform; 356 p1.addPath(p2, m); 357 ctx.fillStyle = 'yellow'; 358 ctx.fill(p1); 359 isPixel(ctx, 0, 100, [255, 255, 0, 255], 0); 360 361 ctx.clearRect(0,0,200,200); 362 363 ctx.beginPath(); 364 var p3 = new Path2D(); 365 p3.rect(0,0,100,100); 366 var p4 = new Path2D(); 367 p4.rect(0,100,100,100); 368 var m = document.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGMatrix(); 369 m.a = 1; m.b = 0; 370 m.c = 0; m.d = 1; 371 m.e = 100; m.f = -100; 372 p3.addPath(p4, m); 373 ctx.fillStyle = 'yellow'; 374 ctx.fill(p3); 375 isPixel(ctx, 50, 50, [255, 255, 0, 255], 0); 376 isPixel(ctx, 150, 150, [0, 0, 0, 0], 0); 377 378 var p5 = new Path2D(); 379 p5.rect(0,0,100,100); 380 shouldThrow(ctx, "p5.addPath(null, m)"); 381 shouldThrow(ctx, "p5.addPath([], m)"); 382 shouldThrow(ctx, "p5.addPath({}, m)"); 383 384 p5 = p5.addPath(p5); 385 } 386 </script> 387 388 <script> 389 390 function runTests() { 391 try { 392 test_drawClipPath_canvas(); 393 } catch(e) { 394 ok(false, "unexpected exception thrown in: test_drawClipPath_canvas"); 395 throw e; 396 } 397 try { 398 test_drawFillPath_canvas(); 399 } catch(e) { 400 ok(false, "unexpected exception thrown in: test_drawFillPath_canvas"); 401 throw e; 402 } 403 try { 404 test_drawStrokePath_canvas(); 405 } catch(e) { 406 ok(false, "unexpected exception thrown in: test_drawStrokePath_canvas"); 407 throw e; 408 } 409 try { 410 test_large_canvas(); 411 } catch(e) { 412 ok(false, "unexpected exception thrown in: test_large_canvas"); 413 throw e; 414 } 415 try { 416 test_isPointInPath_canvas(); 417 } catch(e) { 418 ok(false, "unexpected exception thrown in: test_isPointInPath_canvas"); 419 throw e; 420 } 421 try { 422 test_isPointInStroke_canvas(); 423 } catch(e) { 424 ok(false, "unexpected exception thrown in: test_isPointInStroke_canvas"); 425 throw e; 426 } 427 try { 428 test_pathconstructor_canvas(); 429 } catch(e) { 430 ok(false, "unexpected exception thrown in: test_pathconstructor_canvas"); 431 throw e; 432 } 433 try { 434 test_addpath_canvas(); 435 } catch(e) { 436 ok(false, "unexpected exception thrown in: test_addpath_canvas"); 437 throw e; 438 } 439 SimpleTest.finish(); 440 } 441 442 addLoadEvent(function() { 443 SpecialPowers.pushPrefEnv({"set":[["canvas.path.enabled", true]]}, runTests); 444 }); 445 446 // Don't leak the world via the Path2D reference to its window. 447 document.all; 448 window.p = new Path2D(); 449 450 </script>