path-objects.yaml (104855B)
1 - name: 2d.path.initial 2 #mozilla: { bug: TODO } 3 code: | 4 ctx.fillStyle = '#0f0'; 5 ctx.fillRect(0, 0, 100, 50); 6 ctx.closePath(); 7 ctx.fillStyle = '#f00'; 8 ctx.fill(); 9 @assert pixel 50,25 == 0,255,0,255; 10 expected: green 11 12 - name: 2d.path.beginPath 13 code: | 14 ctx.fillStyle = '#0f0'; 15 ctx.fillRect(0, 0, 100, 50); 16 ctx.rect(0, 0, 100, 50); 17 ctx.beginPath(); 18 ctx.fillStyle = '#f00'; 19 ctx.fill(); 20 @assert pixel 50,25 == 0,255,0,255; 21 expected: green 22 23 - name: 2d.path.moveTo.basic 24 code: | 25 ctx.fillStyle = '#f00'; 26 ctx.fillRect(0, 0, 100, 50); 27 ctx.rect(0, 0, 10, 50); 28 ctx.moveTo(100, 0); 29 ctx.lineTo(10, 0); 30 ctx.lineTo(10, 50); 31 ctx.lineTo(100, 50); 32 ctx.fillStyle = '#0f0'; 33 ctx.fill(); 34 @assert pixel 90,25 == 0,255,0,255; 35 expected: green 36 37 - name: 2d.path.moveTo.newsubpath 38 code: | 39 ctx.fillStyle = '#0f0'; 40 ctx.fillRect(0, 0, 100, 50); 41 ctx.beginPath(); 42 ctx.moveTo(0, 0); 43 ctx.moveTo(100, 0); 44 ctx.moveTo(100, 50); 45 ctx.moveTo(0, 50); 46 ctx.fillStyle = '#f00'; 47 ctx.fill(); 48 @assert pixel 50,25 == 0,255,0,255; 49 expected: green 50 51 - name: 2d.path.moveTo.multiple 52 code: | 53 ctx.fillStyle = '#f00'; 54 ctx.fillRect(0, 0, 100, 50); 55 ctx.moveTo(0, 25); 56 ctx.moveTo(100, 25); 57 ctx.moveTo(0, 25); 58 ctx.lineTo(100, 25); 59 ctx.strokeStyle = '#0f0'; 60 ctx.lineWidth = 50; 61 ctx.stroke(); 62 @assert pixel 50,25 == 0,255,0,255; 63 expected: green 64 65 - name: 2d.path.moveTo.nonfinite 66 desc: moveTo() with Infinity/NaN is ignored 67 code: | 68 ctx.moveTo(0, 0); 69 ctx.lineTo(100, 0); 70 @nonfinite ctx.moveTo(<0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>); 71 ctx.lineTo(100, 50); 72 ctx.lineTo(0, 50); 73 ctx.fillStyle = '#0f0'; 74 ctx.fill(); 75 @assert pixel 50,25 == 0,255,0,255; 76 expected: green 77 78 - name: 2d.path.closePath.empty 79 code: | 80 ctx.fillStyle = '#0f0'; 81 ctx.fillRect(0, 0, 100, 50); 82 ctx.closePath(); 83 ctx.fillStyle = '#f00'; 84 ctx.fill(); 85 @assert pixel 50,25 == 0,255,0,255; 86 expected: green 87 88 - name: 2d.path.closePath.newline 89 code: | 90 ctx.fillStyle = '#f00'; 91 ctx.fillRect(0, 0, 100, 50); 92 ctx.strokeStyle = '#0f0'; 93 ctx.lineWidth = 50; 94 ctx.moveTo(-100, 25); 95 ctx.lineTo(-100, -100); 96 ctx.lineTo(200, -100); 97 ctx.lineTo(200, 25); 98 ctx.closePath(); 99 ctx.stroke(); 100 @assert pixel 50,25 == 0,255,0,255; 101 expected: green 102 103 - name: 2d.path.closePath.nextpoint 104 code: | 105 ctx.fillStyle = '#f00'; 106 ctx.fillRect(0, 0, 100, 50); 107 ctx.strokeStyle = '#0f0'; 108 ctx.lineWidth = 50; 109 ctx.moveTo(-100, 25); 110 ctx.lineTo(-100, -1000); 111 ctx.closePath(); 112 ctx.lineTo(1000, 25); 113 ctx.stroke(); 114 @assert pixel 50,25 == 0,255,0,255; 115 expected: green 116 117 - name: 2d.path.lineTo.ensuresubpath.1 118 desc: If there is no subpath, the point is added and nothing is drawn 119 code: | 120 ctx.fillStyle = '#0f0'; 121 ctx.fillRect(0, 0, 100, 50); 122 ctx.strokeStyle = '#f00'; 123 ctx.lineWidth = 50; 124 ctx.beginPath(); 125 ctx.lineTo(100, 50); 126 ctx.stroke(); 127 @assert pixel 50,25 == 0,255,0,255; 128 expected: green 129 130 - name: 2d.path.lineTo.ensuresubpath.2 131 desc: If there is no subpath, the point is added and used for subsequent drawing 132 code: | 133 ctx.fillStyle = '#f00'; 134 ctx.fillRect(0, 0, 100, 50); 135 ctx.strokeStyle = '#0f0'; 136 ctx.lineWidth = 50; 137 ctx.beginPath(); 138 ctx.lineTo(0, 25); 139 ctx.lineTo(100, 25); 140 ctx.stroke(); 141 @assert pixel 50,25 == 0,255,0,255; 142 expected: green 143 144 - name: 2d.path.lineTo.basic 145 code: | 146 ctx.fillStyle = '#f00'; 147 ctx.fillRect(0, 0, 100, 50); 148 ctx.strokeStyle = '#0f0'; 149 ctx.lineWidth = 50; 150 ctx.beginPath(); 151 ctx.moveTo(0, 25); 152 ctx.lineTo(100, 25); 153 ctx.stroke(); 154 @assert pixel 50,25 == 0,255,0,255; 155 expected: green 156 157 - name: 2d.path.lineTo.nextpoint 158 code: | 159 ctx.fillStyle = '#f00'; 160 ctx.fillRect(0, 0, 100, 50); 161 ctx.strokeStyle = '#0f0'; 162 ctx.lineWidth = 50; 163 ctx.beginPath(); 164 ctx.moveTo(-100, -100); 165 ctx.lineTo(0, 25); 166 ctx.lineTo(100, 25); 167 ctx.stroke(); 168 @assert pixel 50,25 == 0,255,0,255; 169 expected: green 170 171 - name: 2d.path.lineTo.nonfinite 172 desc: lineTo() with Infinity/NaN is ignored 173 code: | 174 ctx.moveTo(0, 0); 175 ctx.lineTo(100, 0); 176 @nonfinite ctx.lineTo(<0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>); 177 ctx.lineTo(100, 50); 178 ctx.lineTo(0, 50); 179 ctx.fillStyle = '#0f0'; 180 ctx.fill(); 181 @assert pixel 50,25 == 0,255,0,255; 182 @assert pixel 90,45 == 0,255,0,255; 183 expected: green 184 185 - name: 2d.path.lineTo.nonfinite.details 186 desc: lineTo() with Infinity/NaN for first arg still converts the second arg 187 code: | 188 for (var arg1 of [Infinity, -Infinity, NaN]) { 189 var converted = false; 190 ctx.lineTo(arg1, { valueOf: function() { converted = true; return 0; } }); 191 @assert converted; 192 } 193 expected: clear 194 195 - name: 2d.path.quadraticCurveTo.ensuresubpath.1 196 desc: If there is no subpath, the first control point is added (and nothing is drawn 197 up to it) 198 code: | 199 ctx.fillStyle = '#0f0'; 200 ctx.fillRect(0, 0, 100, 50); 201 ctx.strokeStyle = '#f00'; 202 ctx.lineWidth = 50; 203 ctx.beginPath(); 204 ctx.quadraticCurveTo(100, 50, 200, 50); 205 ctx.stroke(); 206 @assert pixel 50,25 == 0,255,0,255; 207 @assert pixel 95,45 == 0,255,0,255; @moz-todo 208 expected: green 209 210 - name: 2d.path.quadraticCurveTo.ensuresubpath.2 211 desc: If there is no subpath, the first control point is added 212 code: | 213 ctx.fillStyle = '#f00'; 214 ctx.fillRect(0, 0, 100, 50); 215 ctx.strokeStyle = '#0f0'; 216 ctx.lineWidth = 50; 217 ctx.beginPath(); 218 ctx.quadraticCurveTo(0, 25, 100, 25); 219 ctx.stroke(); 220 @assert pixel 50,25 == 0,255,0,255; 221 @assert pixel 5,45 == 0,255,0,255; @moz-todo 222 expected: green 223 224 - name: 2d.path.quadraticCurveTo.basic 225 code: | 226 ctx.fillStyle = '#f00'; 227 ctx.fillRect(0, 0, 100, 50); 228 ctx.strokeStyle = '#0f0'; 229 ctx.lineWidth = 50; 230 ctx.beginPath(); 231 ctx.moveTo(0, 25); 232 ctx.quadraticCurveTo(100, 25, 100, 25); 233 ctx.stroke(); 234 @assert pixel 50,25 == 0,255,0,255; 235 expected: green 236 237 - name: 2d.path.quadraticCurveTo.shape 238 code: | 239 ctx.fillStyle = '#f00'; 240 ctx.fillRect(0, 0, 100, 50); 241 ctx.strokeStyle = '#0f0'; 242 ctx.lineWidth = 55; 243 ctx.beginPath(); 244 ctx.moveTo(-1000, 1050); 245 ctx.quadraticCurveTo(0, -1000, 1200, 1050); 246 ctx.stroke(); 247 @assert pixel 50,25 == 0,255,0,255; 248 @assert pixel 1,1 == 0,255,0,255; 249 @assert pixel 98,1 == 0,255,0,255; 250 @assert pixel 1,48 == 0,255,0,255; 251 @assert pixel 98,48 == 0,255,0,255; 252 expected: green 253 254 - name: 2d.path.quadraticCurveTo.scaled 255 code: | 256 ctx.fillStyle = '#f00'; 257 ctx.fillRect(0, 0, 100, 50); 258 ctx.scale(1000, 1000); 259 ctx.strokeStyle = '#0f0'; 260 ctx.lineWidth = 0.055; 261 ctx.beginPath(); 262 ctx.moveTo(-1, 1.05); 263 ctx.quadraticCurveTo(0, -1, 1.2, 1.05); 264 ctx.stroke(); 265 @assert pixel 50,25 == 0,255,0,255; 266 @assert pixel 1,1 == 0,255,0,255; 267 @assert pixel 98,1 == 0,255,0,255; 268 @assert pixel 1,48 == 0,255,0,255; 269 @assert pixel 98,48 == 0,255,0,255; 270 expected: green 271 272 - name: 2d.path.quadraticCurveTo.nonfinite 273 desc: quadraticCurveTo() with Infinity/NaN is ignored 274 code: | 275 ctx.moveTo(0, 0); 276 ctx.lineTo(100, 0); 277 @nonfinite ctx.quadraticCurveTo(<0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>); 278 ctx.lineTo(100, 50); 279 ctx.lineTo(0, 50); 280 ctx.fillStyle = '#0f0'; 281 ctx.fill(); 282 @assert pixel 50,25 == 0,255,0,255; 283 @assert pixel 90,45 == 0,255,0,255; 284 expected: green 285 286 - name: 2d.path.bezierCurveTo.ensuresubpath.1 287 desc: If there is no subpath, the first control point is added (and nothing is drawn 288 up to it) 289 code: | 290 ctx.fillStyle = '#0f0'; 291 ctx.fillRect(0, 0, 100, 50); 292 ctx.strokeStyle = '#f00'; 293 ctx.lineWidth = 50; 294 ctx.beginPath(); 295 ctx.bezierCurveTo(100, 50, 200, 50, 200, 50); 296 ctx.stroke(); 297 @assert pixel 50,25 == 0,255,0,255; 298 @assert pixel 95,45 == 0,255,0,255; 299 expected: green 300 301 - name: 2d.path.bezierCurveTo.ensuresubpath.2 302 desc: If there is no subpath, the first control point is added 303 code: | 304 ctx.fillStyle = '#f00'; 305 ctx.fillRect(0, 0, 100, 50); 306 ctx.strokeStyle = '#0f0'; 307 ctx.lineWidth = 50; 308 ctx.beginPath(); 309 ctx.bezierCurveTo(0, 25, 100, 25, 100, 25); 310 ctx.stroke(); 311 @assert pixel 50,25 == 0,255,0,255; 312 @assert pixel 5,45 == 0,255,0,255; 313 expected: green 314 315 - name: 2d.path.bezierCurveTo.basic 316 code: | 317 ctx.fillStyle = '#f00'; 318 ctx.fillRect(0, 0, 100, 50); 319 ctx.strokeStyle = '#0f0'; 320 ctx.lineWidth = 50; 321 ctx.beginPath(); 322 ctx.moveTo(0, 25); 323 ctx.bezierCurveTo(100, 25, 100, 25, 100, 25); 324 ctx.stroke(); 325 @assert pixel 50,25 == 0,255,0,255; 326 expected: green 327 328 - name: 2d.path.bezierCurveTo.shape 329 code: | 330 ctx.fillStyle = '#f00'; 331 ctx.fillRect(0, 0, 100, 50); 332 ctx.strokeStyle = '#0f0'; 333 ctx.lineWidth = 55; 334 ctx.beginPath(); 335 ctx.moveTo(-2000, 3100); 336 ctx.bezierCurveTo(-2000, -1000, 2100, -1000, 2100, 3100); 337 ctx.stroke(); 338 @assert pixel 50,25 == 0,255,0,255; 339 @assert pixel 1,1 == 0,255,0,255; 340 @assert pixel 98,1 == 0,255,0,255; 341 @assert pixel 1,48 == 0,255,0,255; 342 @assert pixel 98,48 == 0,255,0,255; 343 expected: green 344 345 - name: 2d.path.bezierCurveTo.scaled 346 code: | 347 ctx.fillStyle = '#f00'; 348 ctx.fillRect(0, 0, 100, 50); 349 ctx.scale(1000, 1000); 350 ctx.strokeStyle = '#0f0'; 351 ctx.lineWidth = 0.055; 352 ctx.beginPath(); 353 ctx.moveTo(-2, 3.1); 354 ctx.bezierCurveTo(-2, -1, 2.1, -1, 2.1, 3.1); 355 ctx.stroke(); 356 @assert pixel 50,25 == 0,255,0,255; 357 @assert pixel 1,1 == 0,255,0,255; 358 @assert pixel 98,1 == 0,255,0,255; 359 @assert pixel 1,48 == 0,255,0,255; 360 @assert pixel 98,48 == 0,255,0,255; 361 expected: green 362 363 - name: 2d.path.bezierCurveTo.nonfinite 364 desc: bezierCurveTo() with Infinity/NaN is ignored 365 code: | 366 ctx.moveTo(0, 0); 367 ctx.lineTo(100, 0); 368 @nonfinite ctx.bezierCurveTo(<0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>); 369 ctx.lineTo(100, 50); 370 ctx.lineTo(0, 50); 371 ctx.fillStyle = '#0f0'; 372 ctx.fill(); 373 @assert pixel 50,25 == 0,255,0,255; 374 @assert pixel 90,45 == 0,255,0,255; 375 expected: green 376 377 - name: 2d.path.arcTo.ensuresubpath.1 378 desc: If there is no subpath, the first control point is added (and nothing is drawn 379 up to it) 380 code: | 381 ctx.fillStyle = '#0f0'; 382 ctx.fillRect(0, 0, 100, 50); 383 ctx.lineWidth = 50; 384 ctx.strokeStyle = '#f00'; 385 ctx.beginPath(); 386 ctx.arcTo(100, 50, 200, 50, 0.1); 387 ctx.stroke(); 388 @assert pixel 50,25 == 0,255,0,255; 389 expected: green 390 391 - name: 2d.path.arcTo.ensuresubpath.2 392 desc: If there is no subpath, the first control point is added 393 code: | 394 ctx.fillStyle = '#f00'; 395 ctx.fillRect(0, 0, 100, 50); 396 ctx.lineWidth = 50; 397 ctx.strokeStyle = '#0f0'; 398 ctx.beginPath(); 399 ctx.arcTo(0, 25, 50, 250, 0.1); // adds (x1,y1), draws nothing 400 ctx.lineTo(100, 25); 401 ctx.stroke(); 402 @assert pixel 50,25 == 0,255,0,255; 403 expected: green 404 405 - name: 2d.path.arcTo.ensuresubpath.3 406 desc: If there is no subpath, the first control point is added (and nothing is drawn 407 up to it) 408 code: | 409 ctx.fillStyle = '#0f0'; 410 ctx.fillRect(0, 0, 100, 50); 411 ctx.strokeStyle = '#f00'; 412 ctx.lineWidth = 100; 413 ctx.beginPath(); 414 ctx.arcTo(50, 0, 50, 100, 100); 415 ctx.stroke(); 416 @assert pixel 50,25 == 0,255,0,255; 417 expected: green 418 419 - name: 2d.path.arcTo.coincide.1 420 desc: arcTo() has no effect if P0 = P1 421 code: | 422 ctx.fillStyle = '#f00'; 423 ctx.fillRect(0, 0, 100, 50); 424 ctx.lineWidth = 50; 425 426 ctx.strokeStyle = '#0f0'; 427 ctx.beginPath(); 428 ctx.moveTo(0, 25); 429 ctx.arcTo(0, 25, 50, 1000, 1); 430 ctx.lineTo(100, 25); 431 ctx.stroke(); 432 433 ctx.strokeStyle = '#f00'; 434 ctx.beginPath(); 435 ctx.moveTo(50, 25); 436 ctx.arcTo(50, 25, 100, 25, 1); 437 ctx.stroke(); 438 439 @assert pixel 50,1 == 0,255,0,255; 440 @assert pixel 50,25 == 0,255,0,255; 441 @assert pixel 50,48 == 0,255,0,255; 442 expected: green 443 444 - name: 2d.path.arcTo.coincide.2 445 desc: arcTo() draws a straight line to P1 if P1 = P2 446 code: | 447 ctx.fillStyle = '#f00'; 448 ctx.fillRect(0, 0, 100, 50); 449 ctx.lineWidth = 50; 450 ctx.strokeStyle = '#0f0'; 451 ctx.beginPath(); 452 ctx.moveTo(0, 25); 453 ctx.arcTo(100, 25, 100, 25, 1); 454 ctx.stroke(); 455 456 @assert pixel 50,25 == 0,255,0,255; 457 expected: green 458 459 - name: 2d.path.arcTo.collinear.1 460 desc: arcTo() with all points on a line, and P1 between P0/P2, draws a straight 461 line to P1 462 code: | 463 ctx.fillStyle = '#f00'; 464 ctx.fillRect(0, 0, 100, 50); 465 ctx.lineWidth = 50; 466 467 ctx.strokeStyle = '#0f0'; 468 ctx.beginPath(); 469 ctx.moveTo(0, 25); 470 ctx.arcTo(100, 25, 200, 25, 1); 471 ctx.stroke(); 472 473 ctx.strokeStyle = '#f00'; 474 ctx.beginPath(); 475 ctx.moveTo(-100, 25); 476 ctx.arcTo(0, 25, 100, 25, 1); 477 ctx.stroke(); 478 479 @assert pixel 50,25 == 0,255,0,255; 480 expected: green 481 482 - name: 2d.path.arcTo.collinear.2 483 desc: arcTo() with all points on a line, and P2 between P0/P1, draws a straight 484 line to P1 485 code: | 486 ctx.fillStyle = '#f00'; 487 ctx.fillRect(0, 0, 100, 50); 488 ctx.lineWidth = 50; 489 490 ctx.strokeStyle = '#0f0'; 491 ctx.beginPath(); 492 ctx.moveTo(0, 25); 493 ctx.arcTo(100, 25, 10, 25, 1); 494 ctx.stroke(); 495 496 ctx.strokeStyle = '#f00'; 497 ctx.beginPath(); 498 ctx.moveTo(100, 25); 499 ctx.arcTo(200, 25, 110, 25, 1); 500 ctx.stroke(); 501 502 @assert pixel 50,25 == 0,255,0,255; 503 expected: green 504 505 - name: 2d.path.arcTo.collinear.3 506 desc: arcTo() with all points on a line, and P0 between P1/P2, draws a straight 507 line to P1 508 code: | 509 ctx.fillStyle = '#f00'; 510 ctx.fillRect(0, 0, 100, 50); 511 ctx.lineWidth = 50; 512 513 ctx.strokeStyle = '#0f0'; 514 ctx.beginPath(); 515 ctx.moveTo(0, 25); 516 ctx.arcTo(100, 25, -100, 25, 1); 517 ctx.stroke(); 518 519 ctx.strokeStyle = '#f00'; 520 ctx.beginPath(); 521 ctx.moveTo(100, 25); 522 ctx.arcTo(200, 25, 0, 25, 1); 523 ctx.stroke(); 524 525 ctx.beginPath(); 526 ctx.moveTo(-100, 25); 527 ctx.arcTo(0, 25, -200, 25, 1); 528 ctx.stroke(); 529 530 @assert pixel 50,25 == 0,255,0,255; 531 expected: green 532 533 - name: 2d.path.arcTo.shape.curve1 534 desc: arcTo() curves in the right kind of shape 535 code: | 536 var tol = 1.5; // tolerance to avoid antialiasing artifacts 537 538 ctx.fillStyle = '#0f0'; 539 ctx.fillRect(0, 0, 100, 50); 540 541 ctx.strokeStyle = '#f00'; 542 ctx.lineWidth = 10; 543 ctx.beginPath(); 544 ctx.moveTo(10, 25); 545 ctx.arcTo(75, 25, 75, 60, 20); 546 ctx.stroke(); 547 548 ctx.fillStyle = '#0f0'; 549 ctx.beginPath(); 550 ctx.rect(10, 20, 45, 10); 551 ctx.moveTo(80, 45); 552 ctx.arc(55, 45, 25+tol, 0, -Math.PI/2, true); 553 ctx.arc(55, 45, 15-tol, -Math.PI/2, 0, false); 554 ctx.fill(); 555 556 @assert pixel 50,25 == 0,255,0,255; 557 @assert pixel 55,19 == 0,255,0,255; 558 @assert pixel 55,20 == 0,255,0,255; 559 @assert pixel 55,21 == 0,255,0,255; 560 @assert pixel 64,22 == 0,255,0,255; 561 @assert pixel 65,21 == 0,255,0,255; 562 @assert pixel 72,28 == 0,255,0,255; 563 @assert pixel 73,27 == 0,255,0,255; 564 @assert pixel 78,36 == 0,255,0,255; 565 @assert pixel 79,35 == 0,255,0,255; 566 @assert pixel 80,44 == 0,255,0,255; 567 @assert pixel 80,45 == 0,255,0,255; 568 @assert pixel 80,46 == 0,255,0,255; 569 @assert pixel 65,45 == 0,255,0,255; 570 expected: green 571 572 - name: 2d.path.arcTo.shape.curve2 573 desc: arcTo() curves in the right kind of shape 574 code: | 575 var tol = 1.5; // tolerance to avoid antialiasing artifacts 576 577 ctx.fillStyle = '#0f0'; 578 ctx.fillRect(0, 0, 100, 50); 579 580 ctx.fillStyle = '#f00'; 581 ctx.beginPath(); 582 ctx.rect(10, 20, 45, 10); 583 ctx.moveTo(80, 45); 584 ctx.arc(55, 45, 25-tol, 0, -Math.PI/2, true); 585 ctx.arc(55, 45, 15+tol, -Math.PI/2, 0, false); 586 ctx.fill(); 587 588 ctx.strokeStyle = '#0f0'; 589 ctx.lineWidth = 10; 590 ctx.beginPath(); 591 ctx.moveTo(10, 25); 592 ctx.arcTo(75, 25, 75, 60, 20); 593 ctx.stroke(); 594 595 @assert pixel 50,25 == 0,255,0,255; 596 @assert pixel 55,19 == 0,255,0,255; 597 @assert pixel 55,20 == 0,255,0,255; 598 @assert pixel 55,21 == 0,255,0,255; 599 @assert pixel 64,22 == 0,255,0,255; 600 @assert pixel 65,21 == 0,255,0,255; 601 @assert pixel 72,28 == 0,255,0,255; 602 @assert pixel 73,27 == 0,255,0,255; 603 @assert pixel 78,36 == 0,255,0,255; 604 @assert pixel 79,35 == 0,255,0,255; 605 @assert pixel 80,44 == 0,255,0,255; 606 @assert pixel 80,45 == 0,255,0,255; 607 @assert pixel 80,46 == 0,255,0,255; 608 expected: green 609 610 - name: 2d.path.arcTo.shape.start 611 desc: arcTo() draws a straight line from P0 to P1 612 code: | 613 ctx.fillStyle = '#f00'; 614 ctx.fillRect(0, 0, 100, 50); 615 ctx.strokeStyle = '#0f0'; 616 ctx.lineWidth = 50; 617 ctx.beginPath(); 618 ctx.moveTo(0, 25); 619 ctx.arcTo(200, 25, 200, 50, 10); 620 ctx.stroke(); 621 622 @assert pixel 1,1 == 0,255,0,255; 623 @assert pixel 1,48 == 0,255,0,255; 624 @assert pixel 50,25 == 0,255,0,255; 625 @assert pixel 98,1 == 0,255,0,255; 626 @assert pixel 98,48 == 0,255,0,255; 627 expected: green 628 629 - name: 2d.path.arcTo.shape.end 630 desc: arcTo() does not draw anything from P1 to P2 631 code: | 632 ctx.fillStyle = '#0f0'; 633 ctx.fillRect(0, 0, 100, 50); 634 ctx.strokeStyle = '#f00'; 635 ctx.lineWidth = 50; 636 ctx.beginPath(); 637 ctx.moveTo(-100, -100); 638 ctx.arcTo(-100, 25, 200, 25, 10); 639 ctx.stroke(); 640 641 @assert pixel 1,1 == 0,255,0,255; 642 @assert pixel 1,48 == 0,255,0,255; 643 @assert pixel 50,25 == 0,255,0,255; 644 @assert pixel 98,1 == 0,255,0,255; 645 @assert pixel 98,48 == 0,255,0,255; 646 expected: green 647 648 - name: 2d.path.arcTo.negative 649 desc: arcTo() with negative radius throws an exception 650 code: | 651 @assert throws INDEX_SIZE_ERR ctx.arcTo(0, 0, 0, 0, -1); 652 var path = new Path2D(); 653 @assert throws INDEX_SIZE_ERR path.arcTo(10, 10, 20, 20, -5); 654 655 - name: 2d.path.arcTo.zero.1 656 desc: arcTo() with zero radius draws a straight line from P0 to P1 657 code: | 658 ctx.fillStyle = '#f00'; 659 ctx.fillRect(0, 0, 100, 50); 660 ctx.lineWidth = 50; 661 662 ctx.strokeStyle = '#0f0'; 663 ctx.beginPath(); 664 ctx.moveTo(0, 25); 665 ctx.arcTo(100, 25, 100, 100, 0); 666 ctx.stroke(); 667 668 ctx.strokeStyle = '#f00'; 669 ctx.beginPath(); 670 ctx.moveTo(0, -25); 671 ctx.arcTo(50, -25, 50, 50, 0); 672 ctx.stroke(); 673 674 @assert pixel 50,25 == 0,255,0,255; 675 expected: green 676 677 - name: 2d.path.arcTo.zero.2 678 desc: arcTo() with zero radius draws a straight line from P0 to P1, even when all 679 points are collinear 680 code: | 681 ctx.fillStyle = '#f00'; 682 ctx.fillRect(0, 0, 100, 50); 683 ctx.lineWidth = 50; 684 685 ctx.strokeStyle = '#0f0'; 686 ctx.beginPath(); 687 ctx.moveTo(0, 25); 688 ctx.arcTo(100, 25, -100, 25, 0); 689 ctx.stroke(); 690 691 ctx.strokeStyle = '#f00'; 692 ctx.beginPath(); 693 ctx.moveTo(100, 25); 694 ctx.arcTo(200, 25, 50, 25, 0); 695 ctx.stroke(); 696 697 @assert pixel 50,25 == 0,255,0,255; 698 expected: green 699 700 - name: 2d.path.arcTo.transformation 701 desc: arcTo joins up to the last subpath point correctly 702 code: | 703 ctx.fillStyle = '#f00'; 704 ctx.fillRect(0, 0, 100, 50); 705 706 ctx.fillStyle = '#0f0'; 707 ctx.beginPath(); 708 ctx.moveTo(0, 50); 709 ctx.translate(100, 0); 710 ctx.arcTo(50, 50, 50, 0, 50); 711 ctx.lineTo(-100, 0); 712 ctx.fill(); 713 714 @assert pixel 0,0 == 0,255,0,255; 715 @assert pixel 50,0 == 0,255,0,255; 716 @assert pixel 99,0 == 0,255,0,255; 717 @assert pixel 0,25 == 0,255,0,255; 718 @assert pixel 50,25 == 0,255,0,255; 719 @assert pixel 99,25 == 0,255,0,255; 720 @assert pixel 0,49 == 0,255,0,255; 721 @assert pixel 50,49 == 0,255,0,255; 722 @assert pixel 99,49 == 0,255,0,255; 723 expected: green 724 725 - name: 2d.path.arcTo.scale 726 desc: arcTo scales the curve, not just the control points 727 code: | 728 ctx.fillStyle = '#f00'; 729 ctx.fillRect(0, 0, 100, 50); 730 731 ctx.fillStyle = '#0f0'; 732 ctx.beginPath(); 733 ctx.moveTo(0, 50); 734 ctx.translate(100, 0); 735 ctx.scale(0.1, 1); 736 ctx.arcTo(50, 50, 50, 0, 50); 737 ctx.lineTo(-1000, 0); 738 ctx.fill(); 739 740 @assert pixel 0,0 == 0,255,0,255; 741 @assert pixel 50,0 == 0,255,0,255; 742 @assert pixel 99,0 == 0,255,0,255; 743 @assert pixel 0,25 == 0,255,0,255; 744 @assert pixel 50,25 == 0,255,0,255; 745 @assert pixel 99,25 == 0,255,0,255; 746 @assert pixel 0,49 == 0,255,0,255; 747 @assert pixel 50,49 == 0,255,0,255; 748 @assert pixel 99,49 == 0,255,0,255; 749 expected: green 750 751 - name: 2d.path.arcTo.nonfinite 752 desc: arcTo() with Infinity/NaN is ignored 753 code: | 754 ctx.moveTo(0, 0); 755 ctx.lineTo(100, 0); 756 @nonfinite ctx.arcTo(<0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>); 757 ctx.lineTo(100, 50); 758 ctx.lineTo(0, 50); 759 ctx.fillStyle = '#0f0'; 760 ctx.fill(); 761 @assert pixel 50,25 == 0,255,0,255; 762 @assert pixel 90,45 == 0,255,0,255; 763 expected: green 764 765 766 - name: 2d.path.arc.empty 767 desc: arc() with an empty path does not draw a straight line to the start point 768 code: | 769 ctx.fillStyle = '#0f0'; 770 ctx.fillRect(0, 0, 100, 50); 771 ctx.lineWidth = 50; 772 ctx.strokeStyle = '#f00'; 773 ctx.beginPath(); 774 ctx.arc(200, 25, 5, 0, 2*Math.PI, true); 775 ctx.stroke(); 776 @assert pixel 50,25 == 0,255,0,255; 777 expected: green 778 779 - name: 2d.path.arc.nonempty 780 desc: arc() with a non-empty path does draw a straight line to the start point 781 code: | 782 ctx.fillStyle = '#f00'; 783 ctx.fillRect(0, 0, 100, 50); 784 ctx.lineWidth = 50; 785 ctx.strokeStyle = '#0f0'; 786 ctx.beginPath(); 787 ctx.moveTo(0, 25); 788 ctx.arc(200, 25, 5, 0, 2*Math.PI, true); 789 ctx.stroke(); 790 @assert pixel 50,25 == 0,255,0,255; 791 expected: green 792 793 - name: 2d.path.arc.end 794 desc: arc() adds the end point of the arc to the subpath 795 code: | 796 ctx.fillStyle = '#f00'; 797 ctx.fillRect(0, 0, 100, 50); 798 ctx.lineWidth = 50; 799 ctx.strokeStyle = '#0f0'; 800 ctx.beginPath(); 801 ctx.moveTo(-100, 0); 802 ctx.arc(-100, 0, 25, -Math.PI/2, Math.PI/2, true); 803 ctx.lineTo(100, 25); 804 ctx.stroke(); 805 @assert pixel 50,25 == 0,255,0,255; 806 expected: green 807 808 - name: 2d.path.arc.default 809 desc: arc() with missing last argument defaults to clockwise 810 code: | 811 ctx.fillStyle = '#0f0'; 812 ctx.fillRect(0, 0, 100, 50); 813 ctx.fillStyle = '#f00'; 814 ctx.beginPath(); 815 ctx.moveTo(100, 0); 816 ctx.arc(100, 0, 150, -Math.PI, Math.PI/2); 817 ctx.fill(); 818 @assert pixel 50,25 == 0,255,0,255; 819 expected: green 820 821 - name: 2d.path.arc.angle.1 822 desc: arc() draws pi/2 .. -pi anticlockwise correctly 823 code: | 824 ctx.fillStyle = '#0f0'; 825 ctx.fillRect(0, 0, 100, 50); 826 ctx.fillStyle = '#f00'; 827 ctx.beginPath(); 828 ctx.moveTo(100, 0); 829 ctx.arc(100, 0, 150, Math.PI/2, -Math.PI, true); 830 ctx.fill(); 831 @assert pixel 50,25 == 0,255,0,255; 832 expected: green 833 834 - name: 2d.path.arc.angle.2 835 desc: arc() draws -3pi/2 .. -pi anticlockwise correctly 836 code: | 837 ctx.fillStyle = '#0f0'; 838 ctx.fillRect(0, 0, 100, 50); 839 ctx.fillStyle = '#f00'; 840 ctx.beginPath(); 841 ctx.moveTo(100, 0); 842 ctx.arc(100, 0, 150, -3*Math.PI/2, -Math.PI, true); 843 ctx.fill(); 844 @assert pixel 50,25 == 0,255,0,255; 845 expected: green 846 847 - name: 2d.path.arc.angle.3 848 desc: arc() wraps angles mod 2pi when anticlockwise and end > start+2pi 849 code: | 850 ctx.fillStyle = '#0f0'; 851 ctx.fillRect(0, 0, 100, 50); 852 ctx.fillStyle = '#f00'; 853 ctx.beginPath(); 854 ctx.moveTo(100, 0); 855 ctx.arc(100, 0, 150, (512+1/2)*Math.PI, (1024-1)*Math.PI, true); 856 ctx.fill(); 857 @assert pixel 50,25 == 0,255,0,255; 858 expected: green 859 860 - name: 2d.path.arc.angle.4 861 desc: arc() draws a full circle when clockwise and end > start+2pi 862 code: | 863 ctx.fillStyle = '#f00'; 864 ctx.fillRect(0, 0, 100, 50); 865 ctx.fillStyle = '#0f0'; 866 ctx.beginPath(); 867 ctx.moveTo(50, 25); 868 ctx.arc(50, 25, 60, (512+1/2)*Math.PI, (1024-1)*Math.PI, false); 869 ctx.fill(); 870 @assert pixel 1,1 == 0,255,0,255; 871 @assert pixel 98,1 == 0,255,0,255; 872 @assert pixel 1,48 == 0,255,0,255; 873 @assert pixel 98,48 == 0,255,0,255; 874 expected: green 875 876 - name: 2d.path.arc.angle.5 877 desc: arc() wraps angles mod 2pi when clockwise and start > end+2pi 878 code: | 879 ctx.fillStyle = '#0f0'; 880 ctx.fillRect(0, 0, 100, 50); 881 ctx.fillStyle = '#f00'; 882 ctx.beginPath(); 883 ctx.moveTo(100, 0); 884 ctx.arc(100, 0, 150, (1024-1)*Math.PI, (512+1/2)*Math.PI, false); 885 ctx.fill(); 886 @assert pixel 50,25 == 0,255,0,255; 887 expected: green 888 889 - name: 2d.path.arc.angle.6 890 desc: arc() draws a full circle when anticlockwise and start > end+2pi 891 code: | 892 ctx.fillStyle = '#f00'; 893 ctx.fillRect(0, 0, 100, 50); 894 ctx.fillStyle = '#0f0'; 895 ctx.beginPath(); 896 ctx.moveTo(50, 25); 897 ctx.arc(50, 25, 60, (1024-1)*Math.PI, (512+1/2)*Math.PI, true); 898 ctx.fill(); 899 @assert pixel 1,1 == 0,255,0,255; 900 @assert pixel 98,1 == 0,255,0,255; 901 @assert pixel 1,48 == 0,255,0,255; 902 @assert pixel 98,48 == 0,255,0,255; 903 expected: green 904 905 - name: 2d.path.arc.zero.1 906 desc: arc() draws nothing when startAngle = endAngle and anticlockwise 907 code: | 908 ctx.fillStyle = '#0f0'; 909 ctx.fillRect(0, 0, 100, 50); 910 ctx.strokeStyle = '#f00'; 911 ctx.lineWidth = 100; 912 ctx.beginPath(); 913 ctx.arc(50, 25, 50, 0, 0, true); 914 ctx.stroke(); 915 @assert pixel 50,20 == 0,255,0,255; 916 expected: green 917 918 - name: 2d.path.arc.zero.2 919 desc: arc() draws nothing when startAngle = endAngle and clockwise 920 code: | 921 ctx.fillStyle = '#0f0'; 922 ctx.fillRect(0, 0, 100, 50); 923 ctx.strokeStyle = '#f00'; 924 ctx.lineWidth = 100; 925 ctx.beginPath(); 926 ctx.arc(50, 25, 50, 0, 0, false); 927 ctx.stroke(); 928 @assert pixel 50,20 == 0,255,0,255; 929 expected: green 930 931 - name: 2d.path.arc.twopie.1 932 desc: arc() draws nothing when end = start + 2pi-e and anticlockwise 933 code: | 934 ctx.fillStyle = '#0f0'; 935 ctx.fillRect(0, 0, 100, 50); 936 ctx.strokeStyle = '#f00'; 937 ctx.lineWidth = 100; 938 ctx.beginPath(); 939 ctx.arc(50, 25, 50, 0, 2*Math.PI - 1e-4, true); 940 ctx.stroke(); 941 @assert pixel 50,20 == 0,255,0,255; 942 expected: green 943 944 - name: 2d.path.arc.twopie.2 945 desc: arc() draws a full circle when end = start + 2pi-e and clockwise 946 code: | 947 ctx.fillStyle = '#f00'; 948 ctx.fillRect(0, 0, 100, 50); 949 ctx.strokeStyle = '#0f0'; 950 ctx.lineWidth = 100; 951 ctx.beginPath(); 952 ctx.arc(50, 25, 50, 0, 2*Math.PI - 1e-4, false); 953 ctx.stroke(); 954 @assert pixel 50,20 == 0,255,0,255; 955 expected: green 956 957 - name: 2d.path.arc.twopie.3 958 desc: arc() draws a full circle when end = start + 2pi+e and anticlockwise 959 code: | 960 ctx.fillStyle = '#f00'; 961 ctx.fillRect(0, 0, 100, 50); 962 ctx.strokeStyle = '#0f0'; 963 ctx.lineWidth = 100; 964 ctx.beginPath(); 965 ctx.arc(50, 25, 50, 0, 2*Math.PI + 1e-4, true); 966 ctx.stroke(); 967 @assert pixel 50,20 == 0,255,0,255; 968 expected: green 969 970 - name: 2d.path.arc.twopie.4 971 desc: arc() draws nothing when end = start + 2pi+e and clockwise 972 code: | 973 ctx.fillStyle = '#f00'; 974 ctx.fillRect(0, 0, 100, 50); 975 ctx.strokeStyle = '#0f0'; 976 ctx.lineWidth = 100; 977 ctx.beginPath(); 978 ctx.arc(50, 25, 50, 0, 2*Math.PI + 1e-4, false); 979 ctx.stroke(); 980 @assert pixel 50,20 == 0,255,0,255; 981 expected: green 982 983 - name: 2d.path.arc.twopie.5 984 desc: arc() draws correctly when start = 2 and end = start + 2pi+e and clockwise 985 code: | 986 ctx.fillStyle = '#fff'; 987 ctx.fillRect(0, 0, 100, 50); 988 ctx.fillStyle = '#000'; 989 ctx.beginPath(); 990 ctx.moveTo(50, 25); 991 ctx.arc(50, 25, 50, 2, 2 + 2*Math.PI, false); 992 ctx.closePath(); 993 ctx.fill(); 994 @assert pixel 95,25 == 0,0,0,255; 995 996 - name: 2d.path.arc.twopie.6 997 desc: arc() draws correctly when start = 5 and end = start + 2pi+e and clockwise 998 code: | 999 ctx.fillStyle = '#fff'; 1000 ctx.fillRect(0, 0, 100, 50); 1001 ctx.fillStyle = '#000'; 1002 ctx.beginPath(); 1003 ctx.moveTo(50, 25); 1004 ctx.arc(50, 25, 50, 5, 5 + 2*Math.PI, false); 1005 ctx.closePath(); 1006 ctx.fill(); 1007 @assert pixel 5,25 == 0,0,0,255; 1008 1009 - name: 2d.path.arc.shape.1 1010 desc: arc() from 0 to pi does not draw anything in the wrong half 1011 code: | 1012 ctx.fillStyle = '#0f0'; 1013 ctx.fillRect(0, 0, 100, 50); 1014 ctx.lineWidth = 50; 1015 ctx.strokeStyle = '#f00'; 1016 ctx.beginPath(); 1017 ctx.arc(50, 50, 50, 0, Math.PI, false); 1018 ctx.stroke(); 1019 @assert pixel 50,25 == 0,255,0,255; 1020 @assert pixel 1,1 == 0,255,0,255; 1021 @assert pixel 98,1 == 0,255,0,255; 1022 @assert pixel 1,48 == 0,255,0,255; 1023 @assert pixel 20,48 == 0,255,0,255; 1024 @assert pixel 98,48 == 0,255,0,255; 1025 expected: green 1026 1027 - name: 2d.path.arc.shape.2 1028 desc: arc() from 0 to pi draws stuff in the right half 1029 code: | 1030 ctx.fillStyle = '#f00'; 1031 ctx.fillRect(0, 0, 100, 50); 1032 ctx.lineWidth = 100; 1033 ctx.strokeStyle = '#0f0'; 1034 ctx.beginPath(); 1035 ctx.arc(50, 50, 50, 0, Math.PI, true); 1036 ctx.stroke(); 1037 @assert pixel 50,25 == 0,255,0,255; 1038 @assert pixel 1,1 == 0,255,0,255; 1039 @assert pixel 98,1 == 0,255,0,255; 1040 @assert pixel 1,48 == 0,255,0,255; 1041 @assert pixel 20,48 == 0,255,0,255; 1042 @assert pixel 98,48 == 0,255,0,255; 1043 expected: green 1044 1045 - name: 2d.path.arc.shape.3 1046 desc: arc() from 0 to -pi/2 does not draw anything in the wrong quadrant 1047 code: | 1048 ctx.fillStyle = '#0f0'; 1049 ctx.fillRect(0, 0, 100, 50); 1050 ctx.lineWidth = 100; 1051 ctx.strokeStyle = '#f00'; 1052 ctx.beginPath(); 1053 ctx.arc(0, 50, 50, 0, -Math.PI/2, false); 1054 ctx.stroke(); 1055 @assert pixel 50,25 == 0,255,0,255; 1056 @assert pixel 1,1 == 0,255,0,255; 1057 @assert pixel 98,1 == 0,255,0,255; 1058 @assert pixel 1,48 == 0,255,0,255; @moz-todo 1059 @assert pixel 98,48 == 0,255,0,255; 1060 expected: green 1061 1062 - name: 2d.path.arc.shape.4 1063 desc: arc() from 0 to -pi/2 draws stuff in the right quadrant 1064 code: | 1065 ctx.fillStyle = '#f00'; 1066 ctx.fillRect(0, 0, 100, 50); 1067 ctx.lineWidth = 150; 1068 ctx.strokeStyle = '#0f0'; 1069 ctx.beginPath(); 1070 ctx.arc(-50, 50, 100, 0, -Math.PI/2, true); 1071 ctx.stroke(); 1072 @assert pixel 50,25 == 0,255,0,255; 1073 @assert pixel 1,1 == 0,255,0,255; 1074 @assert pixel 98,1 == 0,255,0,255; 1075 @assert pixel 1,48 == 0,255,0,255; 1076 @assert pixel 98,48 == 0,255,0,255; 1077 expected: green 1078 1079 - name: 2d.path.arc.shape.5 1080 desc: arc() from 0 to 5pi does not draw crazy things 1081 code: | 1082 ctx.fillStyle = '#0f0'; 1083 ctx.fillRect(0, 0, 100, 50); 1084 ctx.lineWidth = 200; 1085 ctx.strokeStyle = '#f00'; 1086 ctx.beginPath(); 1087 ctx.arc(300, 0, 100, 0, 5*Math.PI, false); 1088 ctx.stroke(); 1089 @assert pixel 50,25 == 0,255,0,255; 1090 @assert pixel 1,1 == 0,255,0,255; 1091 @assert pixel 98,1 == 0,255,0,255; 1092 @assert pixel 1,48 == 0,255,0,255; 1093 @assert pixel 98,48 == 0,255,0,255; 1094 expected: green 1095 1096 - name: 2d.path.arc.selfintersect.1 1097 desc: arc() with lineWidth > 2*radius is drawn sensibly 1098 code: | 1099 ctx.fillStyle = '#0f0'; 1100 ctx.fillRect(0, 0, 100, 50); 1101 ctx.lineWidth = 200; 1102 ctx.strokeStyle = '#f00'; 1103 ctx.beginPath(); 1104 ctx.arc(100, 50, 25, 0, -Math.PI/2, true); 1105 ctx.stroke(); 1106 ctx.beginPath(); 1107 ctx.arc(0, 0, 25, 0, -Math.PI/2, true); 1108 ctx.stroke(); 1109 @assert pixel 1,1 == 0,255,0,255; @moz-todo 1110 @assert pixel 50,25 == 0,255,0,255; 1111 expected: green 1112 1113 - name: 2d.path.arc.selfintersect.2 1114 desc: arc() with lineWidth > 2*radius is drawn sensibly 1115 code: | 1116 ctx.fillStyle = '#f00'; 1117 ctx.fillRect(0, 0, 100, 50); 1118 ctx.lineWidth = 180; 1119 ctx.strokeStyle = '#0f0'; 1120 ctx.beginPath(); 1121 ctx.arc(-50, 50, 25, 0, -Math.PI/2, true); 1122 ctx.stroke(); 1123 ctx.beginPath(); 1124 ctx.arc(100, 0, 25, 0, -Math.PI/2, true); 1125 ctx.stroke(); 1126 @assert pixel 50,25 == 0,255,0,255; 1127 @assert pixel 90,10 == 0,255,0,255; 1128 @assert pixel 97,1 == 0,255,0,255; 1129 @assert pixel 97,2 == 0,255,0,255; 1130 @assert pixel 97,3 == 0,255,0,255; 1131 @assert pixel 2,48 == 0,255,0,255; 1132 expected: green 1133 1134 - name: 2d.path.arc.negative 1135 desc: arc() with negative radius throws INDEX_SIZE_ERR 1136 code: | 1137 @assert throws INDEX_SIZE_ERR ctx.arc(0, 0, -1, 0, 0, true); 1138 var path = new Path2D(); 1139 @assert throws INDEX_SIZE_ERR path.arc(10, 10, -5, 0, 1, false); 1140 1141 - name: 2d.path.arc.zeroradius 1142 desc: arc() with zero radius draws a line to the start point 1143 code: | 1144 ctx.fillStyle = '#f00' 1145 ctx.fillRect(0, 0, 100, 50); 1146 ctx.lineWidth = 50; 1147 ctx.strokeStyle = '#0f0'; 1148 ctx.beginPath(); 1149 ctx.moveTo(0, 25); 1150 ctx.arc(200, 25, 0, 0, Math.PI, true); 1151 ctx.stroke(); 1152 @assert pixel 50,25 == 0,255,0,255; 1153 expected: green 1154 1155 - name: 2d.path.arc.scale.1 1156 desc: Non-uniformly scaled arcs are the right shape 1157 code: | 1158 ctx.fillStyle = '#f00'; 1159 ctx.fillRect(0, 0, 100, 50); 1160 ctx.scale(2, 0.5); 1161 ctx.fillStyle = '#0f0'; 1162 ctx.beginPath(); 1163 ctx.arc(25, 50, 56, 0, 2*Math.PI, false); 1164 ctx.fill(); 1165 ctx.fillStyle = '#f00'; 1166 ctx.beginPath(); 1167 ctx.moveTo(-25, 50); 1168 ctx.arc(-25, 50, 24, 0, 2*Math.PI, false); 1169 ctx.moveTo(75, 50); 1170 ctx.arc(75, 50, 24, 0, 2*Math.PI, false); 1171 ctx.moveTo(25, -25); 1172 ctx.arc(25, -25, 24, 0, 2*Math.PI, false); 1173 ctx.moveTo(25, 125); 1174 ctx.arc(25, 125, 24, 0, 2*Math.PI, false); 1175 ctx.fill(); 1176 1177 @assert pixel 0,0 == 0,255,0,255; 1178 @assert pixel 50,0 == 0,255,0,255; 1179 @assert pixel 99,0 == 0,255,0,255; 1180 @assert pixel 0,25 == 0,255,0,255; 1181 @assert pixel 50,25 == 0,255,0,255; 1182 @assert pixel 99,25 == 0,255,0,255; 1183 @assert pixel 0,49 == 0,255,0,255; 1184 @assert pixel 50,49 == 0,255,0,255; 1185 @assert pixel 99,49 == 0,255,0,255; 1186 expected: green 1187 1188 - name: 2d.path.arc.scale.2 1189 desc: Highly scaled arcs are the right shape 1190 code: | 1191 ctx.fillStyle = '#f00'; 1192 ctx.fillRect(0, 0, 100, 50); 1193 ctx.scale(100, 100); 1194 ctx.strokeStyle = '#0f0'; 1195 ctx.lineWidth = 1.2; 1196 ctx.beginPath(); 1197 ctx.arc(0, 0, 0.6, 0, Math.PI/2, false); 1198 ctx.stroke(); 1199 1200 @assert pixel 1,1 == 0,255,0,255; 1201 @assert pixel 50,1 == 0,255,0,255; 1202 @assert pixel 98,1 == 0,255,0,255; 1203 @assert pixel 1,25 == 0,255,0,255; 1204 @assert pixel 50,25 == 0,255,0,255; 1205 @assert pixel 98,25 == 0,255,0,255; 1206 @assert pixel 1,48 == 0,255,0,255; 1207 @assert pixel 50,48 == 0,255,0,255; 1208 @assert pixel 98,48 == 0,255,0,255; 1209 expected: green 1210 1211 - name: 2d.path.arc.nonfinite 1212 desc: arc() with Infinity/NaN is ignored 1213 code: | 1214 ctx.fillStyle = '#f00'; 1215 ctx.fillRect(0, 0, 100, 50); 1216 ctx.moveTo(0, 0); 1217 ctx.lineTo(100, 0); 1218 @nonfinite ctx.arc(<0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <2*Math.PI Infinity -Infinity NaN>, <true>); 1219 ctx.lineTo(100, 50); 1220 ctx.lineTo(0, 50); 1221 ctx.fillStyle = '#0f0'; 1222 ctx.fill(); 1223 @assert pixel 50,25 == 0,255,0,255; 1224 @assert pixel 90,45 == 0,255,0,255; 1225 expected: green 1226 1227 - name: 2d.path.closed.arc 1228 desc: line caps should not be drawn on closed arcs 1229 size: [300, 300] 1230 code: | 1231 ctx.beginPath(); 1232 ctx.strokeStyle = 'red'; 1233 ctx.lineWidth = 20; 1234 ctx.lineCap = 'square'; 1235 ctx.arc(150, 150, 50, 0, 2 * Math.PI); 1236 ctx.closePath(); 1237 ctx.stroke(); 1238 // The pixel (209, 148) is part of the line cap, but not part of the circle. 1239 // Linecap is not drawn if the circle is closed, so the pixel is not red. 1240 assert_not_equals(ctx.getImageData(209, 148, 1, 1).data, [255, 0, 0, 255]) 1241 1242 - name: 2d.path.open.arc 1243 desc: line caps should be drawn on open arcs 1244 size: [300, 300] 1245 code: | 1246 ctx.beginPath(); 1247 ctx.strokeStyle = 'red'; 1248 ctx.lineWidth = 20; 1249 ctx.lineCap = 'square'; 1250 ctx.arc(150, 150, 50, 0, 2 * Math.PI); 1251 ctx.stroke(); 1252 // The pixel (209, 148) is part of the line cap, but not part of the circle. 1253 // Linecap is drawn with 360 degree arc, so the pixel is red. 1254 @assert pixel 209,148 ==~ 255,0,0,255 +/- 1; 1255 1256 - name: 2d.path.rect.basic 1257 code: | 1258 ctx.fillStyle = '#f00'; 1259 ctx.fillRect(0, 0, 100, 50); 1260 ctx.fillStyle = '#0f0'; 1261 ctx.rect(0, 0, 100, 50); 1262 ctx.fill(); 1263 @assert pixel 50,25 == 0,255,0,255; 1264 expected: green 1265 1266 - name: 2d.path.rect.newsubpath 1267 code: | 1268 ctx.fillStyle = '#0f0'; 1269 ctx.fillRect(0, 0, 100, 50); 1270 ctx.beginPath(); 1271 ctx.strokeStyle = '#f00'; 1272 ctx.lineWidth = 50; 1273 ctx.moveTo(-100, 25); 1274 ctx.lineTo(-50, 25); 1275 ctx.rect(200, 25, 1, 1); 1276 ctx.stroke(); 1277 @assert pixel 50,25 == 0,255,0,255; 1278 expected: green 1279 1280 - name: 2d.path.rect.closed 1281 code: | 1282 ctx.fillStyle = '#f00'; 1283 ctx.fillRect(0, 0, 100, 50); 1284 ctx.strokeStyle = '#0f0'; 1285 ctx.lineWidth = 200; 1286 ctx.lineJoin = 'miter'; 1287 ctx.rect(100, 50, 100, 100); 1288 ctx.stroke(); 1289 @assert pixel 50,25 == 0,255,0,255; 1290 expected: green 1291 1292 - name: 2d.path.rect.end.1 1293 code: | 1294 ctx.fillStyle = '#f00'; 1295 ctx.fillRect(0, 0, 100, 50); 1296 ctx.strokeStyle = '#0f0'; 1297 ctx.lineWidth = 100; 1298 ctx.rect(200, 100, 400, 1000); 1299 ctx.lineTo(-2000, -1000); 1300 ctx.stroke(); 1301 @assert pixel 50,25 == 0,255,0,255; 1302 expected: green 1303 1304 - name: 2d.path.rect.end.2 1305 code: | 1306 ctx.fillStyle = '#f00'; 1307 ctx.fillRect(0, 0, 100, 50); 1308 ctx.strokeStyle = '#0f0'; 1309 ctx.lineWidth = 450; 1310 ctx.lineCap = 'round'; 1311 ctx.lineJoin = 'bevel'; 1312 ctx.rect(150, 150, 2000, 2000); 1313 ctx.lineTo(160, 160); 1314 ctx.stroke(); 1315 @assert pixel 1,1 == 0,255,0,255; 1316 @assert pixel 98,1 == 0,255,0,255; 1317 @assert pixel 1,48 == 0,255,0,255; 1318 @assert pixel 98,48 == 0,255,0,255; 1319 expected: green 1320 1321 - name: 2d.path.rect.zero.1 1322 code: | 1323 ctx.fillStyle = '#f00'; 1324 ctx.fillRect(0, 0, 100, 50); 1325 ctx.strokeStyle = '#0f0'; 1326 ctx.lineWidth = 100; 1327 ctx.beginPath(); 1328 ctx.rect(0, 50, 100, 0); 1329 ctx.stroke(); 1330 @assert pixel 50,25 == 0,255,0,255; 1331 expected: green 1332 1333 - name: 2d.path.rect.zero.2 1334 code: | 1335 ctx.fillStyle = '#f00'; 1336 ctx.fillRect(0, 0, 100, 50); 1337 ctx.strokeStyle = '#0f0'; 1338 ctx.lineWidth = 100; 1339 ctx.beginPath(); 1340 ctx.rect(50, -100, 0, 250); 1341 ctx.stroke(); 1342 @assert pixel 50,25 == 0,255,0,255; 1343 expected: green 1344 1345 - name: 2d.path.rect.zero.3 1346 code: | 1347 ctx.fillStyle = '#0f0'; 1348 ctx.fillRect(0, 0, 100, 50); 1349 ctx.strokeStyle = '#f00'; 1350 ctx.lineWidth = 100; 1351 ctx.beginPath(); 1352 ctx.rect(50, 25, 0, 0); 1353 ctx.stroke(); 1354 @assert pixel 50,25 == 0,255,0,255; 1355 expected: green 1356 1357 - name: 2d.path.rect.zero.4 1358 code: | 1359 ctx.fillStyle = '#f00'; 1360 ctx.fillRect(0, 0, 100, 50); 1361 ctx.strokeStyle = '#0f0'; 1362 ctx.lineWidth = 50; 1363 ctx.rect(100, 25, 0, 0); 1364 ctx.lineTo(0, 25); 1365 ctx.stroke(); 1366 @assert pixel 50,25 == 0,255,0,255; 1367 expected: green 1368 1369 - name: 2d.path.rect.zero.5 1370 code: | 1371 ctx.fillStyle = '#0f0'; 1372 ctx.fillRect(0, 0, 100, 50); 1373 ctx.strokeStyle = '#f00'; 1374 ctx.lineWidth = 50; 1375 ctx.moveTo(0, 0); 1376 ctx.rect(100, 25, 0, 0); 1377 ctx.stroke(); 1378 @assert pixel 50,25 == 0,255,0,255; 1379 expected: green 1380 1381 - name: 2d.path.rect.zero.6 1382 #mozilla: { bug: TODO } 1383 code: | 1384 ctx.fillStyle = '#0f0'; 1385 ctx.fillRect(0, 0, 100, 50); 1386 ctx.strokeStyle = '#f00'; 1387 ctx.lineJoin = 'miter'; 1388 ctx.miterLimit = 1.5; 1389 ctx.lineWidth = 200; 1390 ctx.beginPath(); 1391 ctx.rect(100, 25, 1000, 0); 1392 ctx.stroke(); 1393 @assert pixel 50,25 == 0,255,0,255; @moz-todo 1394 expected: green 1395 1396 - name: 2d.path.rect.negative 1397 code: | 1398 ctx.fillStyle = '#f00'; 1399 ctx.fillRect(0, 0, 100, 50); 1400 ctx.beginPath(); 1401 ctx.fillStyle = '#0f0'; 1402 ctx.rect(0, 0, 50, 25); 1403 ctx.rect(100, 0, -50, 25); 1404 ctx.rect(0, 50, 50, -25); 1405 ctx.rect(100, 50, -50, -25); 1406 ctx.fill(); 1407 @assert pixel 25,12 == 0,255,0,255; 1408 @assert pixel 75,12 == 0,255,0,255; 1409 @assert pixel 25,37 == 0,255,0,255; 1410 @assert pixel 75,37 == 0,255,0,255; 1411 1412 - name: 2d.path.rect.winding 1413 code: | 1414 ctx.fillStyle = '#0f0'; 1415 ctx.fillRect(0, 0, 100, 50); 1416 ctx.beginPath(); 1417 ctx.fillStyle = '#f00'; 1418 ctx.rect(0, 0, 50, 50); 1419 ctx.rect(100, 50, -50, -50); 1420 ctx.rect(0, 25, 100, -25); 1421 ctx.rect(100, 25, -100, 25); 1422 ctx.fill(); 1423 @assert pixel 25,12 == 0,255,0,255; 1424 @assert pixel 75,12 == 0,255,0,255; 1425 @assert pixel 25,37 == 0,255,0,255; 1426 @assert pixel 75,37 == 0,255,0,255; 1427 1428 - name: 2d.path.rect.selfintersect 1429 #mozilla: { bug: TODO } 1430 code: | 1431 ctx.fillStyle = '#f00'; 1432 ctx.fillRect(0, 0, 100, 50); 1433 ctx.strokeStyle = '#0f0'; 1434 ctx.lineWidth = 90; 1435 ctx.beginPath(); 1436 ctx.rect(45, 20, 10, 10); 1437 ctx.stroke(); 1438 @assert pixel 50,25 == 0,255,0,255; @moz-todo 1439 expected: green 1440 1441 - name: 2d.path.rect.nonfinite 1442 desc: rect() with Infinity/NaN is ignored 1443 code: | 1444 ctx.moveTo(0, 0); 1445 ctx.lineTo(100, 0); 1446 @nonfinite ctx.rect(<0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <1 Infinity -Infinity NaN>, <1 Infinity -Infinity NaN>); 1447 ctx.lineTo(100, 50); 1448 ctx.lineTo(0, 50); 1449 ctx.fillStyle = '#0f0'; 1450 ctx.fill(); 1451 @assert pixel 50,25 == 0,255,0,255; 1452 @assert pixel 90,45 == 0,255,0,255; 1453 expected: green 1454 1455 - name: 2d.path.roundrect.newsubpath 1456 code: | 1457 ctx.fillStyle = '#0f0'; 1458 ctx.fillRect(0, 0, 100, 50); 1459 ctx.beginPath(); 1460 ctx.strokeStyle = '#f00'; 1461 ctx.lineWidth = 50; 1462 ctx.moveTo(-100, 25); 1463 ctx.lineTo(-50, 25); 1464 ctx.roundRect(200, 25, 1, 1, [0]); 1465 ctx.stroke(); 1466 @assert pixel 50,25 == 0,255,0,255; 1467 expected: green 1468 1469 - name: 2d.path.roundrect.closed 1470 code: | 1471 ctx.fillStyle = '#f00'; 1472 ctx.fillRect(0, 0, 100, 50); 1473 ctx.strokeStyle = '#0f0'; 1474 ctx.lineWidth = 200; 1475 ctx.lineJoin = 'miter'; 1476 ctx.roundRect(100, 50, 100, 100, [0]); 1477 ctx.stroke(); 1478 @assert pixel 50,25 == 0,255,0,255; 1479 expected: green 1480 1481 - name: 2d.path.roundrect.end.1 1482 code: | 1483 ctx.fillStyle = '#f00'; 1484 ctx.fillRect(0, 0, 100, 50); 1485 ctx.strokeStyle = '#0f0'; 1486 ctx.lineWidth = 100; 1487 ctx.roundRect(200, 100, 400, 1000, [0]); 1488 ctx.lineTo(-2000, -1000); 1489 ctx.stroke(); 1490 @assert pixel 50,25 == 0,255,0,255; 1491 expected: green 1492 1493 - name: 2d.path.roundrect.end.2 1494 code: | 1495 ctx.fillStyle = '#f00'; 1496 ctx.fillRect(0, 0, 100, 50); 1497 ctx.strokeStyle = '#0f0'; 1498 ctx.lineWidth = 450; 1499 ctx.lineCap = 'round'; 1500 ctx.lineJoin = 'bevel'; 1501 ctx.roundRect(150, 150, 2000, 2000, [0]); 1502 ctx.lineTo(160, 160); 1503 ctx.stroke(); 1504 @assert pixel 1,1 == 0,255,0,255; 1505 @assert pixel 98,1 == 0,255,0,255; 1506 @assert pixel 1,48 == 0,255,0,255; 1507 @assert pixel 98,48 == 0,255,0,255; 1508 expected: green 1509 1510 - name: 2d.path.roundrect.end.3 1511 code: | 1512 ctx.fillStyle = '#f00'; 1513 ctx.fillRect(0, 0, 100, 50); 1514 ctx.strokeStyle = '#0f0'; 1515 ctx.lineWidth = 100; 1516 ctx.roundRect(101, 51, 2000, 2000, [500, 500, 500, 500]); 1517 ctx.lineTo(-1, -1); 1518 ctx.stroke(); 1519 @assert pixel 1,1 == 0,255,0,255; 1520 @assert pixel 98,1 == 0,255,0,255; 1521 @assert pixel 1,48 == 0,255,0,255; 1522 @assert pixel 98,48 == 0,255,0,255; 1523 expected: green 1524 1525 - name: 2d.path.roundrect.end.4 1526 code: | 1527 ctx.fillStyle = '#0f0'; 1528 ctx.fillRect(0, 0, 100, 50); 1529 ctx.strokeStyle = '#f00'; 1530 ctx.lineWidth = 10; 1531 ctx.roundRect(-1, -1, 2000, 2000, [1000, 1000, 1000, 1000]); 1532 ctx.lineTo(-150, -150); 1533 ctx.stroke(); 1534 @assert pixel 1,1 == 0,255,0,255; 1535 @assert pixel 98,1 == 0,255,0,255; 1536 @assert pixel 1,48 == 0,255,0,255; 1537 @assert pixel 98,48 == 0,255,0,255; 1538 expected: green 1539 1540 - name: 2d.path.roundrect.zero.1 1541 code: | 1542 ctx.fillStyle = '#f00'; 1543 ctx.fillRect(0, 0, 100, 50); 1544 ctx.strokeStyle = '#0f0'; 1545 ctx.lineWidth = 100; 1546 ctx.beginPath(); 1547 ctx.roundRect(0, 50, 100, 0, [0]); 1548 ctx.stroke(); 1549 @assert pixel 50,25 == 0,255,0,255; 1550 expected: green 1551 1552 - name: 2d.path.roundrect.zero.2 1553 code: | 1554 ctx.fillStyle = '#f00'; 1555 ctx.fillRect(0, 0, 100, 50); 1556 ctx.strokeStyle = '#0f0'; 1557 ctx.lineWidth = 100; 1558 ctx.beginPath(); 1559 ctx.roundRect(50, -100, 0, 250, [0]); 1560 ctx.stroke(); 1561 @assert pixel 50,25 == 0,255,0,255; 1562 expected: green 1563 1564 - name: 2d.path.roundrect.zero.3 1565 code: | 1566 ctx.fillStyle = '#0f0'; 1567 ctx.fillRect(0, 0, 100, 50); 1568 ctx.strokeStyle = '#f00'; 1569 ctx.lineWidth = 100; 1570 ctx.beginPath(); 1571 ctx.roundRect(50, 25, 0, 0, [0]); 1572 ctx.stroke(); 1573 @assert pixel 50,25 == 0,255,0,255; 1574 expected: green 1575 1576 - name: 2d.path.roundrect.zero.4 1577 code: | 1578 ctx.fillStyle = '#f00'; 1579 ctx.fillRect(0, 0, 100, 50); 1580 ctx.strokeStyle = '#0f0'; 1581 ctx.lineWidth = 50; 1582 ctx.roundRect(100, 25, 0, 0, [0]); 1583 ctx.lineTo(0, 25); 1584 ctx.stroke(); 1585 @assert pixel 50,25 == 0,255,0,255; 1586 expected: green 1587 1588 - name: 2d.path.roundrect.zero.5 1589 code: | 1590 ctx.fillStyle = '#0f0'; 1591 ctx.fillRect(0, 0, 100, 50); 1592 ctx.strokeStyle = '#f00'; 1593 ctx.lineWidth = 50; 1594 ctx.moveTo(0, 0); 1595 ctx.roundRect(100, 25, 0, 0, [0]); 1596 ctx.stroke(); 1597 @assert pixel 50,25 == 0,255,0,255; 1598 expected: green 1599 1600 - name: 2d.path.roundrect.zero.6 1601 code: | 1602 ctx.fillStyle = '#0f0'; 1603 ctx.fillRect(0, 0, 100, 50); 1604 ctx.strokeStyle = '#f00'; 1605 ctx.lineJoin = 'miter'; 1606 ctx.miterLimit = 1.5; 1607 ctx.lineWidth = 200; 1608 ctx.beginPath(); 1609 ctx.roundRect(100, 25, 1000, 0, [0]); 1610 ctx.stroke(); 1611 @assert pixel 50,25 == 0,255,0,255; 1612 expected: green 1613 1614 - name: 2d.path.roundrect.negative 1615 code: | 1616 ctx.fillStyle = '#f00'; 1617 ctx.fillRect(0, 0, 100, 50); 1618 ctx.beginPath(); 1619 ctx.fillStyle = '#0f0'; 1620 ctx.roundRect(0, 0, 50, 25, [10, 0, 0, 0]); 1621 ctx.roundRect(100, 0, -50, 25, [10, 0, 0, 0]); 1622 ctx.roundRect(0, 50, 50, -25, [10, 0, 0, 0]); 1623 ctx.roundRect(100, 50, -50, -25, [10, 0, 0, 0]); 1624 ctx.fill(); 1625 // All rects drawn 1626 @assert pixel 25,12 == 0,255,0,255; 1627 @assert pixel 75,12 == 0,255,0,255; 1628 @assert pixel 25,37 == 0,255,0,255; 1629 @assert pixel 75,37 == 0,255,0,255; 1630 // Correct corners are rounded. 1631 @assert pixel 1,1 == 255,0,0,255; 1632 @assert pixel 98,1 == 255,0,0,255; 1633 @assert pixel 1,48 == 255,0,0,255; 1634 @assert pixel 98,48 == 255,0,0,255; 1635 1636 - name: 2d.path.roundrect.winding 1637 code: | 1638 ctx.fillStyle = '#0f0'; 1639 ctx.fillRect(0, 0, 100, 50); 1640 ctx.beginPath(); 1641 ctx.fillStyle = '#f00'; 1642 ctx.roundRect(0, 0, 50, 50, [0]); 1643 ctx.roundRect(100, 50, -50, -50, [0]); 1644 ctx.roundRect(0, 25, 100, -25, [0]); 1645 ctx.roundRect(100, 25, -100, 25, [0]); 1646 ctx.fill(); 1647 @assert pixel 25,12 == 0,255,0,255; 1648 @assert pixel 75,12 == 0,255,0,255; 1649 @assert pixel 25,37 == 0,255,0,255; 1650 @assert pixel 75,37 == 0,255,0,255; 1651 1652 - name: 2d.path.roundrect.selfintersect 1653 code: | 1654 ctx.fillStyle = '#f00'; 1655 ctx.roundRect(0, 0, 100, 50, [0]); 1656 ctx.strokeStyle = '#0f0'; 1657 ctx.lineWidth = 90; 1658 ctx.beginPath(); 1659 ctx.roundRect(45, 20, 10, 10, [0]); 1660 ctx.stroke(); 1661 @assert pixel 50,25 == 0,255,0,255; 1662 expected: green 1663 1664 - name: 2d.path.roundrect.nonfinite 1665 desc: roundRect() with Infinity/NaN is ignored 1666 code: | 1667 ctx.fillStyle = '#f00'; 1668 ctx.fillRect(0, 0, 100, 50) 1669 ctx.moveTo(0, 0); 1670 ctx.lineTo(100, 0); 1671 @nonfinite ctx.roundRect(<0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <1 Infinity -Infinity NaN>, <1 Infinity -Infinity NaN>, <[0] [Infinity] [-Infinity] [NaN] [Infinity,0] [-Infinity,0] [NaN,0] [0,Infinity] [0,-Infinity] [0,NaN] [Infinity,0,0] [-Infinity,0,0] [NaN,0,0] [0,Infinity,0] [0,-Infinity,0] [0,NaN,0] [0,0,Infinity] [0,0,-Infinity] [0,0,NaN] [Infinity,0,0,0] [-Infinity,0,0,0] [NaN,0,0,0] [0,Infinity,0,0] [0,-Infinity,0,0] [0,NaN,0,0] [0,0,Infinity,0] [0,0,-Infinity,0] [0,0,NaN,0] [0,0,0,Infinity] [0,0,0,-Infinity] [0,0,0,NaN]>); 1672 ctx.roundRect(0, 0, 100, 100, [new DOMPoint(10, Infinity)]); 1673 ctx.roundRect(0, 0, 100, 100, [new DOMPoint(10, -Infinity)]); 1674 ctx.roundRect(0, 0, 100, 100, [new DOMPoint(10, NaN)]); 1675 ctx.roundRect(0, 0, 100, 100, [new DOMPoint(Infinity, 10)]); 1676 ctx.roundRect(0, 0, 100, 100, [new DOMPoint(-Infinity, 10)]); 1677 ctx.roundRect(0, 0, 100, 100, [new DOMPoint(NaN, 10)]); 1678 ctx.roundRect(0, 0, 100, 100, [{x: 10, y: Infinity}]); 1679 ctx.roundRect(0, 0, 100, 100, [{x: 10, y: -Infinity}]); 1680 ctx.roundRect(0, 0, 100, 100, [{x: 10, y: NaN}]); 1681 ctx.roundRect(0, 0, 100, 100, [{x: Infinity, y: 10}]); 1682 ctx.roundRect(0, 0, 100, 100, [{x: -Infinity, y: 10}]); 1683 ctx.roundRect(0, 0, 100, 100, [{x: NaN, y: 10}]); 1684 ctx.lineTo(100, 50); 1685 ctx.lineTo(0, 50); 1686 ctx.fillStyle = '#0f0'; 1687 ctx.fill(); 1688 @assert pixel 50,25 == 0,255,0,255; 1689 @assert pixel 90,45 == 0,255,0,255; 1690 expected: green 1691 1692 - name: 2d.path.roundrect.4.radii.1.double 1693 desc: Verify that when four radii are given to roundRect(), the first radius, specified as a double, applies to the top-left corner. 1694 code: | 1695 ctx.fillStyle = '#f00'; 1696 ctx.fillRect(0, 0, 100, 50); 1697 ctx.roundRect(0, 0, 100, 50, [20, 0, 0, 0]); 1698 ctx.fillStyle = '#0f0'; 1699 ctx.fill(); 1700 @assert pixel 1,1 == 255,0,0,255; 1701 @assert pixel 98,1 == 0,255,0,255; 1702 @assert pixel 98,48 == 0,255,0,255; 1703 @assert pixel 1,48 == 0,255,0,255; 1704 1705 - name: 2d.path.roundrect.4.radii.1.dompoint 1706 desc: Verify that when four radii are given to roundRect(), the first radius, specified as a DOMPoint, applies to the top-left corner. 1707 code: | 1708 ctx.fillStyle = '#f00'; 1709 ctx.fillRect(0, 0, 100, 50); 1710 ctx.roundRect(0, 0, 100, 50, [new DOMPoint(40, 20), 0, 0, 0]); 1711 ctx.fillStyle = '#0f0'; 1712 ctx.fill(); 1713 1714 // top-left corner 1715 @assert pixel 20,1 == 255,0,0,255; 1716 @assert pixel 41,1 == 0,255,0,255; 1717 @assert pixel 1,10 == 255,0,0,255; 1718 @assert pixel 1,21 == 0,255,0,255; 1719 1720 // other corners 1721 @assert pixel 98,1 == 0,255,0,255; 1722 @assert pixel 98,48 == 0,255,0,255; 1723 @assert pixel 1,48 == 0,255,0,255; 1724 1725 - name: 2d.path.roundrect.4.radii.1.dompointinit 1726 desc: Verify that when four radii are given to roundRect(), the first radius, specified as a DOMPointInit, applies to the top-left corner. 1727 code: | 1728 ctx.fillStyle = '#f00'; 1729 ctx.fillRect(0, 0, 100, 50); 1730 ctx.roundRect(0, 0, 100, 50, [{x: 40, y: 20}, 0, 0, 0]); 1731 ctx.fillStyle = '#0f0'; 1732 ctx.fill(); 1733 1734 // top-left corner 1735 @assert pixel 20,1 == 255,0,0,255; 1736 @assert pixel 41,1 == 0,255,0,255; 1737 @assert pixel 1,10 == 255,0,0,255; 1738 @assert pixel 1,21 == 0,255,0,255; 1739 1740 // other corners 1741 @assert pixel 98,1 == 0,255,0,255; 1742 @assert pixel 98,48 == 0,255,0,255; 1743 @assert pixel 1,48 == 0,255,0,255; 1744 1745 - name: 2d.path.roundrect.4.radii.2.double 1746 desc: Verify that when four radii are given to roundRect(), the second radius, specified as a double, applies to the top-right corner. 1747 code: | 1748 ctx.fillStyle = '#f00'; 1749 ctx.fillRect(0, 0, 100, 50); 1750 ctx.roundRect(0, 0, 100, 50, [0, 20, 0, 0]); 1751 ctx.fillStyle = '#0f0'; 1752 ctx.fill(); 1753 @assert pixel 1,1 == 0,255,0,255; 1754 @assert pixel 98,1 == 255,0,0,255; 1755 @assert pixel 98,48 == 0,255,0,255; 1756 @assert pixel 1,48 == 0,255,0,255; 1757 1758 - name: 2d.path.roundrect.4.radii.2.dompoint 1759 desc: Verify that when four radii are given to roundRect(), the second radius, specified as a DOMPoint, applies to the top-right corner. 1760 code: | 1761 ctx.fillStyle = '#f00'; 1762 ctx.fillRect(0, 0, 100, 50); 1763 ctx.roundRect(0, 0, 100, 50, [0, new DOMPoint(40, 20), 0, 0]); 1764 ctx.fillStyle = '#0f0'; 1765 ctx.fill(); 1766 1767 // top-right corner 1768 @assert pixel 79,1 == 255,0,0,255; 1769 @assert pixel 58,1 == 0,255,0,255; 1770 @assert pixel 98,10 == 255,0,0,255; 1771 @assert pixel 98,21 == 0,255,0,255; 1772 1773 // other corners 1774 @assert pixel 1,1 == 0,255,0,255; 1775 @assert pixel 98,48 == 0,255,0,255; 1776 @assert pixel 1,48 == 0,255,0,255; 1777 1778 - name: 2d.path.roundrect.4.radii.2.dompointinit 1779 desc: Verify that when four radii are given to roundRect(), the second radius, specified as a DOMPointInit, applies to the top-right corner. 1780 code: | 1781 ctx.fillStyle = '#f00'; 1782 ctx.fillRect(0, 0, 100, 50); 1783 ctx.roundRect(0, 0, 100, 50, [0, {x: 40, y: 20}, 0, 0]); 1784 ctx.fillStyle = '#0f0'; 1785 ctx.fill(); 1786 1787 // top-right corner 1788 @assert pixel 79,1 == 255,0,0,255; 1789 @assert pixel 58,1 == 0,255,0,255; 1790 @assert pixel 98,10 == 255,0,0,255; 1791 @assert pixel 98,21 == 0,255,0,255; 1792 1793 // other corners 1794 @assert pixel 1,1 == 0,255,0,255; 1795 @assert pixel 98,48 == 0,255,0,255; 1796 @assert pixel 1,48 == 0,255,0,255; 1797 1798 - name: 2d.path.roundrect.4.radii.3.double 1799 desc: Verify that when four radii are given to roundRect(), the third radius, specified as a double, applies to the bottom-right corner. 1800 code: | 1801 ctx.fillStyle = '#f00'; 1802 ctx.fillRect(0, 0, 100, 50); 1803 ctx.roundRect(0, 0, 100, 50, [0, 0, 20, 0]); 1804 ctx.fillStyle = '#0f0'; 1805 ctx.fill(); 1806 @assert pixel 1,1 == 0,255,0,255; 1807 @assert pixel 98,1 == 0,255,0,255; 1808 @assert pixel 98,48 == 255,0,0,255; 1809 @assert pixel 1,48 == 0,255,0,255; 1810 1811 - name: 2d.path.roundrect.4.radii.3.dompoint 1812 desc: Verify that when four radii are given to roundRect(), the third radius, specified as a DOMPoint, applies to the bottom-right corner. 1813 code: | 1814 ctx.fillStyle = '#f00'; 1815 ctx.fillRect(0, 0, 100, 50); 1816 ctx.roundRect(0, 0, 100, 50, [0, 0, new DOMPoint(40, 20), 0]); 1817 ctx.fillStyle = '#0f0'; 1818 ctx.fill(); 1819 1820 // bottom-right corner 1821 @assert pixel 79,48 == 255,0,0,255; 1822 @assert pixel 58,48 == 0,255,0,255; 1823 @assert pixel 98,39 == 255,0,0,255; 1824 @assert pixel 98,28 == 0,255,0,255; 1825 1826 // other corners 1827 @assert pixel 1,1 == 0,255,0,255; 1828 @assert pixel 98,1 == 0,255,0,255; 1829 @assert pixel 1,48 == 0,255,0,255; 1830 1831 - name: 2d.path.roundrect.4.radii.3.dompointinit 1832 desc: Verify that when four radii are given to roundRect(), the third radius, specified as a DOMPointInit, applies to the bottom-right corner. 1833 code: | 1834 ctx.fillStyle = '#f00'; 1835 ctx.fillRect(0, 0, 100, 50); 1836 ctx.roundRect(0, 0, 100, 50, [0, 0, {x: 40, y: 20}, 0]); 1837 ctx.fillStyle = '#0f0'; 1838 ctx.fill(); 1839 1840 // bottom-right corner 1841 @assert pixel 79,48 == 255,0,0,255; 1842 @assert pixel 58,48 == 0,255,0,255; 1843 @assert pixel 98,39 == 255,0,0,255; 1844 @assert pixel 98,28 == 0,255,0,255; 1845 1846 // other corners 1847 @assert pixel 1,1 == 0,255,0,255; 1848 @assert pixel 98,1 == 0,255,0,255; 1849 @assert pixel 1,48 == 0,255,0,255; 1850 1851 - name: 2d.path.roundrect.4.radii.4.double 1852 desc: Verify that when four radii are given to roundRect(), the fourth radius, specified as a double, applies to the bottom-left corner. 1853 code: | 1854 ctx.fillStyle = '#f00'; 1855 ctx.fillRect(0, 0, 100, 50); 1856 ctx.roundRect(0, 0, 100, 50, [0, 0, 0, 20]); 1857 ctx.fillStyle = '#0f0'; 1858 ctx.fill(); 1859 @assert pixel 1,1 == 0,255,0,255; 1860 @assert pixel 98,1 == 0,255,0,255; 1861 @assert pixel 98,48 == 0,255,0,255; 1862 @assert pixel 1,48 == 255,0,0,255; 1863 1864 - name: 2d.path.roundrect.4.radii.4.dompoint 1865 desc: Verify that when four radii are given to roundRect(), the fourth radius, specified as a DOMPoint, applies to the bottom-left corner. 1866 code: | 1867 ctx.fillStyle = '#f00'; 1868 ctx.fillRect(0, 0, 100, 50); 1869 ctx.roundRect(0, 0, 100, 50, [0, 0, 0, new DOMPoint(40, 20)]); 1870 ctx.fillStyle = '#0f0'; 1871 ctx.fill(); 1872 1873 // bottom-left corner 1874 @assert pixel 20,48 == 255,0,0,255; 1875 @assert pixel 41,48 == 0,255,0,255; 1876 @assert pixel 1,39 == 255,0,0,255; 1877 @assert pixel 1,28 == 0,255,0,255; 1878 1879 // other corners 1880 @assert pixel 1,1 == 0,255,0,255; 1881 @assert pixel 98,1 == 0,255,0,255; 1882 @assert pixel 98,48 == 0,255,0,255; 1883 1884 - name: 2d.path.roundrect.4.radii.4.dompointinit 1885 desc: Verify that when four radii are given to roundRect(), the fourth radius, specified as a DOMPointInit, applies to the bottom-left corner. 1886 code: | 1887 ctx.fillStyle = '#f00'; 1888 ctx.fillRect(0, 0, 100, 50); 1889 ctx.roundRect(0, 0, 100, 50, [0, 0, 0, {x: 40, y: 20}]); 1890 ctx.fillStyle = '#0f0'; 1891 ctx.fill(); 1892 1893 // bottom-left corner 1894 @assert pixel 20,48 == 255,0,0,255; 1895 @assert pixel 41,48 == 0,255,0,255; 1896 @assert pixel 1,39 == 255,0,0,255; 1897 @assert pixel 1,28 == 0,255,0,255; 1898 1899 // other corners 1900 @assert pixel 1,1 == 0,255,0,255; 1901 @assert pixel 98,1 == 0,255,0,255; 1902 @assert pixel 98,48 == 0,255,0,255; 1903 1904 - name: 2d.path.roundrect.3.radii.1.double 1905 desc: Verify that when three radii are given to roundRect(), the first radius, specified as a double, applies to the top-left corner. 1906 code: | 1907 ctx.fillStyle = '#f00'; 1908 ctx.fillRect(0, 0, 100, 50); 1909 ctx.roundRect(0, 0, 100, 50, [20, 0, 0]); 1910 ctx.fillStyle = '#0f0'; 1911 ctx.fill(); 1912 @assert pixel 1,1 == 255,0,0,255; 1913 @assert pixel 98,1 == 0,255,0,255; 1914 @assert pixel 98,48 == 0,255,0,255; 1915 @assert pixel 1,48 == 0,255,0,255; 1916 1917 - name: 2d.path.roundrect.3.radii.1.dompoint 1918 desc: Verify that when three radii are given to roundRect(), the first radius, specified as a DOMPoint, applies to the top-left corner. 1919 code: | 1920 ctx.fillStyle = '#f00'; 1921 ctx.fillRect(0, 0, 100, 50); 1922 ctx.roundRect(0, 0, 100, 50, [new DOMPoint(40, 20), 0, 0]); 1923 ctx.fillStyle = '#0f0'; 1924 ctx.fill(); 1925 1926 // top-left corner 1927 @assert pixel 20,1 == 255,0,0,255; 1928 @assert pixel 41,1 == 0,255,0,255; 1929 @assert pixel 1,10 == 255,0,0,255; 1930 @assert pixel 1,21 == 0,255,0,255; 1931 1932 // other corners 1933 @assert pixel 98,1 == 0,255,0,255; 1934 @assert pixel 98,48 == 0,255,0,255; 1935 @assert pixel 1,48 == 0,255,0,255; 1936 1937 - name: 2d.path.roundrect.3.radii.1.dompointinit 1938 desc: Verify that when three radii are given to roundRect(), the first radius, specified as a DOMPointInit, applies to the top-left corner. 1939 code: | 1940 ctx.fillStyle = '#f00'; 1941 ctx.fillRect(0, 0, 100, 50); 1942 ctx.roundRect(0, 0, 100, 50, [{x: 40, y: 20}, 0, 0]); 1943 ctx.fillStyle = '#0f0'; 1944 ctx.fill(); 1945 1946 // top-left corner 1947 @assert pixel 20,1 == 255,0,0,255; 1948 @assert pixel 41,1 == 0,255,0,255; 1949 @assert pixel 1,10 == 255,0,0,255; 1950 @assert pixel 1,21 == 0,255,0,255; 1951 1952 // other corners 1953 @assert pixel 98,1 == 0,255,0,255; 1954 @assert pixel 98,48 == 0,255,0,255; 1955 @assert pixel 1,48 == 0,255,0,255; 1956 1957 - name: 2d.path.roundrect.3.radii.2.double 1958 desc: Verify that when three radii are given to roundRect(), the second radius, specified as a double, applies to the top-right and bottom-left corners. 1959 code: | 1960 ctx.fillStyle = '#f00'; 1961 ctx.fillRect(0, 0, 100, 50); 1962 ctx.roundRect(0, 0, 100, 50, [0, 20, 0]); 1963 ctx.fillStyle = '#0f0'; 1964 ctx.fill(); 1965 @assert pixel 1,1 == 0,255,0,255; 1966 @assert pixel 98,1 == 255,0,0,255; 1967 @assert pixel 98,48 == 0,255,0,255; 1968 @assert pixel 1,48 == 255,0,0,255; 1969 1970 - name: 2d.path.roundrect.3.radii.2.dompoint 1971 desc: Verify that when three radii are given to roundRect(), the second radius, specified as a DOMPoint, applies to the top-right and bottom-left corners. 1972 code: | 1973 ctx.fillStyle = '#f00'; 1974 ctx.fillRect(0, 0, 100, 50); 1975 ctx.roundRect(0, 0, 100, 50, [0, new DOMPoint(40, 20), 0]); 1976 ctx.fillStyle = '#0f0'; 1977 ctx.fill(); 1978 1979 // top-right corner 1980 @assert pixel 79,1 == 255,0,0,255; 1981 @assert pixel 58,1 == 0,255,0,255; 1982 @assert pixel 98,10 == 255,0,0,255; 1983 @assert pixel 98,21 == 0,255,0,255; 1984 1985 // bottom-left corner 1986 @assert pixel 20,48 == 255,0,0,255; 1987 @assert pixel 41,48 == 0,255,0,255; 1988 @assert pixel 1,39 == 255,0,0,255; 1989 @assert pixel 1,28 == 0,255,0,255; 1990 1991 // other corners 1992 @assert pixel 1,1 == 0,255,0,255; 1993 @assert pixel 98,48 == 0,255,0,255; 1994 1995 - name: 2d.path.roundrect.3.radii.2.dompointinit 1996 desc: Verify that when three radii are given to roundRect(), the second radius, specified as a DOMPoint, applies to the top-right and bottom-left corners. 1997 code: | 1998 ctx.fillStyle = '#f00'; 1999 ctx.fillRect(0, 0, 100, 50); 2000 ctx.roundRect(0, 0, 100, 50, [0, {x: 40, y: 20}, 0]); 2001 ctx.fillStyle = '#0f0'; 2002 ctx.fill(); 2003 2004 // top-right corner 2005 @assert pixel 79,1 == 255,0,0,255; 2006 @assert pixel 58,1 == 0,255,0,255; 2007 @assert pixel 98,10 == 255,0,0,255; 2008 @assert pixel 98,21 == 0,255,0,255; 2009 2010 // bottom-left corner 2011 @assert pixel 20,48 == 255,0,0,255; 2012 @assert pixel 41,48 == 0,255,0,255; 2013 @assert pixel 1,39 == 255,0,0,255; 2014 @assert pixel 1,28 == 0,255,0,255; 2015 2016 // other corners 2017 @assert pixel 1,1 == 0,255,0,255; 2018 @assert pixel 98,48 == 0,255,0,255; 2019 2020 - name: 2d.path.roundrect.3.radii.3.double 2021 desc: Verify that when three radii are given to roundRect(), the third radius, specified as a double, applies to the bottom-right corner. 2022 code: | 2023 ctx.fillStyle = '#f00'; 2024 ctx.fillRect(0, 0, 100, 50); 2025 ctx.roundRect(0, 0, 100, 50, [0, 0, 20]); 2026 ctx.fillStyle = '#0f0'; 2027 ctx.fill(); 2028 @assert pixel 1,1 == 0,255,0,255; 2029 @assert pixel 98,1 == 0,255,0,255; 2030 @assert pixel 98,48 == 255,0,0,255; 2031 @assert pixel 1,48 == 0,255,0,255; 2032 2033 - name: 2d.path.roundrect.3.radii.3.dompoint 2034 desc: Verify that when three radii are given to roundRect(), the third radius, specified as a DOMPoint, applies to the bottom-right corner. 2035 code: | 2036 ctx.fillStyle = '#f00'; 2037 ctx.fillRect(0, 0, 100, 50); 2038 ctx.roundRect(0, 0, 100, 50, [0, 0, new DOMPoint(40, 20)]); 2039 ctx.fillStyle = '#0f0'; 2040 ctx.fill(); 2041 2042 // bottom-right corner 2043 @assert pixel 79,48 == 255,0,0,255; 2044 @assert pixel 58,48 == 0,255,0,255; 2045 @assert pixel 98,39 == 255,0,0,255; 2046 @assert pixel 98,28 == 0,255,0,255; 2047 2048 // other corners 2049 @assert pixel 1,1 == 0,255,0,255; 2050 @assert pixel 98,1 == 0,255,0,255; 2051 @assert pixel 1,48 == 0,255,0,255; 2052 2053 - name: 2d.path.roundrect.3.radii.3.dompointinit 2054 desc: Verify that when three radii are given to roundRect(), the third radius, specified as a DOMPointInit, applies to the bottom-right corner. 2055 code: | 2056 ctx.fillStyle = '#f00'; 2057 ctx.fillRect(0, 0, 100, 50); 2058 ctx.roundRect(0, 0, 100, 50, [0, 0, {x: 40, y: 20}]); 2059 ctx.fillStyle = '#0f0'; 2060 ctx.fill(); 2061 2062 // bottom-right corner 2063 @assert pixel 79,48 == 255,0,0,255; 2064 @assert pixel 58,48 == 0,255,0,255; 2065 @assert pixel 98,39 == 255,0,0,255; 2066 @assert pixel 98,28 == 0,255,0,255; 2067 2068 // other corners 2069 @assert pixel 1,1 == 0,255,0,255; 2070 @assert pixel 98,1 == 0,255,0,255; 2071 @assert pixel 1,48 == 0,255,0,255; 2072 2073 - name: 2d.path.roundrect.2.radii.1.double 2074 desc: Verify that when two radii are given to roundRect(), the first radius, specified as a double, applies to the top-left and bottom-right corners. 2075 code: | 2076 ctx.fillStyle = '#f00'; 2077 ctx.fillRect(0, 0, 100, 50); 2078 ctx.roundRect(0, 0, 100, 50, [20, 0]); 2079 ctx.fillStyle = '#0f0'; 2080 ctx.fill(); 2081 @assert pixel 1,1 == 255,0,0,255; 2082 @assert pixel 98,1 == 0,255,0,255; 2083 @assert pixel 98,48 == 255,0,0,255; 2084 @assert pixel 1,48 == 0,255,0,255; 2085 2086 - name: 2d.path.roundrect.2.radii.1.dompoint 2087 desc: Verify that when two radii are given to roundRect(), the first radius, specified as a DOMPoint, applies to the top-left and bottom-right corners. 2088 code: | 2089 ctx.fillStyle = '#f00'; 2090 ctx.fillRect(0, 0, 100, 50); 2091 ctx.roundRect(0, 0, 100, 50, [new DOMPoint(40, 20), 0]); 2092 ctx.fillStyle = '#0f0'; 2093 ctx.fill(); 2094 2095 // top-left corner 2096 @assert pixel 20,1 == 255,0,0,255; 2097 @assert pixel 41,1 == 0,255,0,255; 2098 @assert pixel 1,10 == 255,0,0,255; 2099 @assert pixel 1,21 == 0,255,0,255; 2100 2101 // bottom-right corner 2102 @assert pixel 79,48 == 255,0,0,255; 2103 @assert pixel 58,48 == 0,255,0,255; 2104 @assert pixel 98,39 == 255,0,0,255; 2105 @assert pixel 98,28 == 0,255,0,255; 2106 2107 // other corners 2108 @assert pixel 98,1 == 0,255,0,255; 2109 @assert pixel 1,48 == 0,255,0,255; 2110 2111 - name: 2d.path.roundrect.2.radii.1.dompointinit 2112 desc: Verify that when two radii are given to roundRect(), the first radius, specified as a DOMPointInit, applies to the top-left and bottom-right corners. 2113 code: | 2114 ctx.fillStyle = '#f00'; 2115 ctx.fillRect(0, 0, 100, 50); 2116 ctx.roundRect(0, 0, 100, 50, [{x: 40, y: 20}, 0]); 2117 ctx.fillStyle = '#0f0'; 2118 ctx.fill(); 2119 2120 // top-left corner 2121 @assert pixel 20,1 == 255,0,0,255; 2122 @assert pixel 41,1 == 0,255,0,255; 2123 @assert pixel 1,10 == 255,0,0,255; 2124 @assert pixel 1,21 == 0,255,0,255; 2125 2126 // bottom-right corner 2127 @assert pixel 79,48 == 255,0,0,255; 2128 @assert pixel 58,48 == 0,255,0,255; 2129 @assert pixel 98,39 == 255,0,0,255; 2130 @assert pixel 98,28 == 0,255,0,255; 2131 2132 // other corners 2133 @assert pixel 98,1 == 0,255,0,255; 2134 @assert pixel 1,48 == 0,255,0,255; 2135 2136 - name: 2d.path.roundrect.2.radii.2.double 2137 desc: Verify that when two radii are given to roundRect(), the second radius, specified as a double, applies to the top-right and bottom-left corners. 2138 code: | 2139 ctx.fillStyle = '#f00'; 2140 ctx.fillRect(0, 0, 100, 50); 2141 ctx.roundRect(0, 0, 100, 50, [0, 20]); 2142 ctx.fillStyle = '#0f0'; 2143 ctx.fill(); 2144 @assert pixel 1,1 == 0,255,0,255; 2145 @assert pixel 98,1 == 255,0,0,255; 2146 @assert pixel 98,48 == 0,255,0,255; 2147 @assert pixel 1,48 == 255,0,0,255; 2148 2149 - name: 2d.path.roundrect.2.radii.2.dompoint 2150 desc: Verify that when two radii are given to roundRect(), the second radius, specified as a DOMPoint, applies to the top-right and bottom-left corners. 2151 code: | 2152 ctx.fillStyle = '#f00'; 2153 ctx.fillRect(0, 0, 100, 50); 2154 ctx.roundRect(0, 0, 100, 50, [0, new DOMPoint(40, 20)]); 2155 ctx.fillStyle = '#0f0'; 2156 ctx.fill(); 2157 2158 // top-right corner 2159 @assert pixel 79,1 == 255,0,0,255; 2160 @assert pixel 58,1 == 0,255,0,255; 2161 @assert pixel 98,10 == 255,0,0,255; 2162 @assert pixel 98,21 == 0,255,0,255; 2163 2164 // bottom-left corner 2165 @assert pixel 20,48 == 255,0,0,255; 2166 @assert pixel 41,48 == 0,255,0,255; 2167 @assert pixel 1,39 == 255,0,0,255; 2168 @assert pixel 1,28 == 0,255,0,255; 2169 2170 // other corners 2171 @assert pixel 1,1 == 0,255,0,255; 2172 @assert pixel 98,48 == 0,255,0,255; 2173 2174 - name: 2d.path.roundrect.2.radii.2.dompointinit 2175 desc: Verify that when two radii are given to roundRect(), the second radius, specified as a DOMPointInit, applies to the top-right and bottom-left corners. 2176 code: | 2177 ctx.fillStyle = '#f00'; 2178 ctx.fillRect(0, 0, 100, 50); 2179 ctx.roundRect(0, 0, 100, 50, [0, {x: 40, y: 20}]); 2180 ctx.fillStyle = '#0f0'; 2181 ctx.fill(); 2182 2183 // top-right corner 2184 @assert pixel 79,1 == 255,0,0,255; 2185 @assert pixel 58,1 == 0,255,0,255; 2186 @assert pixel 98,10 == 255,0,0,255; 2187 @assert pixel 98,21 == 0,255,0,255; 2188 2189 // bottom-left corner 2190 @assert pixel 20,48 == 255,0,0,255; 2191 @assert pixel 41,48 == 0,255,0,255; 2192 @assert pixel 1,39 == 255,0,0,255; 2193 @assert pixel 1,28 == 0,255,0,255; 2194 2195 // other corners 2196 @assert pixel 1,1 == 0,255,0,255; 2197 @assert pixel 98,48 == 0,255,0,255; 2198 2199 - name: 2d.path.roundrect.1.radius.double 2200 desc: Verify that when one radius is given to roundRect(), specified as a double, it applies to all corners. 2201 code: | 2202 ctx.fillStyle = '#f00'; 2203 ctx.fillRect(0, 0, 100, 50); 2204 ctx.roundRect(0, 0, 100, 50, [20]); 2205 ctx.fillStyle = '#0f0'; 2206 ctx.fill(); 2207 @assert pixel 1,1 == 255,0,0,255; 2208 @assert pixel 98,1 == 255,0,0,255; 2209 @assert pixel 98,48 == 255,0,0,255; 2210 @assert pixel 1,48 == 255,0,0,255; 2211 2212 - name: 2d.path.roundrect.1.radius.double.single.argument 2213 desc: Verify that when one radius is given to roundRect() as a non-array argument, specified as a double, it applies to all corners. 2214 code: | 2215 ctx.fillStyle = '#f00'; 2216 ctx.fillRect(0, 0, 100, 50); 2217 ctx.roundRect(0, 0, 100, 50, 20); 2218 ctx.fillStyle = '#0f0'; 2219 ctx.fill(); 2220 @assert pixel 1,1 == 255,0,0,255; 2221 @assert pixel 98,1 == 255,0,0,255; 2222 @assert pixel 98,48 == 255,0,0,255; 2223 @assert pixel 1,48 == 255,0,0,255; 2224 2225 - name: 2d.path.roundrect.1.radius.dompoint 2226 desc: Verify that when one radius is given to roundRect(), specified as a DOMPoint, it applies to all corners. 2227 code: | 2228 ctx.fillStyle = '#f00'; 2229 ctx.fillRect(0, 0, 100, 50); 2230 ctx.roundRect(0, 0, 100, 50, [new DOMPoint(40, 20)]); 2231 ctx.fillStyle = '#0f0'; 2232 ctx.fill(); 2233 2234 // top-left corner 2235 @assert pixel 20,1 == 255,0,0,255; 2236 @assert pixel 41,1 == 0,255,0,255; 2237 @assert pixel 1,10 == 255,0,0,255; 2238 @assert pixel 1,21 == 0,255,0,255; 2239 2240 // top-right corner 2241 @assert pixel 79,1 == 255,0,0,255; 2242 @assert pixel 58,1 == 0,255,0,255; 2243 @assert pixel 98,10 == 255,0,0,255; 2244 @assert pixel 98,21 == 0,255,0,255; 2245 2246 // bottom-right corner 2247 @assert pixel 79,48 == 255,0,0,255; 2248 @assert pixel 58,48 == 0,255,0,255; 2249 @assert pixel 98,39 == 255,0,0,255; 2250 @assert pixel 98,28 == 0,255,0,255; 2251 2252 // bottom-left corner 2253 @assert pixel 20,48 == 255,0,0,255; 2254 @assert pixel 41,48 == 0,255,0,255; 2255 @assert pixel 1,39 == 255,0,0,255; 2256 @assert pixel 1,28 == 0,255,0,255; 2257 2258 - name: 2d.path.roundrect.1.radius.dompoint.single.argument 2259 desc: Verify that when one radius is given to roundRect() as a non-array argument, specified as a DOMPoint, it applies to all corners. 2260 code: | 2261 ctx.fillStyle = '#f00'; 2262 ctx.fillRect(0, 0, 100, 50); 2263 ctx.roundRect(0, 0, 100, 50, new DOMPoint(40, 20)); 2264 ctx.fillStyle = '#0f0'; 2265 ctx.fill(); 2266 2267 // top-left corner 2268 @assert pixel 20,1 == 255,0,0,255; 2269 @assert pixel 41,1 == 0,255,0,255; 2270 @assert pixel 1,10 == 255,0,0,255; 2271 @assert pixel 1,21 == 0,255,0,255; 2272 2273 // top-right corner 2274 @assert pixel 79,1 == 255,0,0,255; 2275 @assert pixel 58,1 == 0,255,0,255; 2276 @assert pixel 98,10 == 255,0,0,255; 2277 @assert pixel 98,21 == 0,255,0,255; 2278 2279 // bottom-right corner 2280 @assert pixel 79,48 == 255,0,0,255; 2281 @assert pixel 58,48 == 0,255,0,255; 2282 @assert pixel 98,39 == 255,0,0,255; 2283 @assert pixel 98,28 == 0,255,0,255; 2284 2285 // bottom-left corner 2286 @assert pixel 20,48 == 255,0,0,255; 2287 @assert pixel 41,48 == 0,255,0,255; 2288 @assert pixel 1,39 == 255,0,0,255; 2289 @assert pixel 1,28 == 0,255,0,255; 2290 2291 - name: 2d.path.roundrect.1.radius.dompointinit 2292 desc: Verify that when one radius is given to roundRect(), specified as a DOMPointInit, applies to all corners. 2293 code: | 2294 ctx.fillStyle = '#f00'; 2295 ctx.fillRect(0, 0, 100, 50); 2296 ctx.roundRect(0, 0, 100, 50, [{x: 40, y: 20}]); 2297 ctx.fillStyle = '#0f0'; 2298 ctx.fill(); 2299 2300 // top-left corner 2301 @assert pixel 20,1 == 255,0,0,255; 2302 @assert pixel 41,1 == 0,255,0,255; 2303 @assert pixel 1,10 == 255,0,0,255; 2304 @assert pixel 1,21 == 0,255,0,255; 2305 2306 // top-right corner 2307 @assert pixel 79,1 == 255,0,0,255; 2308 @assert pixel 58,1 == 0,255,0,255; 2309 @assert pixel 98,10 == 255,0,0,255; 2310 @assert pixel 98,21 == 0,255,0,255; 2311 2312 // bottom-right corner 2313 @assert pixel 79,48 == 255,0,0,255; 2314 @assert pixel 58,48 == 0,255,0,255; 2315 @assert pixel 98,39 == 255,0,0,255; 2316 @assert pixel 98,28 == 0,255,0,255; 2317 2318 // bottom-left corner 2319 @assert pixel 20,48 == 255,0,0,255; 2320 @assert pixel 41,48 == 0,255,0,255; 2321 @assert pixel 1,39 == 255,0,0,255; 2322 @assert pixel 1,28 == 0,255,0,255; 2323 2324 - name: 2d.path.roundrect.1.radius.dompointinit.single.argument 2325 desc: Verify that when one radius is given to roundRect() as a non-array argument, specified as a DOMPointInit, applies to all corners. 2326 code: | 2327 ctx.fillStyle = '#f00'; 2328 ctx.fillRect(0, 0, 100, 50); 2329 ctx.roundRect(0, 0, 100, 50, {x: 40, y: 20}); 2330 ctx.fillStyle = '#0f0'; 2331 ctx.fill(); 2332 2333 // top-left corner 2334 @assert pixel 20,1 == 255,0,0,255; 2335 @assert pixel 41,1 == 0,255,0,255; 2336 @assert pixel 1,10 == 255,0,0,255; 2337 @assert pixel 1,21 == 0,255,0,255; 2338 2339 // top-right corner 2340 @assert pixel 79,1 == 255,0,0,255; 2341 @assert pixel 58,1 == 0,255,0,255; 2342 @assert pixel 98,10 == 255,0,0,255; 2343 @assert pixel 98,21 == 0,255,0,255; 2344 2345 // bottom-right corner 2346 @assert pixel 79,48 == 255,0,0,255; 2347 @assert pixel 58,48 == 0,255,0,255; 2348 @assert pixel 98,39 == 255,0,0,255; 2349 @assert pixel 98,28 == 0,255,0,255; 2350 2351 // bottom-left corner 2352 @assert pixel 20,48 == 255,0,0,255; 2353 @assert pixel 41,48 == 0,255,0,255; 2354 @assert pixel 1,39 == 255,0,0,255; 2355 @assert pixel 1,28 == 0,255,0,255; 2356 2357 - name: 2d.path.roundrect.radius.intersecting.1 2358 desc: Check that roundRects with intersecting corner arcs are rendered correctly. 2359 code: | 2360 ctx.fillStyle = '#f00'; 2361 ctx.fillRect(0, 0, 100, 50); 2362 ctx.roundRect(0, 0, 100, 50, [40, 40, 40, 40]); 2363 ctx.fillStyle = '#0f0'; 2364 ctx.fill(); 2365 @assert pixel 2,25 == 0,255,0,255; 2366 @assert pixel 50,1 == 0,255,0,255; 2367 @assert pixel 50,25 == 0,255,0,255; 2368 @assert pixel 50,48 == 0,255,0,255; 2369 @assert pixel 97,25 == 0,255,0,255; 2370 @assert pixel 1,1 == 255,0,0,255; 2371 @assert pixel 98,1 == 255,0,0,255; 2372 @assert pixel 1,48 == 255,0,0,255; 2373 @assert pixel 98,48 == 255,0,0,255; 2374 2375 - name: 2d.path.roundrect.radius.intersecting.2 2376 desc: Check that roundRects with intersecting corner arcs are rendered correctly. 2377 code: | 2378 ctx.fillStyle = '#f00'; 2379 ctx.fillRect(0, 0, 100, 50); 2380 ctx.roundRect(0, 0, 100, 50, [1000, 1000, 1000, 1000]); 2381 ctx.fillStyle = '#0f0'; 2382 ctx.fill(); 2383 @assert pixel 2,25 == 0,255,0,255; 2384 @assert pixel 50,1 == 0,255,0,255; 2385 @assert pixel 50,25 == 0,255,0,255; 2386 @assert pixel 50,48 == 0,255,0,255; 2387 @assert pixel 97,25 == 0,255,0,255; 2388 @assert pixel 1,1 == 255,0,0,255; 2389 @assert pixel 98,1 == 255,0,0,255; 2390 @assert pixel 1,48 == 255,0,0,255; 2391 @assert pixel 98,48 == 255,0,0,255; 2392 2393 - name: 2d.path.roundrect.radius.none 2394 desc: Check that roundRect throws an RangeError if radii is an empty array. 2395 code: | 2396 assert_throws_js(RangeError, () => { ctx.roundRect(0, 0, 100, 50, [])}); 2397 2398 - name: 2d.path.roundrect.radius.noargument 2399 desc: Check that roundRect draws a rectangle when no radii are provided. 2400 code: | 2401 ctx.fillStyle = '#f00'; 2402 ctx.fillRect(0, 0, 100, 50); 2403 ctx.roundRect(10, 10, 80, 30); 2404 ctx.fillStyle = '#0f0'; 2405 ctx.fill(); 2406 // upper left corner (10, 10) 2407 @assert pixel 10,9 == 255,0,0,255; 2408 @assert pixel 9,10 == 255,0,0,255; 2409 @assert pixel 10,10 == 0,255,0,255; 2410 2411 // upper right corner (89, 10) 2412 @assert pixel 90,10 == 255,0,0,255; 2413 @assert pixel 89,9 == 255,0,0,255; 2414 @assert pixel 89,10 == 0,255,0,255; 2415 2416 // lower right corner (89, 39) 2417 @assert pixel 89,40 == 255,0,0,255; 2418 @assert pixel 90,39 == 255,0,0,255; 2419 @assert pixel 89,39 == 0,255,0,255; 2420 2421 // lower left corner (10, 30) 2422 @assert pixel 9,39 == 255,0,0,255; 2423 @assert pixel 10,40 == 255,0,0,255; 2424 @assert pixel 10,39 == 0,255,0,255; 2425 2426 - name: 2d.path.roundrect.radius.toomany 2427 desc: Check that roundRect throws an IndeSizeError if radii has more than four items. 2428 code: | 2429 assert_throws_js(RangeError, () => { ctx.roundRect(0, 0, 100, 50, [0, 0, 0, 0, 0])}); 2430 2431 - name: 2d.path.roundrect.radius.negative 2432 desc: roundRect() with negative radius throws an exception 2433 code: | 2434 assert_throws_js(RangeError, () => { ctx.roundRect(0, 0, 0, 0, [-1])}); 2435 assert_throws_js(RangeError, () => { ctx.roundRect(0, 0, 0, 0, [1, -1])}); 2436 assert_throws_js(RangeError, () => { ctx.roundRect(0, 0, 0, 0, [new DOMPoint(-1, 1), 1])}); 2437 assert_throws_js(RangeError, () => { ctx.roundRect(0, 0, 0, 0, [new DOMPoint(1, -1)])}); 2438 assert_throws_js(RangeError, () => { ctx.roundRect(0, 0, 0, 0, [{x: -1, y: 1}, 1])}); 2439 assert_throws_js(RangeError, () => { ctx.roundRect(0, 0, 0, 0, [{x: 1, y: -1}])}); 2440 2441 - name: 2d.path.roundrect.badinput 2442 desc: roundRect() throws or does not throw errors given the strange inputs. 2443 code: | 2444 ctx.roundRect(0, 0, 100, 100, { foo: "bar" }); //=> DOMPointInit 2445 ctx.roundRect(0, 0, 100, 100, undefined); //=> "missing" -> 0 2446 ctx.roundRect(0, 0, 100, 100, [[]]); //=> « DOMPointInit » 2447 ctx.roundRect(0, 0, 100, 100, [[25]]); //=> « DOMPointInit » 2448 ctx.roundRect(0, 0, 100, 100, [undefined]); //=> « DOMPointInit » 2449 @assert throws TypeError ctx.roundRect(0, 0, 100, 100, 0n); 2450 @assert throws TypeError ctx.roundRect(0, 0, 100, 100, { x: 0n }); 2451 @assert throws TypeError ctx.roundRect(0, 0, 100, 100, [{ x: 0n }]); 2452 2453 - name: 2d.path.ellipse.basics 2454 desc: Verify canvas throws error when drawing ellipse with negative radii. 2455 code: | 2456 ctx.ellipse(10, 10, 10, 5, 0, 0, 1, false); 2457 ctx.ellipse(10, 10, 10, 0, 0, 0, 1, false); 2458 ctx.ellipse(10, 10, -0, 5, 0, 0, 1, false); 2459 @assert throws INDEX_SIZE_ERR ctx.ellipse(10, 10, -2, 5, 0, 0, 1, false); 2460 @assert throws INDEX_SIZE_ERR ctx.ellipse(10, 10, 0, -1.5, 0, 0, 1, false); 2461 @assert throws INDEX_SIZE_ERR ctx.ellipse(10, 10, -2, -5, 0, 0, 1, false); 2462 ctx.ellipse(80, 0, 10, 4294967277, Math.PI / -84, -Math.PI / 2147483436, false); 2463 2464 - name: 2d.path.fill.overlap 2465 code: | 2466 ctx.fillStyle = '#000'; 2467 ctx.fillRect(0, 0, 100, 50); 2468 2469 ctx.fillStyle = 'rgba(0, 255, 0, 0.5)'; 2470 ctx.rect(0, 0, 100, 50); 2471 ctx.closePath(); 2472 ctx.rect(10, 10, 80, 30); 2473 ctx.fill(); 2474 2475 @assert pixel 50,25 ==~ 0,127,0,255 +/- 1; 2476 expected: | 2477 size 100 50 2478 cr.set_source_rgb(0, 0.5, 0) 2479 cr.rectangle(0, 0, 100, 50) 2480 cr.fill() 2481 2482 - name: 2d.path.fill.winding.evenodd.1 2483 desc: evenodd winding number rule works in fill 2484 code: | 2485 ctx.fillStyle = '#0f0'; 2486 ctx.fillRect(0, 0, 100, 50); 2487 2488 ctx.beginPath(); 2489 ctx.rect(0, 0, 100, 50); 2490 ctx.rect(0, 0, 100, 50); 2491 2492 ctx.fillStyle = "#f00"; 2493 ctx.fill("evenodd"); 2494 2495 @assert pixel 50,25 == 0,255,0,255; 2496 2497 - name: 2d.path.fill.winding.evenodd.2 2498 desc: evenodd winding number rule works in fill 2499 code: | 2500 ctx.fillStyle = '#0f0'; 2501 ctx.fillRect(0, 0, 100, 50); 2502 2503 let path = new Path2D(); 2504 path.rect(0, 0, 100, 50); 2505 path.rect(0, 0, 100, 50); 2506 path.closePath(); 2507 2508 ctx.fillStyle = "#f00"; 2509 ctx.fill(path, "evenodd"); 2510 2511 @assert pixel 50,25 == 0,255,0,255; 2512 2513 - name: 2d.path.fill.winding.add 2514 code: | 2515 ctx.fillStyle = '#f00'; 2516 ctx.fillRect(0, 0, 100, 50); 2517 2518 ctx.fillStyle = '#0f0'; 2519 ctx.moveTo(-10, -10); 2520 ctx.lineTo(110, -10); 2521 ctx.lineTo(110, 60); 2522 ctx.lineTo(-10, 60); 2523 ctx.lineTo(-10, -10); 2524 ctx.lineTo(0, 0); 2525 ctx.lineTo(100, 0); 2526 ctx.lineTo(100, 50); 2527 ctx.lineTo(0, 50); 2528 ctx.fill(); 2529 2530 @assert pixel 50,25 == 0,255,0,255; 2531 expected: green 2532 2533 - name: 2d.path.fill.winding.subtract.1 2534 code: | 2535 ctx.fillStyle = '#0f0'; 2536 ctx.fillRect(0, 0, 100, 50); 2537 2538 ctx.fillStyle = '#f00'; 2539 ctx.moveTo(-10, -10); 2540 ctx.lineTo(110, -10); 2541 ctx.lineTo(110, 60); 2542 ctx.lineTo(-10, 60); 2543 ctx.lineTo(-10, -10); 2544 ctx.lineTo(0, 0); 2545 ctx.lineTo(0, 50); 2546 ctx.lineTo(100, 50); 2547 ctx.lineTo(100, 0); 2548 ctx.fill(); 2549 2550 @assert pixel 50,25 == 0,255,0,255; 2551 expected: green 2552 2553 - name: 2d.path.fill.winding.subtract.2 2554 code: | 2555 ctx.fillStyle = '#0f0'; 2556 ctx.fillRect(0, 0, 100, 50); 2557 2558 ctx.fillStyle = '#f00'; 2559 ctx.moveTo(-10, -10); 2560 ctx.lineTo(110, -10); 2561 ctx.lineTo(110, 60); 2562 ctx.lineTo(-10, 60); 2563 ctx.moveTo(0, 0); 2564 ctx.lineTo(0, 50); 2565 ctx.lineTo(100, 50); 2566 ctx.lineTo(100, 0); 2567 ctx.fill(); 2568 2569 @assert pixel 50,25 == 0,255,0,255; 2570 expected: green 2571 2572 - name: 2d.path.fill.winding.subtract.3 2573 code: | 2574 ctx.fillStyle = '#f00'; 2575 ctx.fillRect(0, 0, 100, 50); 2576 2577 ctx.fillStyle = '#0f0'; 2578 ctx.moveTo(-10, -10); 2579 ctx.lineTo(110, -10); 2580 ctx.lineTo(110, 60); 2581 ctx.lineTo(-10, 60); 2582 ctx.lineTo(-10, -10); 2583 ctx.lineTo(-20, -20); 2584 ctx.lineTo(120, -20); 2585 ctx.lineTo(120, 70); 2586 ctx.lineTo(-20, 70); 2587 ctx.lineTo(-20, -20); 2588 ctx.lineTo(0, 0); 2589 ctx.lineTo(0, 50); 2590 ctx.lineTo(100, 50); 2591 ctx.lineTo(100, 0); 2592 ctx.fill(); 2593 2594 @assert pixel 50,25 == 0,255,0,255; 2595 expected: green 2596 2597 - name: 2d.path.fill.closed.basic 2598 code: | 2599 ctx.fillStyle = '#f00'; 2600 ctx.fillRect(0, 0, 100, 50); 2601 2602 ctx.fillStyle = '#0f0'; 2603 ctx.moveTo(0, 0); 2604 ctx.lineTo(100, 0); 2605 ctx.lineTo(100, 50); 2606 ctx.lineTo(0, 50); 2607 ctx.fill(); 2608 2609 @assert pixel 50,25 == 0,255,0,255; 2610 expected: green 2611 2612 - name: 2d.path.fill.closed.unaffected 2613 code: | 2614 ctx.fillStyle = '#00f'; 2615 ctx.fillRect(0, 0, 100, 50); 2616 2617 ctx.moveTo(0, 0); 2618 ctx.lineTo(100, 0); 2619 ctx.lineTo(100, 50); 2620 ctx.fillStyle = '#f00'; 2621 ctx.fill(); 2622 ctx.lineTo(0, 50); 2623 ctx.fillStyle = '#0f0'; 2624 ctx.fill(); 2625 2626 @assert pixel 90,10 == 0,255,0,255; 2627 @assert pixel 10,40 == 0,255,0,255; 2628 expected: green 2629 2630 - name: 2d.path.stroke.overlap 2631 desc: Stroked subpaths are combined before being drawn 2632 code: | 2633 ctx.fillStyle = '#000'; 2634 ctx.fillRect(0, 0, 100, 50); 2635 2636 ctx.strokeStyle = 'rgba(0, 255, 0, 0.5)'; 2637 ctx.lineWidth = 50; 2638 ctx.moveTo(0, 20); 2639 ctx.lineTo(100, 20); 2640 ctx.moveTo(0, 30); 2641 ctx.lineTo(100, 30); 2642 ctx.stroke(); 2643 2644 @assert pixel 50,25 ==~ 0,127,0,255 +/- 1; 2645 expected: | 2646 size 100 50 2647 cr.set_source_rgb(0, 0.5, 0) 2648 cr.rectangle(0, 0, 100, 50) 2649 cr.fill() 2650 2651 - name: 2d.path.stroke.union 2652 desc: Strokes in opposite directions are unioned, not subtracted 2653 code: | 2654 ctx.fillStyle = '#f00'; 2655 ctx.fillRect(0, 0, 100, 50); 2656 2657 ctx.strokeStyle = '#0f0'; 2658 ctx.lineWidth = 40; 2659 ctx.moveTo(0, 10); 2660 ctx.lineTo(100, 10); 2661 ctx.moveTo(100, 40); 2662 ctx.lineTo(0, 40); 2663 ctx.stroke(); 2664 2665 @assert pixel 50,25 == 0,255,0,255; 2666 expected: green 2667 2668 - name: 2d.path.stroke.unaffected 2669 desc: Stroking does not start a new path or subpath 2670 code: | 2671 ctx.fillStyle = '#f00'; 2672 ctx.fillRect(0, 0, 100, 50); 2673 2674 ctx.lineWidth = 50; 2675 ctx.moveTo(-100, 25); 2676 ctx.lineTo(-100, -100); 2677 ctx.lineTo(200, -100); 2678 ctx.lineTo(200, 25); 2679 ctx.strokeStyle = '#f00'; 2680 ctx.stroke(); 2681 2682 ctx.closePath(); 2683 ctx.strokeStyle = '#0f0'; 2684 ctx.stroke(); 2685 2686 @assert pixel 50,25 == 0,255,0,255; 2687 expected: green 2688 2689 - name: 2d.path.stroke.scale1 2690 desc: Stroke line widths are scaled by the current transformation matrix 2691 code: | 2692 ctx.fillStyle = '#f00'; 2693 ctx.fillRect(0, 0, 100, 50); 2694 2695 ctx.beginPath(); 2696 ctx.rect(25, 12.5, 50, 25); 2697 ctx.save(); 2698 ctx.scale(50, 25); 2699 ctx.strokeStyle = '#0f0'; 2700 ctx.stroke(); 2701 ctx.restore(); 2702 2703 ctx.beginPath(); 2704 ctx.rect(-25, -12.5, 150, 75); 2705 ctx.save(); 2706 ctx.scale(50, 25); 2707 ctx.strokeStyle = '#f00'; 2708 ctx.stroke(); 2709 ctx.restore(); 2710 2711 @assert pixel 0,0 == 0,255,0,255; 2712 @assert pixel 50,0 == 0,255,0,255; 2713 @assert pixel 99,0 == 0,255,0,255; 2714 @assert pixel 0,25 == 0,255,0,255; 2715 @assert pixel 50,25 == 0,255,0,255; 2716 @assert pixel 99,25 == 0,255,0,255; 2717 @assert pixel 0,49 == 0,255,0,255; 2718 @assert pixel 50,49 == 0,255,0,255; 2719 @assert pixel 99,49 == 0,255,0,255; 2720 expected: green 2721 2722 - name: 2d.path.stroke.scale2 2723 desc: Stroke line widths are scaled by the current transformation matrix 2724 code: | 2725 ctx.fillStyle = '#f00'; 2726 ctx.fillRect(0, 0, 100, 50); 2727 2728 ctx.beginPath(); 2729 ctx.rect(25, 12.5, 50, 25); 2730 ctx.save(); 2731 ctx.rotate(Math.PI/2); 2732 ctx.scale(25, 50); 2733 ctx.strokeStyle = '#0f0'; 2734 ctx.stroke(); 2735 ctx.restore(); 2736 2737 ctx.beginPath(); 2738 ctx.rect(-25, -12.5, 150, 75); 2739 ctx.save(); 2740 ctx.rotate(Math.PI/2); 2741 ctx.scale(25, 50); 2742 ctx.strokeStyle = '#f00'; 2743 ctx.stroke(); 2744 ctx.restore(); 2745 2746 @assert pixel 0,0 == 0,255,0,255; 2747 @assert pixel 50,0 == 0,255,0,255; 2748 @assert pixel 99,0 == 0,255,0,255; 2749 @assert pixel 0,25 == 0,255,0,255; 2750 @assert pixel 50,25 == 0,255,0,255; 2751 @assert pixel 99,25 == 0,255,0,255; 2752 @assert pixel 0,49 == 0,255,0,255; 2753 @assert pixel 50,49 == 0,255,0,255; 2754 @assert pixel 99,49 == 0,255,0,255; 2755 expected: green 2756 2757 - name: 2d.path.stroke.skew 2758 desc: Strokes lines are skewed by the current transformation matrix 2759 code: | 2760 ctx.fillStyle = '#f00'; 2761 ctx.fillRect(0, 0, 100, 50); 2762 2763 ctx.save(); 2764 ctx.beginPath(); 2765 ctx.moveTo(49, -50); 2766 ctx.lineTo(201, -50); 2767 ctx.rotate(Math.PI/4); 2768 ctx.scale(1, 283); 2769 ctx.strokeStyle = '#0f0'; 2770 ctx.stroke(); 2771 ctx.restore(); 2772 2773 ctx.save(); 2774 ctx.beginPath(); 2775 ctx.translate(-150, 0); 2776 ctx.moveTo(49, -50); 2777 ctx.lineTo(199, -50); 2778 ctx.rotate(Math.PI/4); 2779 ctx.scale(1, 142); 2780 ctx.strokeStyle = '#f00'; 2781 ctx.stroke(); 2782 ctx.restore(); 2783 2784 ctx.save(); 2785 ctx.beginPath(); 2786 ctx.translate(-150, 0); 2787 ctx.moveTo(49, -50); 2788 ctx.lineTo(199, -50); 2789 ctx.rotate(Math.PI/4); 2790 ctx.scale(1, 142); 2791 ctx.strokeStyle = '#f00'; 2792 ctx.stroke(); 2793 ctx.restore(); 2794 2795 @assert pixel 0,0 == 0,255,0,255; 2796 @assert pixel 50,0 == 0,255,0,255; 2797 @assert pixel 99,0 == 0,255,0,255; 2798 @assert pixel 0,25 == 0,255,0,255; 2799 @assert pixel 50,25 == 0,255,0,255; 2800 @assert pixel 99,25 == 0,255,0,255; 2801 @assert pixel 0,49 == 0,255,0,255; 2802 @assert pixel 50,49 == 0,255,0,255; 2803 @assert pixel 99,49 == 0,255,0,255; 2804 expected: green 2805 2806 - name: 2d.path.stroke.empty 2807 desc: Empty subpaths are not stroked 2808 code: | 2809 ctx.fillStyle = '#0f0'; 2810 ctx.fillRect(0, 0, 100, 50); 2811 2812 ctx.strokeStyle = '#f00'; 2813 ctx.lineWidth = 100; 2814 ctx.lineCap = 'round'; 2815 ctx.lineJoin = 'round'; 2816 2817 ctx.beginPath(); 2818 ctx.moveTo(40, 25); 2819 ctx.moveTo(60, 25); 2820 ctx.stroke(); 2821 2822 @assert pixel 50,25 == 0,255,0,255; 2823 expected: green 2824 2825 - name: 2d.path.stroke.prune.line 2826 desc: Zero-length line segments from lineTo are removed before stroking 2827 code: | 2828 ctx.fillStyle = '#0f0'; 2829 ctx.fillRect(0, 0, 100, 50); 2830 2831 ctx.strokeStyle = '#f00'; 2832 ctx.lineWidth = 100; 2833 ctx.lineCap = 'round'; 2834 ctx.lineJoin = 'round'; 2835 2836 ctx.beginPath(); 2837 ctx.moveTo(50, 25); 2838 ctx.lineTo(50, 25); 2839 ctx.stroke(); 2840 2841 @assert pixel 50,25 == 0,255,0,255; @moz-todo 2842 expected: green 2843 2844 - name: 2d.path.stroke.prune.closed 2845 desc: Zero-length line segments from closed paths are removed before stroking 2846 code: | 2847 ctx.fillStyle = '#0f0'; 2848 ctx.fillRect(0, 0, 100, 50); 2849 2850 ctx.strokeStyle = '#f00'; 2851 ctx.lineWidth = 100; 2852 ctx.lineCap = 'round'; 2853 ctx.lineJoin = 'round'; 2854 2855 ctx.beginPath(); 2856 ctx.moveTo(50, 25); 2857 ctx.lineTo(50, 25); 2858 ctx.closePath(); 2859 ctx.stroke(); 2860 2861 @assert pixel 50,25 == 0,255,0,255; @moz-todo 2862 expected: green 2863 2864 - name: 2d.path.stroke.prune.curve 2865 desc: Zero-length line segments from quadraticCurveTo and bezierCurveTo are removed 2866 before stroking 2867 code: | 2868 ctx.fillStyle = '#0f0'; 2869 ctx.fillRect(0, 0, 100, 50); 2870 2871 ctx.strokeStyle = '#f00'; 2872 ctx.lineWidth = 100; 2873 ctx.lineCap = 'round'; 2874 ctx.lineJoin = 'round'; 2875 2876 ctx.beginPath(); 2877 ctx.moveTo(50, 25); 2878 ctx.quadraticCurveTo(50, 25, 50, 25); 2879 ctx.stroke(); 2880 2881 ctx.beginPath(); 2882 ctx.moveTo(50, 25); 2883 ctx.bezierCurveTo(50, 25, 50, 25, 50, 25); 2884 ctx.stroke(); 2885 2886 @assert pixel 50,25 == 0,255,0,255; @moz-todo 2887 expected: green 2888 2889 - name: 2d.path.stroke.prune.arc 2890 desc: Zero-length line segments from arcTo and arc are removed before stroking 2891 code: | 2892 ctx.fillStyle = '#0f0'; 2893 ctx.fillRect(0, 0, 100, 50); 2894 2895 ctx.strokeStyle = '#f00'; 2896 ctx.lineWidth = 100; 2897 ctx.lineCap = 'round'; 2898 ctx.lineJoin = 'round'; 2899 2900 ctx.beginPath(); 2901 ctx.moveTo(50, 25); 2902 ctx.arcTo(50, 25, 150, 25, 10); 2903 ctx.stroke(); 2904 2905 ctx.beginPath(); 2906 ctx.moveTo(60, 25); 2907 ctx.arc(50, 25, 10, 0, 0, false); 2908 ctx.stroke(); 2909 2910 @assert pixel 50,25 == 0,255,0,255; @moz-todo 2911 expected: green 2912 2913 - name: 2d.path.stroke.prune.rect 2914 desc: Zero-length line segments from rect and strokeRect are removed before stroking 2915 code: | 2916 ctx.fillStyle = '#0f0'; 2917 ctx.fillRect(0, 0, 100, 50); 2918 2919 ctx.strokeStyle = '#f00'; 2920 ctx.lineWidth = 100; 2921 ctx.lineCap = 'round'; 2922 ctx.lineJoin = 'round'; 2923 2924 ctx.beginPath(); 2925 ctx.rect(50, 25, 0, 0); 2926 ctx.stroke(); 2927 2928 ctx.strokeRect(50, 25, 0, 0); 2929 2930 @assert pixel 50,25 == 0,255,0,255; @moz-todo 2931 expected: green 2932 2933 - name: 2d.path.stroke.prune.corner 2934 desc: Zero-length line segments are removed before stroking with miters 2935 code: | 2936 ctx.fillStyle = '#0f0'; 2937 ctx.fillRect(0, 0, 100, 50); 2938 2939 ctx.strokeStyle = '#f00'; 2940 ctx.lineWidth = 400; 2941 ctx.lineJoin = 'miter'; 2942 ctx.miterLimit = 1.4; 2943 2944 ctx.beginPath(); 2945 ctx.moveTo(-1000, 200); 2946 ctx.lineTo(-100, 200); 2947 ctx.lineTo(-100, 200); 2948 ctx.lineTo(-100, 200); 2949 ctx.lineTo(-100, 1000); 2950 ctx.stroke(); 2951 2952 @assert pixel 50,25 == 0,255,0,255; 2953 expected: green 2954 2955 - name: 2d.path.transformation.basic 2956 code: | 2957 ctx.fillStyle = '#f00'; 2958 ctx.fillRect(0, 0, 100, 50); 2959 2960 ctx.translate(-100, 0); 2961 ctx.rect(100, 0, 100, 50); 2962 ctx.translate(0, -100); 2963 ctx.fillStyle = '#0f0'; 2964 ctx.fill(); 2965 2966 @assert pixel 50,25 == 0,255,0,255; 2967 expected: green 2968 2969 - name: 2d.path.transformation.multiple 2970 # TODO: change this name 2971 desc: Transformations are applied while building paths, not when drawing 2972 code: | 2973 ctx.fillStyle = '#0f0'; 2974 ctx.fillRect(0, 0, 100, 50); 2975 2976 ctx.fillStyle = '#f00'; 2977 ctx.translate(-100, 0); 2978 ctx.rect(0, 0, 100, 50); 2979 ctx.fill(); 2980 ctx.translate(100, 0); 2981 ctx.fill(); 2982 2983 ctx.beginPath(); 2984 ctx.strokeStyle = '#f00'; 2985 ctx.lineWidth = 50; 2986 ctx.translate(0, -50); 2987 ctx.moveTo(0, 25); 2988 ctx.lineTo(100, 25); 2989 ctx.stroke(); 2990 ctx.translate(0, 50); 2991 ctx.stroke(); 2992 2993 @assert pixel 50,25 == 0,255,0,255; 2994 expected: green 2995 2996 - name: 2d.path.transformation.changing 2997 desc: Transformations are applied while building paths, not when drawing 2998 code: | 2999 ctx.fillStyle = '#f00'; 3000 ctx.fillRect(0, 0, 100, 50); 3001 ctx.fillStyle = '#0f0'; 3002 ctx.moveTo(0, 0); 3003 ctx.translate(100, 0); 3004 ctx.lineTo(0, 0); 3005 ctx.translate(0, 50); 3006 ctx.lineTo(0, 0); 3007 ctx.translate(-100, 0); 3008 ctx.lineTo(0, 0); 3009 ctx.translate(1000, 1000); 3010 ctx.rotate(Math.PI/2); 3011 ctx.scale(0.1, 0.1); 3012 ctx.fill(); 3013 3014 @assert pixel 50,25 == 0,255,0,255; 3015 expected: green 3016 3017 3018 - name: 2d.path.clip.empty 3019 code: | 3020 ctx.fillStyle = '#0f0'; 3021 ctx.fillRect(0, 0, 100, 50); 3022 3023 ctx.beginPath(); 3024 ctx.clip(); 3025 3026 ctx.fillStyle = '#f00'; 3027 ctx.fillRect(0, 0, 100, 50); 3028 3029 @assert pixel 50,25 == 0,255,0,255; 3030 expected: green 3031 3032 - name: 2d.path.clip.basic.1 3033 code: | 3034 ctx.fillStyle = '#f00'; 3035 ctx.fillRect(0, 0, 100, 50); 3036 3037 ctx.beginPath(); 3038 ctx.rect(0, 0, 100, 50); 3039 ctx.clip(); 3040 3041 ctx.fillStyle = '#0f0'; 3042 ctx.fillRect(0, 0, 100, 50); 3043 3044 @assert pixel 50,25 == 0,255,0,255; 3045 expected: green 3046 3047 - name: 2d.path.clip.basic.2 3048 code: | 3049 ctx.fillStyle = '#0f0'; 3050 ctx.fillRect(0, 0, 100, 50); 3051 3052 ctx.beginPath(); 3053 ctx.rect(-100, 0, 100, 50); 3054 ctx.clip(); 3055 3056 ctx.fillStyle = '#f00'; 3057 ctx.fillRect(0, 0, 100, 50); 3058 3059 @assert pixel 50,25 == 0,255,0,255; 3060 expected: green 3061 3062 - name: 2d.path.clip.intersect 3063 code: | 3064 ctx.fillStyle = '#0f0'; 3065 ctx.fillRect(0, 0, 100, 50); 3066 3067 ctx.beginPath(); 3068 ctx.rect(0, 0, 50, 50); 3069 ctx.clip(); 3070 ctx.beginPath(); 3071 ctx.rect(50, 0, 50, 50) 3072 ctx.clip(); 3073 3074 ctx.fillStyle = '#f00'; 3075 ctx.fillRect(0, 0, 100, 50); 3076 3077 @assert pixel 50,25 == 0,255,0,255; 3078 expected: green 3079 3080 - name: 2d.path.clip.winding.evenodd.1 3081 desc: evenodd winding number rule works in clip 3082 code: | 3083 ctx.fillStyle = '#0f0'; 3084 ctx.fillRect(0, 0, 100, 50); 3085 3086 ctx.beginPath(); 3087 ctx.rect(0, 0, 100, 50); 3088 ctx.rect(0, 0, 100, 50); 3089 3090 ctx.fillStyle = "#f00"; 3091 ctx.clip("evenodd"); 3092 ctx.fillRect(0, 0, 100, 50); 3093 3094 @assert pixel 50,25 == 0,255,0,255; 3095 3096 - name: 2d.path.clip.winding.evenodd.2 3097 desc: evenodd winding number rule works in clip 3098 code: | 3099 ctx.fillStyle = '#0f0'; 3100 ctx.fillRect(0, 0, 100, 50); 3101 3102 let path = new Path2D(); 3103 path.rect(0, 0, 100, 50); 3104 path.rect(0, 0, 100, 50); 3105 path.closePath(); 3106 3107 ctx.fillStyle = "#f00"; 3108 ctx.clip(path, "evenodd"); 3109 ctx.fillRect(0, 0, 100, 50); 3110 3111 @assert pixel 50,25 == 0,255,0,255; 3112 3113 - name: 2d.path.clip.winding.1 3114 code: | 3115 ctx.fillStyle = '#0f0'; 3116 ctx.fillRect(0, 0, 100, 50); 3117 3118 ctx.beginPath(); 3119 ctx.moveTo(-10, -10); 3120 ctx.lineTo(110, -10); 3121 ctx.lineTo(110, 60); 3122 ctx.lineTo(-10, 60); 3123 ctx.lineTo(-10, -10); 3124 ctx.lineTo(0, 0); 3125 ctx.lineTo(0, 50); 3126 ctx.lineTo(100, 50); 3127 ctx.lineTo(100, 0); 3128 ctx.clip(); 3129 3130 ctx.fillStyle = '#f00'; 3131 ctx.fillRect(0, 0, 100, 50); 3132 3133 @assert pixel 50,25 == 0,255,0,255; 3134 expected: green 3135 3136 - name: 2d.path.clip.winding.2 3137 code: | 3138 ctx.fillStyle = '#f00'; 3139 ctx.fillRect(0, 0, 100, 50); 3140 3141 ctx.beginPath(); 3142 ctx.moveTo(-10, -10); 3143 ctx.lineTo(110, -10); 3144 ctx.lineTo(110, 60); 3145 ctx.lineTo(-10, 60); 3146 ctx.lineTo(-10, -10); 3147 ctx.clip(); 3148 3149 ctx.beginPath(); 3150 ctx.moveTo(0, 0); 3151 ctx.lineTo(0, 50); 3152 ctx.lineTo(100, 50); 3153 ctx.lineTo(100, 0); 3154 ctx.lineTo(0, 0); 3155 ctx.clip(); 3156 3157 ctx.fillStyle = '#0f0'; 3158 ctx.fillRect(0, 0, 100, 50); 3159 3160 @assert pixel 50,25 == 0,255,0,255; 3161 expected: green 3162 3163 - name: 2d.path.clip.unaffected 3164 code: | 3165 ctx.fillStyle = '#f00'; 3166 ctx.fillRect(0, 0, 100, 50); 3167 3168 ctx.fillStyle = '#0f0'; 3169 3170 ctx.beginPath(); 3171 ctx.moveTo(0, 0); 3172 ctx.lineTo(0, 50); 3173 ctx.lineTo(100, 50); 3174 ctx.lineTo(100, 0); 3175 ctx.clip(); 3176 3177 ctx.lineTo(0, 0); 3178 ctx.fill(); 3179 3180 @assert pixel 50,25 == 0,255,0,255; 3181 expected: green 3182 3183 3184 3185 - name: 2d.path.isPointInPath.basic.1 3186 desc: isPointInPath() detects whether the point is inside the path 3187 code: | 3188 ctx.rect(0, 0, 20, 20); 3189 @assert ctx.isPointInPath(10, 10) === true; 3190 @assert ctx.isPointInPath(30, 10) === false; 3191 3192 - name: 2d.path.isPointInPath.basic.2 3193 desc: isPointInPath() detects whether the point is inside the path 3194 code: | 3195 ctx.rect(20, 0, 20, 20); 3196 @assert ctx.isPointInPath(10, 10) === false; 3197 @assert ctx.isPointInPath(30, 10) === true; 3198 3199 - name: 2d.path.isPointInPath.edge 3200 desc: isPointInPath() counts points on the path as being inside 3201 code: | 3202 ctx.rect(0, 0, 20, 20); 3203 @assert ctx.isPointInPath(0, 0) === true; 3204 @assert ctx.isPointInPath(10, 0) === true; 3205 @assert ctx.isPointInPath(20, 0) === true; 3206 @assert ctx.isPointInPath(20, 10) === true; 3207 @assert ctx.isPointInPath(20, 20) === true; 3208 @assert ctx.isPointInPath(10, 20) === true; 3209 @assert ctx.isPointInPath(0, 20) === true; 3210 @assert ctx.isPointInPath(0, 10) === true; 3211 @assert ctx.isPointInPath(10, -0.01) === false; 3212 @assert ctx.isPointInPath(10, 20.01) === false; 3213 @assert ctx.isPointInPath(-0.01, 10) === false; 3214 @assert ctx.isPointInPath(20.01, 10) === false; 3215 3216 - name: 2d.path.isPointInPath.empty 3217 desc: isPointInPath() works when there is no path 3218 code: | 3219 @assert ctx.isPointInPath(0, 0) === false; 3220 3221 - name: 2d.path.isPointInPath.subpath 3222 desc: isPointInPath() uses the current path, not just the subpath 3223 code: | 3224 ctx.rect(0, 0, 20, 20); 3225 ctx.beginPath(); 3226 ctx.rect(20, 0, 20, 20); 3227 ctx.closePath(); 3228 ctx.rect(40, 0, 20, 20); 3229 @assert ctx.isPointInPath(10, 10) === false; 3230 @assert ctx.isPointInPath(30, 10) === true; 3231 @assert ctx.isPointInPath(50, 10) === true; 3232 3233 - name: 2d.path.isPointInPath.outside 3234 desc: isPointInPath() works on paths outside the canvas 3235 code: | 3236 ctx.rect(0, -100, 20, 20); 3237 ctx.rect(20, -10, 20, 20); 3238 @assert ctx.isPointInPath(10, -110) === false; 3239 @assert ctx.isPointInPath(10, -90) === true; 3240 @assert ctx.isPointInPath(10, -70) === false; 3241 @assert ctx.isPointInPath(30, -20) === false; 3242 @assert ctx.isPointInPath(30, 0) === true; 3243 @assert ctx.isPointInPath(30, 20) === false; 3244 3245 - name: 2d.path.isPointInPath.unclosed 3246 desc: isPointInPath() works on unclosed subpaths 3247 code: | 3248 ctx.moveTo(0, 0); 3249 ctx.lineTo(20, 0); 3250 ctx.lineTo(20, 20); 3251 ctx.lineTo(0, 20); 3252 @assert ctx.isPointInPath(10, 10) === true; 3253 @assert ctx.isPointInPath(30, 10) === false; 3254 3255 - name: 2d.path.isPointInPath.arc 3256 desc: isPointInPath() works on arcs 3257 code: | 3258 ctx.arc(50, 25, 10, 0, Math.PI, false); 3259 @assert ctx.isPointInPath(50, 10) === false; 3260 @assert ctx.isPointInPath(50, 20) === false; 3261 @assert ctx.isPointInPath(50, 30) === true; 3262 @assert ctx.isPointInPath(50, 40) === false; 3263 @assert ctx.isPointInPath(30, 20) === false; 3264 @assert ctx.isPointInPath(70, 20) === false; 3265 @assert ctx.isPointInPath(30, 30) === false; 3266 @assert ctx.isPointInPath(70, 30) === false; 3267 3268 - name: 2d.path.isPointInPath.bigarc 3269 desc: isPointInPath() works on unclosed arcs larger than 2pi 3270 opera: {bug: 320937} 3271 code: | 3272 ctx.arc(50, 25, 10, 0, 7, false); 3273 @assert ctx.isPointInPath(50, 10) === false; 3274 @assert ctx.isPointInPath(50, 20) === true; 3275 @assert ctx.isPointInPath(50, 30) === true; 3276 @assert ctx.isPointInPath(50, 40) === false; 3277 @assert ctx.isPointInPath(30, 20) === false; 3278 @assert ctx.isPointInPath(70, 20) === false; 3279 @assert ctx.isPointInPath(30, 30) === false; 3280 @assert ctx.isPointInPath(70, 30) === false; 3281 3282 - name: 2d.path.isPointInPath.bezier 3283 desc: isPointInPath() works on Bezier curves 3284 code: | 3285 ctx.moveTo(25, 25); 3286 ctx.bezierCurveTo(50, -50, 50, 100, 75, 25); 3287 @assert ctx.isPointInPath(25, 20) === false; 3288 @assert ctx.isPointInPath(25, 30) === false; 3289 @assert ctx.isPointInPath(30, 20) === true; 3290 @assert ctx.isPointInPath(30, 30) === false; 3291 @assert ctx.isPointInPath(40, 2) === false; 3292 @assert ctx.isPointInPath(40, 20) === true; 3293 @assert ctx.isPointInPath(40, 30) === false; 3294 @assert ctx.isPointInPath(40, 47) === false; 3295 @assert ctx.isPointInPath(45, 20) === true; 3296 @assert ctx.isPointInPath(45, 30) === false; 3297 @assert ctx.isPointInPath(55, 20) === false; 3298 @assert ctx.isPointInPath(55, 30) === true; 3299 @assert ctx.isPointInPath(60, 2) === false; 3300 @assert ctx.isPointInPath(60, 20) === false; 3301 @assert ctx.isPointInPath(60, 30) === true; 3302 @assert ctx.isPointInPath(60, 47) === false; 3303 @assert ctx.isPointInPath(70, 20) === false; 3304 @assert ctx.isPointInPath(70, 30) === true; 3305 @assert ctx.isPointInPath(75, 20) === false; 3306 @assert ctx.isPointInPath(75, 30) === false; 3307 3308 - name: 2d.path.isPointInPath.winding 3309 desc: isPointInPath() uses the non-zero winding number rule 3310 code: | 3311 // Create a square ring, using opposite windings to make a hole in the centre 3312 ctx.moveTo(0, 0); 3313 ctx.lineTo(50, 0); 3314 ctx.lineTo(50, 50); 3315 ctx.lineTo(0, 50); 3316 ctx.lineTo(0, 0); 3317 ctx.lineTo(10, 10); 3318 ctx.lineTo(10, 40); 3319 ctx.lineTo(40, 40); 3320 ctx.lineTo(40, 10); 3321 ctx.lineTo(10, 10); 3322 3323 @assert ctx.isPointInPath(5, 5) === true; 3324 @assert ctx.isPointInPath(25, 5) === true; 3325 @assert ctx.isPointInPath(45, 5) === true; 3326 @assert ctx.isPointInPath(5, 25) === true; 3327 @assert ctx.isPointInPath(25, 25) === false; 3328 @assert ctx.isPointInPath(45, 25) === true; 3329 @assert ctx.isPointInPath(5, 45) === true; 3330 @assert ctx.isPointInPath(25, 45) === true; 3331 @assert ctx.isPointInPath(45, 45) === true; 3332 3333 - name: 2d.path.isPointInPath.transform.1 3334 desc: isPointInPath() handles transformations correctly 3335 code: | 3336 ctx.translate(50, 0); 3337 ctx.rect(0, 0, 20, 20); 3338 @assert ctx.isPointInPath(-40, 10) === false; 3339 @assert ctx.isPointInPath(10, 10) === false; 3340 @assert ctx.isPointInPath(49, 10) === false; 3341 @assert ctx.isPointInPath(51, 10) === true; 3342 @assert ctx.isPointInPath(69, 10) === true; 3343 @assert ctx.isPointInPath(71, 10) === false; 3344 3345 - name: 2d.path.isPointInPath.transform.2 3346 desc: isPointInPath() handles transformations correctly 3347 code: | 3348 ctx.rect(50, 0, 20, 20); 3349 ctx.translate(50, 0); 3350 @assert ctx.isPointInPath(-40, 10) === false; 3351 @assert ctx.isPointInPath(10, 10) === false; 3352 @assert ctx.isPointInPath(49, 10) === false; 3353 @assert ctx.isPointInPath(51, 10) === true; 3354 @assert ctx.isPointInPath(69, 10) === true; 3355 @assert ctx.isPointInPath(71, 10) === false; 3356 3357 - name: 2d.path.isPointInPath.transform.3 3358 desc: isPointInPath() handles transformations correctly 3359 code: | 3360 ctx.scale(-1, 1); 3361 ctx.rect(-70, 0, 20, 20); 3362 @assert ctx.isPointInPath(-40, 10) === false; 3363 @assert ctx.isPointInPath(10, 10) === false; 3364 @assert ctx.isPointInPath(49, 10) === false; 3365 @assert ctx.isPointInPath(51, 10) === true; 3366 @assert ctx.isPointInPath(69, 10) === true; 3367 @assert ctx.isPointInPath(71, 10) === false; 3368 3369 - name: 2d.path.isPointInPath.transform.4 3370 desc: isPointInPath() handles transformations correctly 3371 code: | 3372 ctx.translate(50, 0); 3373 ctx.rect(50, 0, 20, 20); 3374 ctx.translate(0, 50); 3375 @assert ctx.isPointInPath(60, 10) === false; 3376 @assert ctx.isPointInPath(110, 10) === true; 3377 @assert ctx.isPointInPath(110, 60) === false; 3378 3379 - name: 2d.path.isPointInPath.nonfinite 3380 desc: isPointInPath() returns false for non-finite arguments 3381 code: | 3382 ctx.rect(-100, -50, 200, 100); 3383 @assert ctx.isPointInPath(Infinity, 0) === false; 3384 @assert ctx.isPointInPath(-Infinity, 0) === false; 3385 @assert ctx.isPointInPath(NaN, 0) === false; 3386 @assert ctx.isPointInPath(0, Infinity) === false; 3387 @assert ctx.isPointInPath(0, -Infinity) === false; 3388 @assert ctx.isPointInPath(0, NaN) === false; 3389 @assert ctx.isPointInPath(NaN, NaN) === false; 3390 3391 3392 - name: 2d.path.isPointInStroke.scaleddashes 3393 desc: isPointInStroke() should return correct results on dashed paths at high scale 3394 factors 3395 code: | 3396 var scale = 20; 3397 ctx.setLineDash([10, 21.4159]); // dash from t=0 to t=10 along the circle 3398 ctx.scale(scale, scale); 3399 ctx.ellipse(6, 10, 5, 5, 0, 2*Math.PI, false); 3400 ctx.stroke(); 3401 3402 // hit-test the beginning of the dash (t=0) 3403 @assert ctx.isPointInStroke(11*scale, 10*scale) === true; 3404 // hit-test the middle of the dash (t=5) 3405 @assert ctx.isPointInStroke(8.70*scale, 14.21*scale) === true; 3406 // hit-test the end of the dash (t=9.8) 3407 @assert ctx.isPointInStroke(4.10*scale, 14.63*scale) === true; 3408 // hit-test past the end of the dash (t=10.2) 3409 @assert ctx.isPointInStroke(3.74*scale, 14.46*scale) === false; 3410 3411 - name: 2d.path.isPointInPath.basic 3412 desc: Verify the winding rule in isPointInPath works for for rect path. 3413 code: | 3414 canvas.width = 200; 3415 canvas.height = 200; 3416 3417 // Testing default isPointInPath 3418 ctx.beginPath(); 3419 ctx.rect(0, 0, 100, 100); 3420 ctx.rect(25, 25, 50, 50); 3421 @assert ctx.isPointInPath(50, 50) === true; 3422 @assert ctx.isPointInPath(NaN, 50) === false; 3423 @assert ctx.isPointInPath(50, NaN) === false; 3424 3425 // Testing nonzero isPointInPath 3426 ctx.beginPath(); 3427 ctx.rect(0, 0, 100, 100); 3428 ctx.rect(25, 25, 50, 50); 3429 @assert ctx.isPointInPath(50, 50, 'nonzero') === true; 3430 3431 // Testing evenodd isPointInPath 3432 ctx.beginPath(); 3433 ctx.rect(0, 0, 100, 100); 3434 ctx.rect(25, 25, 50, 50); 3435 @assert ctx.isPointInPath(50, 50, 'evenodd') === false; 3436 3437 // Testing extremely large scale 3438 ctx.save(); 3439 ctx.scale(Number.MAX_VALUE, Number.MAX_VALUE); 3440 ctx.beginPath(); 3441 ctx.rect(-10, -10, 20, 20); 3442 @assert ctx.isPointInPath(0, 0, 'nonzero') === true; 3443 @assert ctx.isPointInPath(0, 0, 'evenodd') === true; 3444 ctx.restore(); 3445 3446 // Check with non-invertible ctm. 3447 ctx.save(); 3448 ctx.scale(0, 0); 3449 ctx.beginPath(); 3450 ctx.rect(-10, -10, 20, 20); 3451 @assert ctx.isPointInPath(0, 0, 'nonzero') === false; 3452 @assert ctx.isPointInPath(0, 0, 'evenodd') === false; 3453 ctx.restore(); 3454 3455 - name: 2d.path.isPointInpath.multi.path 3456 desc: Verify the winding rule in isPointInPath works for path object. 3457 code: | 3458 canvas.width = 200; 3459 canvas.height = 200; 3460 3461 // Testing default isPointInPath with Path object'); 3462 path = new Path2D(); 3463 path.rect(0, 0, 100, 100); 3464 path.rect(25, 25, 50, 50); 3465 @assert ctx.isPointInPath(path, 50, 50) === true; 3466 @assert ctx.isPointInPath(path, 50, 50, undefined) === true; 3467 @assert ctx.isPointInPath(path, NaN, 50) === false; 3468 @assert ctx.isPointInPath(path, 50, NaN) === false; 3469 3470 // Testing nonzero isPointInPath with Path object'); 3471 path = new Path2D(); 3472 path.rect(0, 0, 100, 100); 3473 path.rect(25, 25, 50, 50); 3474 @assert ctx.isPointInPath(path, 50, 50, 'nonzero') === true; 3475 3476 // Testing evenodd isPointInPath with Path object'); 3477 path = new Path2D(); 3478 path.rect(0, 0, 100, 100); 3479 path.rect(25, 25, 50, 50); 3480 assert_false(ctx.isPointInPath(path, 50, 50, 'evenodd')); 3481 3482 - name: 2d.path.isPointInpath.invalid 3483 desc: Verify isPointInPath throws exceptions with invalid inputs. 3484 code: | 3485 canvas.width = 200; 3486 canvas.height = 200; 3487 path = new Path2D(); 3488 path.rect(0, 0, 100, 100); 3489 path.rect(25, 25, 50, 50); 3490 // Testing invalid enumeration isPointInPath (w/ and w/o Path object'); 3491 @assert throws TypeError ctx.isPointInPath(path, 50, 50, 'gazonk'); 3492 @assert throws TypeError ctx.isPointInPath(50, 50, 'gazonk'); 3493 3494 // Testing invalid type isPointInPath with Path object'); 3495 @assert throws TypeError ctx.isPointInPath(null, 50, 50); 3496 @assert throws TypeError ctx.isPointInPath(null, 50, 50, 'nonzero'); 3497 @assert throws TypeError ctx.isPointInPath(null, 50, 50, 'evenodd'); 3498 @assert throws TypeError ctx.isPointInPath(null, 50, 50, null); 3499 @assert throws TypeError ctx.isPointInPath(path, 50, 50, null); 3500 @assert throws TypeError ctx.isPointInPath(undefined, 50, 50); 3501 @assert throws TypeError ctx.isPointInPath(undefined, 50, 50, 'nonzero'); 3502 @assert throws TypeError ctx.isPointInPath(undefined, 50, 50, 'evenodd'); 3503 @assert throws TypeError ctx.isPointInPath(undefined, 50, 50, undefined); 3504 @assert throws TypeError ctx.isPointInPath([], 50, 50); 3505 @assert throws TypeError ctx.isPointInPath([], 50, 50, 'nonzero'); 3506 @assert throws TypeError ctx.isPointInPath([], 50, 50, 'evenodd'); 3507 @assert throws TypeError ctx.isPointInPath({}, 50, 50); 3508 @assert throws TypeError ctx.isPointInPath({}, 50, 50, 'nonzero'); 3509 @assert throws TypeError ctx.isPointInPath({}, 50, 50, 'evenodd');