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