Automatic update from web-platform-tests new reftest Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com> -- generate canvas regression test Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com> -- wpt-commits: d8943e978103c68e07637ad6114e06c1fb0d86c6, a3f19d3119a36216eac2f0dd22bb23e0f0aa7d55 wpt-pr: 59780
3528 lines
103 KiB
YAML
3528 lines
103 KiB
YAML
- name: 2d.path.initial
|
|
#mozilla: { bug: TODO }
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.closePath();
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fill();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.beginPath
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.rect(0, 0, 100, 50);
|
|
ctx.beginPath();
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fill();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.moveTo.basic
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.rect(0, 0, 10, 50);
|
|
ctx.moveTo(100, 0);
|
|
ctx.lineTo(10, 0);
|
|
ctx.lineTo(10, 50);
|
|
ctx.lineTo(100, 50);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 90,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.moveTo.newsubpath
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 0);
|
|
ctx.moveTo(100, 0);
|
|
ctx.moveTo(100, 50);
|
|
ctx.moveTo(0, 50);
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fill();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.moveTo.multiple
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.moveTo(0, 25);
|
|
ctx.moveTo(100, 25);
|
|
ctx.moveTo(0, 25);
|
|
ctx.lineTo(100, 25);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 50;
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.moveTo.nonfinite
|
|
desc: moveTo() with Infinity/NaN is ignored
|
|
code: |
|
|
ctx.moveTo(0, 0);
|
|
ctx.lineTo(100, 0);
|
|
@nonfinite ctx.moveTo(<0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>);
|
|
ctx.lineTo(100, 50);
|
|
ctx.lineTo(0, 50);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.closePath.empty
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.closePath();
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fill();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.closePath.newline
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 50;
|
|
ctx.moveTo(-100, 25);
|
|
ctx.lineTo(-100, -100);
|
|
ctx.lineTo(200, -100);
|
|
ctx.lineTo(200, 25);
|
|
ctx.closePath();
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.closePath.nextpoint
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 50;
|
|
ctx.moveTo(-100, 25);
|
|
ctx.lineTo(-100, -1000);
|
|
ctx.closePath();
|
|
ctx.lineTo(1000, 25);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.lineTo.ensuresubpath.1
|
|
desc: If there is no subpath, the point is added and nothing is drawn
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 50;
|
|
ctx.beginPath();
|
|
ctx.lineTo(100, 50);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.lineTo.ensuresubpath.2
|
|
desc: If there is no subpath, the point is added and used for subsequent drawing
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 50;
|
|
ctx.beginPath();
|
|
ctx.lineTo(0, 25);
|
|
ctx.lineTo(100, 25);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.lineTo.basic
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 50;
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 25);
|
|
ctx.lineTo(100, 25);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.lineTo.nextpoint
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 50;
|
|
ctx.beginPath();
|
|
ctx.moveTo(-100, -100);
|
|
ctx.lineTo(0, 25);
|
|
ctx.lineTo(100, 25);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.lineTo.nonfinite
|
|
desc: lineTo() with Infinity/NaN is ignored
|
|
code: |
|
|
ctx.moveTo(0, 0);
|
|
ctx.lineTo(100, 0);
|
|
@nonfinite ctx.lineTo(<0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>);
|
|
ctx.lineTo(100, 50);
|
|
ctx.lineTo(0, 50);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 90,45 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.lineTo.nonfinite.details
|
|
desc: lineTo() with Infinity/NaN for first arg still converts the second arg
|
|
code: |
|
|
for (var arg1 of [Infinity, -Infinity, NaN]) {
|
|
var converted = false;
|
|
ctx.lineTo(arg1, { valueOf: function() { converted = true; return 0; } });
|
|
@assert converted;
|
|
}
|
|
expected: clear
|
|
|
|
- name: 2d.path.quadraticCurveTo.ensuresubpath.1
|
|
desc: If there is no subpath, the first control point is added (and nothing is drawn
|
|
up to it)
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 50;
|
|
ctx.beginPath();
|
|
ctx.quadraticCurveTo(100, 50, 200, 50);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 95,45 == 0,255,0,255; @moz-todo
|
|
expected: green
|
|
|
|
- name: 2d.path.quadraticCurveTo.ensuresubpath.2
|
|
desc: If there is no subpath, the first control point is added
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 50;
|
|
ctx.beginPath();
|
|
ctx.quadraticCurveTo(0, 25, 100, 25);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 5,45 == 0,255,0,255; @moz-todo
|
|
expected: green
|
|
|
|
- name: 2d.path.quadraticCurveTo.basic
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 50;
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 25);
|
|
ctx.quadraticCurveTo(100, 25, 100, 25);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.quadraticCurveTo.shape
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 55;
|
|
ctx.beginPath();
|
|
ctx.moveTo(-1000, 1050);
|
|
ctx.quadraticCurveTo(0, -1000, 1200, 1050);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.quadraticCurveTo.scaled
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.scale(1000, 1000);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 0.055;
|
|
ctx.beginPath();
|
|
ctx.moveTo(-1, 1.05);
|
|
ctx.quadraticCurveTo(0, -1, 1.2, 1.05);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.quadraticCurveTo.nonfinite
|
|
desc: quadraticCurveTo() with Infinity/NaN is ignored
|
|
code: |
|
|
ctx.moveTo(0, 0);
|
|
ctx.lineTo(100, 0);
|
|
@nonfinite ctx.quadraticCurveTo(<0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>);
|
|
ctx.lineTo(100, 50);
|
|
ctx.lineTo(0, 50);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 90,45 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.bezierCurveTo.ensuresubpath.1
|
|
desc: If there is no subpath, the first control point is added (and nothing is drawn
|
|
up to it)
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 50;
|
|
ctx.beginPath();
|
|
ctx.bezierCurveTo(100, 50, 200, 50, 200, 50);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 95,45 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.bezierCurveTo.ensuresubpath.2
|
|
desc: If there is no subpath, the first control point is added
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 50;
|
|
ctx.beginPath();
|
|
ctx.bezierCurveTo(0, 25, 100, 25, 100, 25);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 5,45 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.bezierCurveTo.basic
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 50;
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 25);
|
|
ctx.bezierCurveTo(100, 25, 100, 25, 100, 25);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.bezierCurveTo.shape
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 55;
|
|
ctx.beginPath();
|
|
ctx.moveTo(-2000, 3100);
|
|
ctx.bezierCurveTo(-2000, -1000, 2100, -1000, 2100, 3100);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.bezierCurveTo.scaled
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.scale(1000, 1000);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 0.055;
|
|
ctx.beginPath();
|
|
ctx.moveTo(-2, 3.1);
|
|
ctx.bezierCurveTo(-2, -1, 2.1, -1, 2.1, 3.1);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.bezierCurveTo.nonfinite
|
|
desc: bezierCurveTo() with Infinity/NaN is ignored
|
|
code: |
|
|
ctx.moveTo(0, 0);
|
|
ctx.lineTo(100, 0);
|
|
@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>);
|
|
ctx.lineTo(100, 50);
|
|
ctx.lineTo(0, 50);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 90,45 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arcTo.ensuresubpath.1
|
|
desc: If there is no subpath, the first control point is added (and nothing is drawn
|
|
up to it)
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 50;
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.arcTo(100, 50, 200, 50, 0.1);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arcTo.ensuresubpath.2
|
|
desc: If there is no subpath, the first control point is added
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 50;
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.arcTo(0, 25, 50, 250, 0.1); // adds (x1,y1), draws nothing
|
|
ctx.lineTo(100, 25);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arcTo.ensuresubpath.3
|
|
desc: If there is no subpath, the first control point is added (and nothing is drawn
|
|
up to it)
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 100;
|
|
ctx.beginPath();
|
|
ctx.arcTo(50, 0, 50, 100, 100);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arcTo.coincide.1
|
|
desc: arcTo() has no effect if P0 = P1
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 50;
|
|
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 25);
|
|
ctx.arcTo(0, 25, 50, 1000, 1);
|
|
ctx.lineTo(100, 25);
|
|
ctx.stroke();
|
|
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.moveTo(50, 25);
|
|
ctx.arcTo(50, 25, 100, 25, 1);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 50,1 == 0,255,0,255;
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 50,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arcTo.coincide.2
|
|
desc: arcTo() draws a straight line to P1 if P1 = P2
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 50;
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 25);
|
|
ctx.arcTo(100, 25, 100, 25, 1);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arcTo.collinear.1
|
|
desc: arcTo() with all points on a line, and P1 between P0/P2, draws a straight
|
|
line to P1
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 50;
|
|
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 25);
|
|
ctx.arcTo(100, 25, 200, 25, 1);
|
|
ctx.stroke();
|
|
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.moveTo(-100, 25);
|
|
ctx.arcTo(0, 25, 100, 25, 1);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arcTo.collinear.2
|
|
desc: arcTo() with all points on a line, and P2 between P0/P1, draws a straight
|
|
line to P1
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 50;
|
|
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 25);
|
|
ctx.arcTo(100, 25, 10, 25, 1);
|
|
ctx.stroke();
|
|
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.moveTo(100, 25);
|
|
ctx.arcTo(200, 25, 110, 25, 1);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arcTo.collinear.3
|
|
desc: arcTo() with all points on a line, and P0 between P1/P2, draws a straight
|
|
line to P1
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 50;
|
|
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 25);
|
|
ctx.arcTo(100, 25, -100, 25, 1);
|
|
ctx.stroke();
|
|
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.moveTo(100, 25);
|
|
ctx.arcTo(200, 25, 0, 25, 1);
|
|
ctx.stroke();
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(-100, 25);
|
|
ctx.arcTo(0, 25, -200, 25, 1);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arcTo.shape.curve1
|
|
desc: arcTo() curves in the right kind of shape
|
|
code: |
|
|
var tol = 1.5; // tolerance to avoid antialiasing artifacts
|
|
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 10;
|
|
ctx.beginPath();
|
|
ctx.moveTo(10, 25);
|
|
ctx.arcTo(75, 25, 75, 60, 20);
|
|
ctx.stroke();
|
|
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.rect(10, 20, 45, 10);
|
|
ctx.moveTo(80, 45);
|
|
ctx.arc(55, 45, 25+tol, 0, -Math.PI/2, true);
|
|
ctx.arc(55, 45, 15-tol, -Math.PI/2, 0, false);
|
|
ctx.fill();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 55,19 == 0,255,0,255;
|
|
@assert pixel 55,20 == 0,255,0,255;
|
|
@assert pixel 55,21 == 0,255,0,255;
|
|
@assert pixel 64,22 == 0,255,0,255;
|
|
@assert pixel 65,21 == 0,255,0,255;
|
|
@assert pixel 72,28 == 0,255,0,255;
|
|
@assert pixel 73,27 == 0,255,0,255;
|
|
@assert pixel 78,36 == 0,255,0,255;
|
|
@assert pixel 79,35 == 0,255,0,255;
|
|
@assert pixel 80,44 == 0,255,0,255;
|
|
@assert pixel 80,45 == 0,255,0,255;
|
|
@assert pixel 80,46 == 0,255,0,255;
|
|
@assert pixel 65,45 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arcTo.shape.curve2
|
|
desc: arcTo() curves in the right kind of shape
|
|
code: |
|
|
var tol = 1.5; // tolerance to avoid antialiasing artifacts
|
|
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.fillStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.rect(10, 20, 45, 10);
|
|
ctx.moveTo(80, 45);
|
|
ctx.arc(55, 45, 25-tol, 0, -Math.PI/2, true);
|
|
ctx.arc(55, 45, 15+tol, -Math.PI/2, 0, false);
|
|
ctx.fill();
|
|
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 10;
|
|
ctx.beginPath();
|
|
ctx.moveTo(10, 25);
|
|
ctx.arcTo(75, 25, 75, 60, 20);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 55,19 == 0,255,0,255;
|
|
@assert pixel 55,20 == 0,255,0,255;
|
|
@assert pixel 55,21 == 0,255,0,255;
|
|
@assert pixel 64,22 == 0,255,0,255;
|
|
@assert pixel 65,21 == 0,255,0,255;
|
|
@assert pixel 72,28 == 0,255,0,255;
|
|
@assert pixel 73,27 == 0,255,0,255;
|
|
@assert pixel 78,36 == 0,255,0,255;
|
|
@assert pixel 79,35 == 0,255,0,255;
|
|
@assert pixel 80,44 == 0,255,0,255;
|
|
@assert pixel 80,45 == 0,255,0,255;
|
|
@assert pixel 80,46 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arcTo.shape.start
|
|
desc: arcTo() draws a straight line from P0 to P1
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 50;
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 25);
|
|
ctx.arcTo(200, 25, 200, 50, 10);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arcTo.shape.end
|
|
desc: arcTo() does not draw anything from P1 to P2
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 50;
|
|
ctx.beginPath();
|
|
ctx.moveTo(-100, -100);
|
|
ctx.arcTo(-100, 25, 200, 25, 10);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arcTo.negative
|
|
desc: arcTo() with negative radius throws an exception
|
|
code: |
|
|
@assert throws INDEX_SIZE_ERR ctx.arcTo(0, 0, 0, 0, -1);
|
|
var path = new Path2D();
|
|
@assert throws INDEX_SIZE_ERR path.arcTo(10, 10, 20, 20, -5);
|
|
|
|
- name: 2d.path.arcTo.zero.1
|
|
desc: arcTo() with zero radius draws a straight line from P0 to P1
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 50;
|
|
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 25);
|
|
ctx.arcTo(100, 25, 100, 100, 0);
|
|
ctx.stroke();
|
|
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, -25);
|
|
ctx.arcTo(50, -25, 50, 50, 0);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arcTo.zero.2
|
|
desc: arcTo() with zero radius draws a straight line from P0 to P1, even when all
|
|
points are collinear
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 50;
|
|
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 25);
|
|
ctx.arcTo(100, 25, -100, 25, 0);
|
|
ctx.stroke();
|
|
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.moveTo(100, 25);
|
|
ctx.arcTo(200, 25, 50, 25, 0);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arcTo.transformation
|
|
desc: arcTo joins up to the last subpath point correctly
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 50);
|
|
ctx.translate(100, 0);
|
|
ctx.arcTo(50, 50, 50, 0, 50);
|
|
ctx.lineTo(-100, 0);
|
|
ctx.fill();
|
|
|
|
@assert pixel 0,0 == 0,255,0,255;
|
|
@assert pixel 50,0 == 0,255,0,255;
|
|
@assert pixel 99,0 == 0,255,0,255;
|
|
@assert pixel 0,25 == 0,255,0,255;
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 99,25 == 0,255,0,255;
|
|
@assert pixel 0,49 == 0,255,0,255;
|
|
@assert pixel 50,49 == 0,255,0,255;
|
|
@assert pixel 99,49 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arcTo.scale
|
|
desc: arcTo scales the curve, not just the control points
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 50);
|
|
ctx.translate(100, 0);
|
|
ctx.scale(0.1, 1);
|
|
ctx.arcTo(50, 50, 50, 0, 50);
|
|
ctx.lineTo(-1000, 0);
|
|
ctx.fill();
|
|
|
|
@assert pixel 0,0 == 0,255,0,255;
|
|
@assert pixel 50,0 == 0,255,0,255;
|
|
@assert pixel 99,0 == 0,255,0,255;
|
|
@assert pixel 0,25 == 0,255,0,255;
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 99,25 == 0,255,0,255;
|
|
@assert pixel 0,49 == 0,255,0,255;
|
|
@assert pixel 50,49 == 0,255,0,255;
|
|
@assert pixel 99,49 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arcTo.nonfinite
|
|
desc: arcTo() with Infinity/NaN is ignored
|
|
code: |
|
|
ctx.moveTo(0, 0);
|
|
ctx.lineTo(100, 0);
|
|
@nonfinite ctx.arcTo(<0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>);
|
|
ctx.lineTo(100, 50);
|
|
ctx.lineTo(0, 50);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 90,45 == 0,255,0,255;
|
|
expected: green
|
|
|
|
|
|
- name: 2d.path.arc.empty
|
|
desc: arc() with an empty path does not draw a straight line to the start point
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 50;
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.arc(200, 25, 5, 0, 2*Math.PI, true);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.nonempty
|
|
desc: arc() with a non-empty path does draw a straight line to the start point
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 50;
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 25);
|
|
ctx.arc(200, 25, 5, 0, 2*Math.PI, true);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.end
|
|
desc: arc() adds the end point of the arc to the subpath
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 50;
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.moveTo(-100, 0);
|
|
ctx.arc(-100, 0, 25, -Math.PI/2, Math.PI/2, true);
|
|
ctx.lineTo(100, 25);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.default
|
|
desc: arc() with missing last argument defaults to clockwise
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.fillStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.moveTo(100, 0);
|
|
ctx.arc(100, 0, 150, -Math.PI, Math.PI/2);
|
|
ctx.fill();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.angle.1
|
|
desc: arc() draws pi/2 .. -pi anticlockwise correctly
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.fillStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.moveTo(100, 0);
|
|
ctx.arc(100, 0, 150, Math.PI/2, -Math.PI, true);
|
|
ctx.fill();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.angle.2
|
|
desc: arc() draws -3pi/2 .. -pi anticlockwise correctly
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.fillStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.moveTo(100, 0);
|
|
ctx.arc(100, 0, 150, -3*Math.PI/2, -Math.PI, true);
|
|
ctx.fill();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.angle.3
|
|
desc: arc() wraps angles mod 2pi when anticlockwise and end > start+2pi
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.fillStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.moveTo(100, 0);
|
|
ctx.arc(100, 0, 150, (512+1/2)*Math.PI, (1024-1)*Math.PI, true);
|
|
ctx.fill();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.angle.4
|
|
desc: arc() draws a full circle when clockwise and end > start+2pi
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.moveTo(50, 25);
|
|
ctx.arc(50, 25, 60, (512+1/2)*Math.PI, (1024-1)*Math.PI, false);
|
|
ctx.fill();
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.angle.5
|
|
desc: arc() wraps angles mod 2pi when clockwise and start > end+2pi
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.fillStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.moveTo(100, 0);
|
|
ctx.arc(100, 0, 150, (1024-1)*Math.PI, (512+1/2)*Math.PI, false);
|
|
ctx.fill();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.angle.6
|
|
desc: arc() draws a full circle when anticlockwise and start > end+2pi
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.moveTo(50, 25);
|
|
ctx.arc(50, 25, 60, (1024-1)*Math.PI, (512+1/2)*Math.PI, true);
|
|
ctx.fill();
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.zero.1
|
|
desc: arc() draws nothing when startAngle = endAngle and anticlockwise
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 100;
|
|
ctx.beginPath();
|
|
ctx.arc(50, 25, 50, 0, 0, true);
|
|
ctx.stroke();
|
|
@assert pixel 50,20 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.zero.2
|
|
desc: arc() draws nothing when startAngle = endAngle and clockwise
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 100;
|
|
ctx.beginPath();
|
|
ctx.arc(50, 25, 50, 0, 0, false);
|
|
ctx.stroke();
|
|
@assert pixel 50,20 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.twopie.1
|
|
desc: arc() draws nothing when end = start + 2pi-e and anticlockwise
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 100;
|
|
ctx.beginPath();
|
|
ctx.arc(50, 25, 50, 0, 2*Math.PI - 1e-4, true);
|
|
ctx.stroke();
|
|
@assert pixel 50,20 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.twopie.2
|
|
desc: arc() draws a full circle when end = start + 2pi-e and clockwise
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 100;
|
|
ctx.beginPath();
|
|
ctx.arc(50, 25, 50, 0, 2*Math.PI - 1e-4, false);
|
|
ctx.stroke();
|
|
@assert pixel 50,20 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.twopie.3
|
|
desc: arc() draws a full circle when end = start + 2pi+e and anticlockwise
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 100;
|
|
ctx.beginPath();
|
|
ctx.arc(50, 25, 50, 0, 2*Math.PI + 1e-4, true);
|
|
ctx.stroke();
|
|
@assert pixel 50,20 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.twopie.4
|
|
desc: arc() draws nothing when end = start + 2pi+e and clockwise
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 100;
|
|
ctx.beginPath();
|
|
ctx.arc(50, 25, 50, 0, 2*Math.PI + 1e-4, false);
|
|
ctx.stroke();
|
|
@assert pixel 50,20 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.twopie.5
|
|
desc: arc() draws correctly when start = 2 and end = start + 2pi+e and clockwise
|
|
code: |
|
|
ctx.fillStyle = '#fff';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.fillStyle = '#000';
|
|
ctx.beginPath();
|
|
ctx.moveTo(50, 25);
|
|
ctx.arc(50, 25, 50, 2, 2 + 2*Math.PI, false);
|
|
ctx.closePath();
|
|
ctx.fill();
|
|
@assert pixel 95,25 == 0,0,0,255;
|
|
|
|
- name: 2d.path.arc.twopie.6
|
|
desc: arc() draws correctly when start = 5 and end = start + 2pi+e and clockwise
|
|
code: |
|
|
ctx.fillStyle = '#fff';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.fillStyle = '#000';
|
|
ctx.beginPath();
|
|
ctx.moveTo(50, 25);
|
|
ctx.arc(50, 25, 50, 5, 5 + 2*Math.PI, false);
|
|
ctx.closePath();
|
|
ctx.fill();
|
|
@assert pixel 5,25 == 0,0,0,255;
|
|
|
|
- name: 2d.path.arc.shape.1
|
|
desc: arc() from 0 to pi does not draw anything in the wrong half
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 50;
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.arc(50, 50, 50, 0, Math.PI, false);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
@assert pixel 20,48 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.shape.2
|
|
desc: arc() from 0 to pi draws stuff in the right half
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 100;
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.arc(50, 50, 50, 0, Math.PI, true);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
@assert pixel 20,48 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.shape.3
|
|
desc: arc() from 0 to -pi/2 does not draw anything in the wrong quadrant
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 100;
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.arc(0, 50, 50, 0, -Math.PI/2, false);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255; @moz-todo
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.shape.4
|
|
desc: arc() from 0 to -pi/2 draws stuff in the right quadrant
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 150;
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.arc(-50, 50, 100, 0, -Math.PI/2, true);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.shape.5
|
|
desc: arc() from 0 to 5pi does not draw crazy things
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 200;
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.arc(300, 0, 100, 0, 5*Math.PI, false);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.selfintersect.1
|
|
desc: arc() with lineWidth > 2*radius is drawn sensibly
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 200;
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.arc(100, 50, 25, 0, -Math.PI/2, true);
|
|
ctx.stroke();
|
|
ctx.beginPath();
|
|
ctx.arc(0, 0, 25, 0, -Math.PI/2, true);
|
|
ctx.stroke();
|
|
@assert pixel 1,1 == 0,255,0,255; @moz-todo
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.selfintersect.2
|
|
desc: arc() with lineWidth > 2*radius is drawn sensibly
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 180;
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.arc(-50, 50, 25, 0, -Math.PI/2, true);
|
|
ctx.stroke();
|
|
ctx.beginPath();
|
|
ctx.arc(100, 0, 25, 0, -Math.PI/2, true);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 90,10 == 0,255,0,255;
|
|
@assert pixel 97,1 == 0,255,0,255;
|
|
@assert pixel 97,2 == 0,255,0,255;
|
|
@assert pixel 97,3 == 0,255,0,255;
|
|
@assert pixel 2,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.negative
|
|
desc: arc() with negative radius throws INDEX_SIZE_ERR
|
|
code: |
|
|
@assert throws INDEX_SIZE_ERR ctx.arc(0, 0, -1, 0, 0, true);
|
|
var path = new Path2D();
|
|
@assert throws INDEX_SIZE_ERR path.arc(10, 10, -5, 0, 1, false);
|
|
|
|
- name: 2d.path.arc.zeroradius
|
|
desc: arc() with zero radius draws a line to the start point
|
|
code: |
|
|
ctx.fillStyle = '#f00'
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.lineWidth = 50;
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 25);
|
|
ctx.arc(200, 25, 0, 0, Math.PI, true);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.scale.1
|
|
desc: Non-uniformly scaled arcs are the right shape
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.scale(2, 0.5);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.beginPath();
|
|
ctx.arc(25, 50, 56, 0, 2*Math.PI, false);
|
|
ctx.fill();
|
|
ctx.fillStyle = '#f00';
|
|
ctx.beginPath();
|
|
ctx.moveTo(-25, 50);
|
|
ctx.arc(-25, 50, 24, 0, 2*Math.PI, false);
|
|
ctx.moveTo(75, 50);
|
|
ctx.arc(75, 50, 24, 0, 2*Math.PI, false);
|
|
ctx.moveTo(25, -25);
|
|
ctx.arc(25, -25, 24, 0, 2*Math.PI, false);
|
|
ctx.moveTo(25, 125);
|
|
ctx.arc(25, 125, 24, 0, 2*Math.PI, false);
|
|
ctx.fill();
|
|
|
|
@assert pixel 0,0 == 0,255,0,255;
|
|
@assert pixel 50,0 == 0,255,0,255;
|
|
@assert pixel 99,0 == 0,255,0,255;
|
|
@assert pixel 0,25 == 0,255,0,255;
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 99,25 == 0,255,0,255;
|
|
@assert pixel 0,49 == 0,255,0,255;
|
|
@assert pixel 50,49 == 0,255,0,255;
|
|
@assert pixel 99,49 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.scale.2
|
|
desc: Highly scaled arcs are the right shape
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.scale(100, 100);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 1.2;
|
|
ctx.beginPath();
|
|
ctx.arc(0, 0, 0.6, 0, Math.PI/2, false);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 50,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,25 == 0,255,0,255;
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 98,25 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
@assert pixel 50,48 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.arc.nonfinite
|
|
desc: arc() with Infinity/NaN is ignored
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.moveTo(0, 0);
|
|
ctx.lineTo(100, 0);
|
|
@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>);
|
|
ctx.lineTo(100, 50);
|
|
ctx.lineTo(0, 50);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 90,45 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.closed.arc
|
|
desc: line caps should not be drawn on closed arcs
|
|
size: [300, 300]
|
|
code: |
|
|
ctx.beginPath();
|
|
ctx.strokeStyle = 'red';
|
|
ctx.lineWidth = 20;
|
|
ctx.lineCap = 'square';
|
|
ctx.arc(150, 150, 50, 0, 2 * Math.PI);
|
|
ctx.closePath();
|
|
ctx.stroke();
|
|
// The pixel (209, 148) is part of the line cap, but not part of the circle.
|
|
// Linecap is not drawn if the circle is closed, so the pixel is not red.
|
|
assert_not_equals(ctx.getImageData(209, 148, 1, 1).data, [255, 0, 0, 255])
|
|
|
|
- name: 2d.path.open.arc
|
|
desc: line caps should be drawn on open arcs
|
|
size: [300, 300]
|
|
code: |
|
|
ctx.beginPath();
|
|
ctx.strokeStyle = 'red';
|
|
ctx.lineWidth = 20;
|
|
ctx.lineCap = 'square';
|
|
ctx.arc(150, 150, 50, 0, 2 * Math.PI);
|
|
ctx.stroke();
|
|
// The pixel (209, 148) is part of the line cap, but not part of the circle.
|
|
// Linecap is drawn with 360 degree arc, so the pixel is red.
|
|
@assert pixel 209,148 ==~ 255,0,0,255 +/- 1;
|
|
|
|
- name: 2d.path.rect.basic
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.rect(0, 0, 100, 50);
|
|
ctx.fill();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.rect.newsubpath
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.beginPath();
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 50;
|
|
ctx.moveTo(-100, 25);
|
|
ctx.lineTo(-50, 25);
|
|
ctx.rect(200, 25, 1, 1);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.rect.closed
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 200;
|
|
ctx.lineJoin = 'miter';
|
|
ctx.rect(100, 50, 100, 100);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.rect.end.1
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 100;
|
|
ctx.rect(200, 100, 400, 1000);
|
|
ctx.lineTo(-2000, -1000);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.rect.end.2
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 450;
|
|
ctx.lineCap = 'round';
|
|
ctx.lineJoin = 'bevel';
|
|
ctx.rect(150, 150, 2000, 2000);
|
|
ctx.lineTo(160, 160);
|
|
ctx.stroke();
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.rect.zero.1
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 100;
|
|
ctx.beginPath();
|
|
ctx.rect(0, 50, 100, 0);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.rect.zero.2
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 100;
|
|
ctx.beginPath();
|
|
ctx.rect(50, -100, 0, 250);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.rect.zero.3
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 100;
|
|
ctx.beginPath();
|
|
ctx.rect(50, 25, 0, 0);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.rect.zero.4
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 50;
|
|
ctx.rect(100, 25, 0, 0);
|
|
ctx.lineTo(0, 25);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.rect.zero.5
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 50;
|
|
ctx.moveTo(0, 0);
|
|
ctx.rect(100, 25, 0, 0);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.rect.zero.6
|
|
#mozilla: { bug: TODO }
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineJoin = 'miter';
|
|
ctx.miterLimit = 1.5;
|
|
ctx.lineWidth = 200;
|
|
ctx.beginPath();
|
|
ctx.rect(100, 25, 1000, 0);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255; @moz-todo
|
|
expected: green
|
|
|
|
- name: 2d.path.rect.negative
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.beginPath();
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.rect(0, 0, 50, 25);
|
|
ctx.rect(100, 0, -50, 25);
|
|
ctx.rect(0, 50, 50, -25);
|
|
ctx.rect(100, 50, -50, -25);
|
|
ctx.fill();
|
|
@assert pixel 25,12 == 0,255,0,255;
|
|
@assert pixel 75,12 == 0,255,0,255;
|
|
@assert pixel 25,37 == 0,255,0,255;
|
|
@assert pixel 75,37 == 0,255,0,255;
|
|
|
|
- name: 2d.path.rect.winding
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.beginPath();
|
|
ctx.fillStyle = '#f00';
|
|
ctx.rect(0, 0, 50, 50);
|
|
ctx.rect(100, 50, -50, -50);
|
|
ctx.rect(0, 25, 100, -25);
|
|
ctx.rect(100, 25, -100, 25);
|
|
ctx.fill();
|
|
@assert pixel 25,12 == 0,255,0,255;
|
|
@assert pixel 75,12 == 0,255,0,255;
|
|
@assert pixel 25,37 == 0,255,0,255;
|
|
@assert pixel 75,37 == 0,255,0,255;
|
|
|
|
- name: 2d.path.rect.selfintersect
|
|
#mozilla: { bug: TODO }
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 90;
|
|
ctx.beginPath();
|
|
ctx.rect(45, 20, 10, 10);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255; @moz-todo
|
|
expected: green
|
|
|
|
- name: 2d.path.rect.nonfinite
|
|
desc: rect() with Infinity/NaN is ignored
|
|
code: |
|
|
ctx.moveTo(0, 0);
|
|
ctx.lineTo(100, 0);
|
|
@nonfinite ctx.rect(<0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <1 Infinity -Infinity NaN>, <1 Infinity -Infinity NaN>);
|
|
ctx.lineTo(100, 50);
|
|
ctx.lineTo(0, 50);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 90,45 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.roundrect.newsubpath
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.beginPath();
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 50;
|
|
ctx.moveTo(-100, 25);
|
|
ctx.lineTo(-50, 25);
|
|
ctx.roundRect(200, 25, 1, 1, [0]);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.roundrect.closed
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 200;
|
|
ctx.lineJoin = 'miter';
|
|
ctx.roundRect(100, 50, 100, 100, [0]);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.roundrect.end.1
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 100;
|
|
ctx.roundRect(200, 100, 400, 1000, [0]);
|
|
ctx.lineTo(-2000, -1000);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.roundrect.end.2
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 450;
|
|
ctx.lineCap = 'round';
|
|
ctx.lineJoin = 'bevel';
|
|
ctx.roundRect(150, 150, 2000, 2000, [0]);
|
|
ctx.lineTo(160, 160);
|
|
ctx.stroke();
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.roundrect.end.3
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 100;
|
|
ctx.roundRect(101, 51, 2000, 2000, [500, 500, 500, 500]);
|
|
ctx.lineTo(-1, -1);
|
|
ctx.stroke();
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.roundrect.end.4
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 10;
|
|
ctx.roundRect(-1, -1, 2000, 2000, [1000, 1000, 1000, 1000]);
|
|
ctx.lineTo(-150, -150);
|
|
ctx.stroke();
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.roundrect.zero.1
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 100;
|
|
ctx.beginPath();
|
|
ctx.roundRect(0, 50, 100, 0, [0]);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.roundrect.zero.2
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 100;
|
|
ctx.beginPath();
|
|
ctx.roundRect(50, -100, 0, 250, [0]);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.roundrect.zero.3
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 100;
|
|
ctx.beginPath();
|
|
ctx.roundRect(50, 25, 0, 0, [0]);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.roundrect.zero.4
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 50;
|
|
ctx.roundRect(100, 25, 0, 0, [0]);
|
|
ctx.lineTo(0, 25);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.roundrect.zero.5
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 50;
|
|
ctx.moveTo(0, 0);
|
|
ctx.roundRect(100, 25, 0, 0, [0]);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.roundrect.zero.6
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineJoin = 'miter';
|
|
ctx.miterLimit = 1.5;
|
|
ctx.lineWidth = 200;
|
|
ctx.beginPath();
|
|
ctx.roundRect(100, 25, 1000, 0, [0]);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.roundrect.negative
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.beginPath();
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.roundRect(0, 0, 50, 25, [10, 0, 0, 0]);
|
|
ctx.roundRect(100, 0, -50, 25, [10, 0, 0, 0]);
|
|
ctx.roundRect(0, 50, 50, -25, [10, 0, 0, 0]);
|
|
ctx.roundRect(100, 50, -50, -25, [10, 0, 0, 0]);
|
|
ctx.fill();
|
|
// All rects drawn
|
|
@assert pixel 25,12 == 0,255,0,255;
|
|
@assert pixel 75,12 == 0,255,0,255;
|
|
@assert pixel 25,37 == 0,255,0,255;
|
|
@assert pixel 75,37 == 0,255,0,255;
|
|
// Correct corners are rounded.
|
|
@assert pixel 1,1 == 255,0,0,255;
|
|
@assert pixel 98,1 == 255,0,0,255;
|
|
@assert pixel 1,48 == 255,0,0,255;
|
|
@assert pixel 98,48 == 255,0,0,255;
|
|
|
|
- name: 2d.path.roundrect.winding
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.beginPath();
|
|
ctx.fillStyle = '#f00';
|
|
ctx.roundRect(0, 0, 50, 50, [0]);
|
|
ctx.roundRect(100, 50, -50, -50, [0]);
|
|
ctx.roundRect(0, 25, 100, -25, [0]);
|
|
ctx.roundRect(100, 25, -100, 25, [0]);
|
|
ctx.fill();
|
|
@assert pixel 25,12 == 0,255,0,255;
|
|
@assert pixel 75,12 == 0,255,0,255;
|
|
@assert pixel 25,37 == 0,255,0,255;
|
|
@assert pixel 75,37 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.selfintersect
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.roundRect(0, 0, 100, 50, [0]);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 90;
|
|
ctx.beginPath();
|
|
ctx.roundRect(45, 20, 10, 10, [0]);
|
|
ctx.stroke();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.roundrect.nonfinite
|
|
desc: roundRect() with Infinity/NaN is ignored
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50)
|
|
ctx.moveTo(0, 0);
|
|
ctx.lineTo(100, 0);
|
|
@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]>);
|
|
ctx.roundRect(0, 0, 100, 100, [new DOMPoint(10, Infinity)]);
|
|
ctx.roundRect(0, 0, 100, 100, [new DOMPoint(10, -Infinity)]);
|
|
ctx.roundRect(0, 0, 100, 100, [new DOMPoint(10, NaN)]);
|
|
ctx.roundRect(0, 0, 100, 100, [new DOMPoint(Infinity, 10)]);
|
|
ctx.roundRect(0, 0, 100, 100, [new DOMPoint(-Infinity, 10)]);
|
|
ctx.roundRect(0, 0, 100, 100, [new DOMPoint(NaN, 10)]);
|
|
ctx.roundRect(0, 0, 100, 100, [{x: 10, y: Infinity}]);
|
|
ctx.roundRect(0, 0, 100, 100, [{x: 10, y: -Infinity}]);
|
|
ctx.roundRect(0, 0, 100, 100, [{x: 10, y: NaN}]);
|
|
ctx.roundRect(0, 0, 100, 100, [{x: Infinity, y: 10}]);
|
|
ctx.roundRect(0, 0, 100, 100, [{x: -Infinity, y: 10}]);
|
|
ctx.roundRect(0, 0, 100, 100, [{x: NaN, y: 10}]);
|
|
ctx.lineTo(100, 50);
|
|
ctx.lineTo(0, 50);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 90,45 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.roundrect.4.radii.1.double
|
|
desc: Verify that when four radii are given to roundRect(), the first radius, specified as a double, applies to the top-left corner.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [20, 0, 0, 0]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 1,1 == 255,0,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.4.radii.1.dompoint
|
|
desc: Verify that when four radii are given to roundRect(), the first radius, specified as a DOMPoint, applies to the top-left corner.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [new DOMPoint(40, 20), 0, 0, 0]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// top-left corner
|
|
@assert pixel 20,1 == 255,0,0,255;
|
|
@assert pixel 41,1 == 0,255,0,255;
|
|
@assert pixel 1,10 == 255,0,0,255;
|
|
@assert pixel 1,21 == 0,255,0,255;
|
|
|
|
// other corners
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.4.radii.1.dompointinit
|
|
desc: Verify that when four radii are given to roundRect(), the first radius, specified as a DOMPointInit, applies to the top-left corner.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [{x: 40, y: 20}, 0, 0, 0]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// top-left corner
|
|
@assert pixel 20,1 == 255,0,0,255;
|
|
@assert pixel 41,1 == 0,255,0,255;
|
|
@assert pixel 1,10 == 255,0,0,255;
|
|
@assert pixel 1,21 == 0,255,0,255;
|
|
|
|
// other corners
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.4.radii.2.double
|
|
desc: Verify that when four radii are given to roundRect(), the second radius, specified as a double, applies to the top-right corner.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [0, 20, 0, 0]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 255,0,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.4.radii.2.dompoint
|
|
desc: Verify that when four radii are given to roundRect(), the second radius, specified as a DOMPoint, applies to the top-right corner.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [0, new DOMPoint(40, 20), 0, 0]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// top-right corner
|
|
@assert pixel 79,1 == 255,0,0,255;
|
|
@assert pixel 58,1 == 0,255,0,255;
|
|
@assert pixel 98,10 == 255,0,0,255;
|
|
@assert pixel 98,21 == 0,255,0,255;
|
|
|
|
// other corners
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.4.radii.2.dompointinit
|
|
desc: Verify that when four radii are given to roundRect(), the second radius, specified as a DOMPointInit, applies to the top-right corner.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [0, {x: 40, y: 20}, 0, 0]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// top-right corner
|
|
@assert pixel 79,1 == 255,0,0,255;
|
|
@assert pixel 58,1 == 0,255,0,255;
|
|
@assert pixel 98,10 == 255,0,0,255;
|
|
@assert pixel 98,21 == 0,255,0,255;
|
|
|
|
// other corners
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.4.radii.3.double
|
|
desc: Verify that when four radii are given to roundRect(), the third radius, specified as a double, applies to the bottom-right corner.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [0, 0, 20, 0]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 255,0,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.4.radii.3.dompoint
|
|
desc: Verify that when four radii are given to roundRect(), the third radius, specified as a DOMPoint, applies to the bottom-right corner.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [0, 0, new DOMPoint(40, 20), 0]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// bottom-right corner
|
|
@assert pixel 79,48 == 255,0,0,255;
|
|
@assert pixel 58,48 == 0,255,0,255;
|
|
@assert pixel 98,39 == 255,0,0,255;
|
|
@assert pixel 98,28 == 0,255,0,255;
|
|
|
|
// other corners
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.4.radii.3.dompointinit
|
|
desc: Verify that when four radii are given to roundRect(), the third radius, specified as a DOMPointInit, applies to the bottom-right corner.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [0, 0, {x: 40, y: 20}, 0]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// bottom-right corner
|
|
@assert pixel 79,48 == 255,0,0,255;
|
|
@assert pixel 58,48 == 0,255,0,255;
|
|
@assert pixel 98,39 == 255,0,0,255;
|
|
@assert pixel 98,28 == 0,255,0,255;
|
|
|
|
// other corners
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.4.radii.4.double
|
|
desc: Verify that when four radii are given to roundRect(), the fourth radius, specified as a double, applies to the bottom-left corner.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [0, 0, 0, 20]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
@assert pixel 1,48 == 255,0,0,255;
|
|
|
|
- name: 2d.path.roundrect.4.radii.4.dompoint
|
|
desc: Verify that when four radii are given to roundRect(), the fourth radius, specified as a DOMPoint, applies to the bottom-left corner.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [0, 0, 0, new DOMPoint(40, 20)]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// bottom-left corner
|
|
@assert pixel 20,48 == 255,0,0,255;
|
|
@assert pixel 41,48 == 0,255,0,255;
|
|
@assert pixel 1,39 == 255,0,0,255;
|
|
@assert pixel 1,28 == 0,255,0,255;
|
|
|
|
// other corners
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.4.radii.4.dompointinit
|
|
desc: Verify that when four radii are given to roundRect(), the fourth radius, specified as a DOMPointInit, applies to the bottom-left corner.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [0, 0, 0, {x: 40, y: 20}]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// bottom-left corner
|
|
@assert pixel 20,48 == 255,0,0,255;
|
|
@assert pixel 41,48 == 0,255,0,255;
|
|
@assert pixel 1,39 == 255,0,0,255;
|
|
@assert pixel 1,28 == 0,255,0,255;
|
|
|
|
// other corners
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.3.radii.1.double
|
|
desc: Verify that when three radii are given to roundRect(), the first radius, specified as a double, applies to the top-left corner.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [20, 0, 0]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 1,1 == 255,0,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.3.radii.1.dompoint
|
|
desc: Verify that when three radii are given to roundRect(), the first radius, specified as a DOMPoint, applies to the top-left corner.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [new DOMPoint(40, 20), 0, 0]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// top-left corner
|
|
@assert pixel 20,1 == 255,0,0,255;
|
|
@assert pixel 41,1 == 0,255,0,255;
|
|
@assert pixel 1,10 == 255,0,0,255;
|
|
@assert pixel 1,21 == 0,255,0,255;
|
|
|
|
// other corners
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.3.radii.1.dompointinit
|
|
desc: Verify that when three radii are given to roundRect(), the first radius, specified as a DOMPointInit, applies to the top-left corner.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [{x: 40, y: 20}, 0, 0]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// top-left corner
|
|
@assert pixel 20,1 == 255,0,0,255;
|
|
@assert pixel 41,1 == 0,255,0,255;
|
|
@assert pixel 1,10 == 255,0,0,255;
|
|
@assert pixel 1,21 == 0,255,0,255;
|
|
|
|
// other corners
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.3.radii.2.double
|
|
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.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [0, 20, 0]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 255,0,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
@assert pixel 1,48 == 255,0,0,255;
|
|
|
|
- name: 2d.path.roundrect.3.radii.2.dompoint
|
|
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.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [0, new DOMPoint(40, 20), 0]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// top-right corner
|
|
@assert pixel 79,1 == 255,0,0,255;
|
|
@assert pixel 58,1 == 0,255,0,255;
|
|
@assert pixel 98,10 == 255,0,0,255;
|
|
@assert pixel 98,21 == 0,255,0,255;
|
|
|
|
// bottom-left corner
|
|
@assert pixel 20,48 == 255,0,0,255;
|
|
@assert pixel 41,48 == 0,255,0,255;
|
|
@assert pixel 1,39 == 255,0,0,255;
|
|
@assert pixel 1,28 == 0,255,0,255;
|
|
|
|
// other corners
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.3.radii.2.dompointinit
|
|
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.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [0, {x: 40, y: 20}, 0]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// top-right corner
|
|
@assert pixel 79,1 == 255,0,0,255;
|
|
@assert pixel 58,1 == 0,255,0,255;
|
|
@assert pixel 98,10 == 255,0,0,255;
|
|
@assert pixel 98,21 == 0,255,0,255;
|
|
|
|
// bottom-left corner
|
|
@assert pixel 20,48 == 255,0,0,255;
|
|
@assert pixel 41,48 == 0,255,0,255;
|
|
@assert pixel 1,39 == 255,0,0,255;
|
|
@assert pixel 1,28 == 0,255,0,255;
|
|
|
|
// other corners
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.3.radii.3.double
|
|
desc: Verify that when three radii are given to roundRect(), the third radius, specified as a double, applies to the bottom-right corner.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [0, 0, 20]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 255,0,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.3.radii.3.dompoint
|
|
desc: Verify that when three radii are given to roundRect(), the third radius, specified as a DOMPoint, applies to the bottom-right corner.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [0, 0, new DOMPoint(40, 20)]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// bottom-right corner
|
|
@assert pixel 79,48 == 255,0,0,255;
|
|
@assert pixel 58,48 == 0,255,0,255;
|
|
@assert pixel 98,39 == 255,0,0,255;
|
|
@assert pixel 98,28 == 0,255,0,255;
|
|
|
|
// other corners
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.3.radii.3.dompointinit
|
|
desc: Verify that when three radii are given to roundRect(), the third radius, specified as a DOMPointInit, applies to the bottom-right corner.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [0, 0, {x: 40, y: 20}]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// bottom-right corner
|
|
@assert pixel 79,48 == 255,0,0,255;
|
|
@assert pixel 58,48 == 0,255,0,255;
|
|
@assert pixel 98,39 == 255,0,0,255;
|
|
@assert pixel 98,28 == 0,255,0,255;
|
|
|
|
// other corners
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.2.radii.1.double
|
|
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.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [20, 0]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 1,1 == 255,0,0,255;
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 255,0,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.2.radii.1.dompoint
|
|
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.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [new DOMPoint(40, 20), 0]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// top-left corner
|
|
@assert pixel 20,1 == 255,0,0,255;
|
|
@assert pixel 41,1 == 0,255,0,255;
|
|
@assert pixel 1,10 == 255,0,0,255;
|
|
@assert pixel 1,21 == 0,255,0,255;
|
|
|
|
// bottom-right corner
|
|
@assert pixel 79,48 == 255,0,0,255;
|
|
@assert pixel 58,48 == 0,255,0,255;
|
|
@assert pixel 98,39 == 255,0,0,255;
|
|
@assert pixel 98,28 == 0,255,0,255;
|
|
|
|
// other corners
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.2.radii.1.dompointinit
|
|
desc: Verify that when two radii are given to roundRect(), the first radius, specified as a DOMPointInit, applies to the top-left and bottom-right corners.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [{x: 40, y: 20}, 0]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// top-left corner
|
|
@assert pixel 20,1 == 255,0,0,255;
|
|
@assert pixel 41,1 == 0,255,0,255;
|
|
@assert pixel 1,10 == 255,0,0,255;
|
|
@assert pixel 1,21 == 0,255,0,255;
|
|
|
|
// bottom-right corner
|
|
@assert pixel 79,48 == 255,0,0,255;
|
|
@assert pixel 58,48 == 0,255,0,255;
|
|
@assert pixel 98,39 == 255,0,0,255;
|
|
@assert pixel 98,28 == 0,255,0,255;
|
|
|
|
// other corners
|
|
@assert pixel 98,1 == 0,255,0,255;
|
|
@assert pixel 1,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.2.radii.2.double
|
|
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.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [0, 20]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,1 == 255,0,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
@assert pixel 1,48 == 255,0,0,255;
|
|
|
|
- name: 2d.path.roundrect.2.radii.2.dompoint
|
|
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.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [0, new DOMPoint(40, 20)]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// top-right corner
|
|
@assert pixel 79,1 == 255,0,0,255;
|
|
@assert pixel 58,1 == 0,255,0,255;
|
|
@assert pixel 98,10 == 255,0,0,255;
|
|
@assert pixel 98,21 == 0,255,0,255;
|
|
|
|
// bottom-left corner
|
|
@assert pixel 20,48 == 255,0,0,255;
|
|
@assert pixel 41,48 == 0,255,0,255;
|
|
@assert pixel 1,39 == 255,0,0,255;
|
|
@assert pixel 1,28 == 0,255,0,255;
|
|
|
|
// other corners
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.2.radii.2.dompointinit
|
|
desc: Verify that when two radii are given to roundRect(), the second radius, specified as a DOMPointInit, applies to the top-right and bottom-left corners.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [0, {x: 40, y: 20}]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// top-right corner
|
|
@assert pixel 79,1 == 255,0,0,255;
|
|
@assert pixel 58,1 == 0,255,0,255;
|
|
@assert pixel 98,10 == 255,0,0,255;
|
|
@assert pixel 98,21 == 0,255,0,255;
|
|
|
|
// bottom-left corner
|
|
@assert pixel 20,48 == 255,0,0,255;
|
|
@assert pixel 41,48 == 0,255,0,255;
|
|
@assert pixel 1,39 == 255,0,0,255;
|
|
@assert pixel 1,28 == 0,255,0,255;
|
|
|
|
// other corners
|
|
@assert pixel 1,1 == 0,255,0,255;
|
|
@assert pixel 98,48 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.1.radius.double
|
|
desc: Verify that when one radius is given to roundRect(), specified as a double, it applies to all corners.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [20]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 1,1 == 255,0,0,255;
|
|
@assert pixel 98,1 == 255,0,0,255;
|
|
@assert pixel 98,48 == 255,0,0,255;
|
|
@assert pixel 1,48 == 255,0,0,255;
|
|
|
|
- name: 2d.path.roundrect.1.radius.double.single.argument
|
|
desc: Verify that when one radius is given to roundRect() as a non-array argument, specified as a double, it applies to all corners.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, 20);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 1,1 == 255,0,0,255;
|
|
@assert pixel 98,1 == 255,0,0,255;
|
|
@assert pixel 98,48 == 255,0,0,255;
|
|
@assert pixel 1,48 == 255,0,0,255;
|
|
|
|
- name: 2d.path.roundrect.1.radius.dompoint
|
|
desc: Verify that when one radius is given to roundRect(), specified as a DOMPoint, it applies to all corners.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [new DOMPoint(40, 20)]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// top-left corner
|
|
@assert pixel 20,1 == 255,0,0,255;
|
|
@assert pixel 41,1 == 0,255,0,255;
|
|
@assert pixel 1,10 == 255,0,0,255;
|
|
@assert pixel 1,21 == 0,255,0,255;
|
|
|
|
// top-right corner
|
|
@assert pixel 79,1 == 255,0,0,255;
|
|
@assert pixel 58,1 == 0,255,0,255;
|
|
@assert pixel 98,10 == 255,0,0,255;
|
|
@assert pixel 98,21 == 0,255,0,255;
|
|
|
|
// bottom-right corner
|
|
@assert pixel 79,48 == 255,0,0,255;
|
|
@assert pixel 58,48 == 0,255,0,255;
|
|
@assert pixel 98,39 == 255,0,0,255;
|
|
@assert pixel 98,28 == 0,255,0,255;
|
|
|
|
// bottom-left corner
|
|
@assert pixel 20,48 == 255,0,0,255;
|
|
@assert pixel 41,48 == 0,255,0,255;
|
|
@assert pixel 1,39 == 255,0,0,255;
|
|
@assert pixel 1,28 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.1.radius.dompoint.single.argument
|
|
desc: Verify that when one radius is given to roundRect() as a non-array argument, specified as a DOMPoint, it applies to all corners.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, new DOMPoint(40, 20));
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// top-left corner
|
|
@assert pixel 20,1 == 255,0,0,255;
|
|
@assert pixel 41,1 == 0,255,0,255;
|
|
@assert pixel 1,10 == 255,0,0,255;
|
|
@assert pixel 1,21 == 0,255,0,255;
|
|
|
|
// top-right corner
|
|
@assert pixel 79,1 == 255,0,0,255;
|
|
@assert pixel 58,1 == 0,255,0,255;
|
|
@assert pixel 98,10 == 255,0,0,255;
|
|
@assert pixel 98,21 == 0,255,0,255;
|
|
|
|
// bottom-right corner
|
|
@assert pixel 79,48 == 255,0,0,255;
|
|
@assert pixel 58,48 == 0,255,0,255;
|
|
@assert pixel 98,39 == 255,0,0,255;
|
|
@assert pixel 98,28 == 0,255,0,255;
|
|
|
|
// bottom-left corner
|
|
@assert pixel 20,48 == 255,0,0,255;
|
|
@assert pixel 41,48 == 0,255,0,255;
|
|
@assert pixel 1,39 == 255,0,0,255;
|
|
@assert pixel 1,28 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.1.radius.dompointinit
|
|
desc: Verify that when one radius is given to roundRect(), specified as a DOMPointInit, applies to all corners.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [{x: 40, y: 20}]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// top-left corner
|
|
@assert pixel 20,1 == 255,0,0,255;
|
|
@assert pixel 41,1 == 0,255,0,255;
|
|
@assert pixel 1,10 == 255,0,0,255;
|
|
@assert pixel 1,21 == 0,255,0,255;
|
|
|
|
// top-right corner
|
|
@assert pixel 79,1 == 255,0,0,255;
|
|
@assert pixel 58,1 == 0,255,0,255;
|
|
@assert pixel 98,10 == 255,0,0,255;
|
|
@assert pixel 98,21 == 0,255,0,255;
|
|
|
|
// bottom-right corner
|
|
@assert pixel 79,48 == 255,0,0,255;
|
|
@assert pixel 58,48 == 0,255,0,255;
|
|
@assert pixel 98,39 == 255,0,0,255;
|
|
@assert pixel 98,28 == 0,255,0,255;
|
|
|
|
// bottom-left corner
|
|
@assert pixel 20,48 == 255,0,0,255;
|
|
@assert pixel 41,48 == 0,255,0,255;
|
|
@assert pixel 1,39 == 255,0,0,255;
|
|
@assert pixel 1,28 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.1.radius.dompointinit.single.argument
|
|
desc: Verify that when one radius is given to roundRect() as a non-array argument, specified as a DOMPointInit, applies to all corners.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, {x: 40, y: 20});
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
// top-left corner
|
|
@assert pixel 20,1 == 255,0,0,255;
|
|
@assert pixel 41,1 == 0,255,0,255;
|
|
@assert pixel 1,10 == 255,0,0,255;
|
|
@assert pixel 1,21 == 0,255,0,255;
|
|
|
|
// top-right corner
|
|
@assert pixel 79,1 == 255,0,0,255;
|
|
@assert pixel 58,1 == 0,255,0,255;
|
|
@assert pixel 98,10 == 255,0,0,255;
|
|
@assert pixel 98,21 == 0,255,0,255;
|
|
|
|
// bottom-right corner
|
|
@assert pixel 79,48 == 255,0,0,255;
|
|
@assert pixel 58,48 == 0,255,0,255;
|
|
@assert pixel 98,39 == 255,0,0,255;
|
|
@assert pixel 98,28 == 0,255,0,255;
|
|
|
|
// bottom-left corner
|
|
@assert pixel 20,48 == 255,0,0,255;
|
|
@assert pixel 41,48 == 0,255,0,255;
|
|
@assert pixel 1,39 == 255,0,0,255;
|
|
@assert pixel 1,28 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.radius.intersecting.1
|
|
desc: Check that roundRects with intersecting corner arcs are rendered correctly.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [40, 40, 40, 40]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 2,25 == 0,255,0,255;
|
|
@assert pixel 50,1 == 0,255,0,255;
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 50,48 == 0,255,0,255;
|
|
@assert pixel 97,25 == 0,255,0,255;
|
|
@assert pixel 1,1 == 255,0,0,255;
|
|
@assert pixel 98,1 == 255,0,0,255;
|
|
@assert pixel 1,48 == 255,0,0,255;
|
|
@assert pixel 98,48 == 255,0,0,255;
|
|
|
|
- name: 2d.path.roundrect.radius.intersecting.2
|
|
desc: Check that roundRects with intersecting corner arcs are rendered correctly.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(0, 0, 100, 50, [1000, 1000, 1000, 1000]);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
@assert pixel 2,25 == 0,255,0,255;
|
|
@assert pixel 50,1 == 0,255,0,255;
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 50,48 == 0,255,0,255;
|
|
@assert pixel 97,25 == 0,255,0,255;
|
|
@assert pixel 1,1 == 255,0,0,255;
|
|
@assert pixel 98,1 == 255,0,0,255;
|
|
@assert pixel 1,48 == 255,0,0,255;
|
|
@assert pixel 98,48 == 255,0,0,255;
|
|
|
|
- name: 2d.path.roundrect.radius.none
|
|
desc: Check that roundRect throws an RangeError if radii is an empty array.
|
|
code: |
|
|
assert_throws_js(RangeError, () => { ctx.roundRect(0, 0, 100, 50, [])});
|
|
|
|
- name: 2d.path.roundrect.radius.noargument
|
|
desc: Check that roundRect draws a rectangle when no radii are provided.
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.roundRect(10, 10, 80, 30);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
// upper left corner (10, 10)
|
|
@assert pixel 10,9 == 255,0,0,255;
|
|
@assert pixel 9,10 == 255,0,0,255;
|
|
@assert pixel 10,10 == 0,255,0,255;
|
|
|
|
// upper right corner (89, 10)
|
|
@assert pixel 90,10 == 255,0,0,255;
|
|
@assert pixel 89,9 == 255,0,0,255;
|
|
@assert pixel 89,10 == 0,255,0,255;
|
|
|
|
// lower right corner (89, 39)
|
|
@assert pixel 89,40 == 255,0,0,255;
|
|
@assert pixel 90,39 == 255,0,0,255;
|
|
@assert pixel 89,39 == 0,255,0,255;
|
|
|
|
// lower left corner (10, 30)
|
|
@assert pixel 9,39 == 255,0,0,255;
|
|
@assert pixel 10,40 == 255,0,0,255;
|
|
@assert pixel 10,39 == 0,255,0,255;
|
|
|
|
- name: 2d.path.roundrect.radius.toomany
|
|
desc: Check that roundRect throws an IndeSizeError if radii has more than four items.
|
|
code: |
|
|
assert_throws_js(RangeError, () => { ctx.roundRect(0, 0, 100, 50, [0, 0, 0, 0, 0])});
|
|
|
|
- name: 2d.path.roundrect.radius.negative
|
|
desc: roundRect() with negative radius throws an exception
|
|
code: |
|
|
assert_throws_js(RangeError, () => { ctx.roundRect(0, 0, 0, 0, [-1])});
|
|
assert_throws_js(RangeError, () => { ctx.roundRect(0, 0, 0, 0, [1, -1])});
|
|
assert_throws_js(RangeError, () => { ctx.roundRect(0, 0, 0, 0, [new DOMPoint(-1, 1), 1])});
|
|
assert_throws_js(RangeError, () => { ctx.roundRect(0, 0, 0, 0, [new DOMPoint(1, -1)])});
|
|
assert_throws_js(RangeError, () => { ctx.roundRect(0, 0, 0, 0, [{x: -1, y: 1}, 1])});
|
|
assert_throws_js(RangeError, () => { ctx.roundRect(0, 0, 0, 0, [{x: 1, y: -1}])});
|
|
|
|
- name: 2d.path.roundrect.badinput
|
|
desc: roundRect() throws or does not throw errors given the strange inputs.
|
|
code: |
|
|
ctx.roundRect(0, 0, 100, 100, { foo: "bar" }); //=> DOMPointInit
|
|
ctx.roundRect(0, 0, 100, 100, undefined); //=> "missing" -> 0
|
|
ctx.roundRect(0, 0, 100, 100, [[]]); //=> « DOMPointInit »
|
|
ctx.roundRect(0, 0, 100, 100, [[25]]); //=> « DOMPointInit »
|
|
ctx.roundRect(0, 0, 100, 100, [undefined]); //=> « DOMPointInit »
|
|
@assert throws TypeError ctx.roundRect(0, 0, 100, 100, 0n);
|
|
@assert throws TypeError ctx.roundRect(0, 0, 100, 100, { x: 0n });
|
|
@assert throws TypeError ctx.roundRect(0, 0, 100, 100, [{ x: 0n }]);
|
|
|
|
- name: 2d.path.ellipse.basics
|
|
desc: Verify canvas throws error when drawing ellipse with negative radii.
|
|
code: |
|
|
ctx.ellipse(10, 10, 10, 5, 0, 0, 1, false);
|
|
ctx.ellipse(10, 10, 10, 0, 0, 0, 1, false);
|
|
ctx.ellipse(10, 10, -0, 5, 0, 0, 1, false);
|
|
@assert throws INDEX_SIZE_ERR ctx.ellipse(10, 10, -2, 5, 0, 0, 1, false);
|
|
@assert throws INDEX_SIZE_ERR ctx.ellipse(10, 10, 0, -1.5, 0, 0, 1, false);
|
|
@assert throws INDEX_SIZE_ERR ctx.ellipse(10, 10, -2, -5, 0, 0, 1, false);
|
|
ctx.ellipse(80, 0, 10, 4294967277, Math.PI / -84, -Math.PI / 2147483436, false);
|
|
|
|
- name: 2d.path.fill.overlap
|
|
code: |
|
|
ctx.fillStyle = '#000';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
|
|
ctx.rect(0, 0, 100, 50);
|
|
ctx.closePath();
|
|
ctx.rect(10, 10, 80, 30);
|
|
ctx.fill();
|
|
|
|
@assert pixel 50,25 ==~ 0,127,0,255 +/- 1;
|
|
expected: |
|
|
size 100 50
|
|
cr.set_source_rgb(0, 0.5, 0)
|
|
cr.rectangle(0, 0, 100, 50)
|
|
cr.fill()
|
|
|
|
- name: 2d.path.fill.winding.evenodd.1
|
|
desc: evenodd winding number rule works in fill
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.beginPath();
|
|
ctx.rect(0, 0, 100, 50);
|
|
ctx.rect(0, 0, 100, 50);
|
|
|
|
ctx.fillStyle = "#f00";
|
|
ctx.fill("evenodd");
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
|
|
- name: 2d.path.fill.winding.evenodd.2
|
|
desc: evenodd winding number rule works in fill
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
let path = new Path2D();
|
|
path.rect(0, 0, 100, 50);
|
|
path.rect(0, 0, 100, 50);
|
|
path.closePath();
|
|
|
|
ctx.fillStyle = "#f00";
|
|
ctx.fill(path, "evenodd");
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
|
|
- name: 2d.path.fill.winding.add
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.moveTo(-10, -10);
|
|
ctx.lineTo(110, -10);
|
|
ctx.lineTo(110, 60);
|
|
ctx.lineTo(-10, 60);
|
|
ctx.lineTo(-10, -10);
|
|
ctx.lineTo(0, 0);
|
|
ctx.lineTo(100, 0);
|
|
ctx.lineTo(100, 50);
|
|
ctx.lineTo(0, 50);
|
|
ctx.fill();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.fill.winding.subtract.1
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.fillStyle = '#f00';
|
|
ctx.moveTo(-10, -10);
|
|
ctx.lineTo(110, -10);
|
|
ctx.lineTo(110, 60);
|
|
ctx.lineTo(-10, 60);
|
|
ctx.lineTo(-10, -10);
|
|
ctx.lineTo(0, 0);
|
|
ctx.lineTo(0, 50);
|
|
ctx.lineTo(100, 50);
|
|
ctx.lineTo(100, 0);
|
|
ctx.fill();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.fill.winding.subtract.2
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.fillStyle = '#f00';
|
|
ctx.moveTo(-10, -10);
|
|
ctx.lineTo(110, -10);
|
|
ctx.lineTo(110, 60);
|
|
ctx.lineTo(-10, 60);
|
|
ctx.moveTo(0, 0);
|
|
ctx.lineTo(0, 50);
|
|
ctx.lineTo(100, 50);
|
|
ctx.lineTo(100, 0);
|
|
ctx.fill();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.fill.winding.subtract.3
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.moveTo(-10, -10);
|
|
ctx.lineTo(110, -10);
|
|
ctx.lineTo(110, 60);
|
|
ctx.lineTo(-10, 60);
|
|
ctx.lineTo(-10, -10);
|
|
ctx.lineTo(-20, -20);
|
|
ctx.lineTo(120, -20);
|
|
ctx.lineTo(120, 70);
|
|
ctx.lineTo(-20, 70);
|
|
ctx.lineTo(-20, -20);
|
|
ctx.lineTo(0, 0);
|
|
ctx.lineTo(0, 50);
|
|
ctx.lineTo(100, 50);
|
|
ctx.lineTo(100, 0);
|
|
ctx.fill();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.fill.closed.basic
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.moveTo(0, 0);
|
|
ctx.lineTo(100, 0);
|
|
ctx.lineTo(100, 50);
|
|
ctx.lineTo(0, 50);
|
|
ctx.fill();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.fill.closed.unaffected
|
|
code: |
|
|
ctx.fillStyle = '#00f';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.moveTo(0, 0);
|
|
ctx.lineTo(100, 0);
|
|
ctx.lineTo(100, 50);
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fill();
|
|
ctx.lineTo(0, 50);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
@assert pixel 90,10 == 0,255,0,255;
|
|
@assert pixel 10,40 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.stroke.overlap
|
|
desc: Stroked subpaths are combined before being drawn
|
|
code: |
|
|
ctx.fillStyle = '#000';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.strokeStyle = 'rgba(0, 255, 0, 0.5)';
|
|
ctx.lineWidth = 50;
|
|
ctx.moveTo(0, 20);
|
|
ctx.lineTo(100, 20);
|
|
ctx.moveTo(0, 30);
|
|
ctx.lineTo(100, 30);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 50,25 ==~ 0,127,0,255 +/- 1;
|
|
expected: |
|
|
size 100 50
|
|
cr.set_source_rgb(0, 0.5, 0)
|
|
cr.rectangle(0, 0, 100, 50)
|
|
cr.fill()
|
|
|
|
- name: 2d.path.stroke.union
|
|
desc: Strokes in opposite directions are unioned, not subtracted
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.lineWidth = 40;
|
|
ctx.moveTo(0, 10);
|
|
ctx.lineTo(100, 10);
|
|
ctx.moveTo(100, 40);
|
|
ctx.lineTo(0, 40);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.stroke.unaffected
|
|
desc: Stroking does not start a new path or subpath
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.lineWidth = 50;
|
|
ctx.moveTo(-100, 25);
|
|
ctx.lineTo(-100, -100);
|
|
ctx.lineTo(200, -100);
|
|
ctx.lineTo(200, 25);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.stroke();
|
|
|
|
ctx.closePath();
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.stroke();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.stroke.scale1
|
|
desc: Stroke line widths are scaled by the current transformation matrix
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.beginPath();
|
|
ctx.rect(25, 12.5, 50, 25);
|
|
ctx.save();
|
|
ctx.scale(50, 25);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.stroke();
|
|
ctx.restore();
|
|
|
|
ctx.beginPath();
|
|
ctx.rect(-25, -12.5, 150, 75);
|
|
ctx.save();
|
|
ctx.scale(50, 25);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.stroke();
|
|
ctx.restore();
|
|
|
|
@assert pixel 0,0 == 0,255,0,255;
|
|
@assert pixel 50,0 == 0,255,0,255;
|
|
@assert pixel 99,0 == 0,255,0,255;
|
|
@assert pixel 0,25 == 0,255,0,255;
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 99,25 == 0,255,0,255;
|
|
@assert pixel 0,49 == 0,255,0,255;
|
|
@assert pixel 50,49 == 0,255,0,255;
|
|
@assert pixel 99,49 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.stroke.scale2
|
|
desc: Stroke line widths are scaled by the current transformation matrix
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.beginPath();
|
|
ctx.rect(25, 12.5, 50, 25);
|
|
ctx.save();
|
|
ctx.rotate(Math.PI/2);
|
|
ctx.scale(25, 50);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.stroke();
|
|
ctx.restore();
|
|
|
|
ctx.beginPath();
|
|
ctx.rect(-25, -12.5, 150, 75);
|
|
ctx.save();
|
|
ctx.rotate(Math.PI/2);
|
|
ctx.scale(25, 50);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.stroke();
|
|
ctx.restore();
|
|
|
|
@assert pixel 0,0 == 0,255,0,255;
|
|
@assert pixel 50,0 == 0,255,0,255;
|
|
@assert pixel 99,0 == 0,255,0,255;
|
|
@assert pixel 0,25 == 0,255,0,255;
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 99,25 == 0,255,0,255;
|
|
@assert pixel 0,49 == 0,255,0,255;
|
|
@assert pixel 50,49 == 0,255,0,255;
|
|
@assert pixel 99,49 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.stroke.skew
|
|
desc: Strokes lines are skewed by the current transformation matrix
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.save();
|
|
ctx.beginPath();
|
|
ctx.moveTo(49, -50);
|
|
ctx.lineTo(201, -50);
|
|
ctx.rotate(Math.PI/4);
|
|
ctx.scale(1, 283);
|
|
ctx.strokeStyle = '#0f0';
|
|
ctx.stroke();
|
|
ctx.restore();
|
|
|
|
ctx.save();
|
|
ctx.beginPath();
|
|
ctx.translate(-150, 0);
|
|
ctx.moveTo(49, -50);
|
|
ctx.lineTo(199, -50);
|
|
ctx.rotate(Math.PI/4);
|
|
ctx.scale(1, 142);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.stroke();
|
|
ctx.restore();
|
|
|
|
ctx.save();
|
|
ctx.beginPath();
|
|
ctx.translate(-150, 0);
|
|
ctx.moveTo(49, -50);
|
|
ctx.lineTo(199, -50);
|
|
ctx.rotate(Math.PI/4);
|
|
ctx.scale(1, 142);
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.stroke();
|
|
ctx.restore();
|
|
|
|
@assert pixel 0,0 == 0,255,0,255;
|
|
@assert pixel 50,0 == 0,255,0,255;
|
|
@assert pixel 99,0 == 0,255,0,255;
|
|
@assert pixel 0,25 == 0,255,0,255;
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
@assert pixel 99,25 == 0,255,0,255;
|
|
@assert pixel 0,49 == 0,255,0,255;
|
|
@assert pixel 50,49 == 0,255,0,255;
|
|
@assert pixel 99,49 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.stroke.empty
|
|
desc: Empty subpaths are not stroked
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 100;
|
|
ctx.lineCap = 'round';
|
|
ctx.lineJoin = 'round';
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(40, 25);
|
|
ctx.moveTo(60, 25);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.stroke.prune.line
|
|
desc: Zero-length line segments from lineTo are removed before stroking
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 100;
|
|
ctx.lineCap = 'round';
|
|
ctx.lineJoin = 'round';
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(50, 25);
|
|
ctx.lineTo(50, 25);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255; @moz-todo
|
|
expected: green
|
|
|
|
- name: 2d.path.stroke.prune.closed
|
|
desc: Zero-length line segments from closed paths are removed before stroking
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 100;
|
|
ctx.lineCap = 'round';
|
|
ctx.lineJoin = 'round';
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(50, 25);
|
|
ctx.lineTo(50, 25);
|
|
ctx.closePath();
|
|
ctx.stroke();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255; @moz-todo
|
|
expected: green
|
|
|
|
- name: 2d.path.stroke.prune.curve
|
|
desc: Zero-length line segments from quadraticCurveTo and bezierCurveTo are removed
|
|
before stroking
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 100;
|
|
ctx.lineCap = 'round';
|
|
ctx.lineJoin = 'round';
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(50, 25);
|
|
ctx.quadraticCurveTo(50, 25, 50, 25);
|
|
ctx.stroke();
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(50, 25);
|
|
ctx.bezierCurveTo(50, 25, 50, 25, 50, 25);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255; @moz-todo
|
|
expected: green
|
|
|
|
- name: 2d.path.stroke.prune.arc
|
|
desc: Zero-length line segments from arcTo and arc are removed before stroking
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 100;
|
|
ctx.lineCap = 'round';
|
|
ctx.lineJoin = 'round';
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(50, 25);
|
|
ctx.arcTo(50, 25, 150, 25, 10);
|
|
ctx.stroke();
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(60, 25);
|
|
ctx.arc(50, 25, 10, 0, 0, false);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255; @moz-todo
|
|
expected: green
|
|
|
|
- name: 2d.path.stroke.prune.rect
|
|
desc: Zero-length line segments from rect and strokeRect are removed before stroking
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 100;
|
|
ctx.lineCap = 'round';
|
|
ctx.lineJoin = 'round';
|
|
|
|
ctx.beginPath();
|
|
ctx.rect(50, 25, 0, 0);
|
|
ctx.stroke();
|
|
|
|
ctx.strokeRect(50, 25, 0, 0);
|
|
|
|
@assert pixel 50,25 == 0,255,0,255; @moz-todo
|
|
expected: green
|
|
|
|
- name: 2d.path.stroke.prune.corner
|
|
desc: Zero-length line segments are removed before stroking with miters
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 400;
|
|
ctx.lineJoin = 'miter';
|
|
ctx.miterLimit = 1.4;
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(-1000, 200);
|
|
ctx.lineTo(-100, 200);
|
|
ctx.lineTo(-100, 200);
|
|
ctx.lineTo(-100, 200);
|
|
ctx.lineTo(-100, 1000);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.transformation.basic
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.translate(-100, 0);
|
|
ctx.rect(100, 0, 100, 50);
|
|
ctx.translate(0, -100);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fill();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.transformation.multiple
|
|
# TODO: change this name
|
|
desc: Transformations are applied while building paths, not when drawing
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.fillStyle = '#f00';
|
|
ctx.translate(-100, 0);
|
|
ctx.rect(0, 0, 100, 50);
|
|
ctx.fill();
|
|
ctx.translate(100, 0);
|
|
ctx.fill();
|
|
|
|
ctx.beginPath();
|
|
ctx.strokeStyle = '#f00';
|
|
ctx.lineWidth = 50;
|
|
ctx.translate(0, -50);
|
|
ctx.moveTo(0, 25);
|
|
ctx.lineTo(100, 25);
|
|
ctx.stroke();
|
|
ctx.translate(0, 50);
|
|
ctx.stroke();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.transformation.changing
|
|
desc: Transformations are applied while building paths, not when drawing
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.moveTo(0, 0);
|
|
ctx.translate(100, 0);
|
|
ctx.lineTo(0, 0);
|
|
ctx.translate(0, 50);
|
|
ctx.lineTo(0, 0);
|
|
ctx.translate(-100, 0);
|
|
ctx.lineTo(0, 0);
|
|
ctx.translate(1000, 1000);
|
|
ctx.rotate(Math.PI/2);
|
|
ctx.scale(0.1, 0.1);
|
|
ctx.fill();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
|
|
- name: 2d.path.clip.empty
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.beginPath();
|
|
ctx.clip();
|
|
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.clip.basic.1
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.beginPath();
|
|
ctx.rect(0, 0, 100, 50);
|
|
ctx.clip();
|
|
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.clip.basic.2
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.beginPath();
|
|
ctx.rect(-100, 0, 100, 50);
|
|
ctx.clip();
|
|
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.clip.intersect
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.beginPath();
|
|
ctx.rect(0, 0, 50, 50);
|
|
ctx.clip();
|
|
ctx.beginPath();
|
|
ctx.rect(50, 0, 50, 50)
|
|
ctx.clip();
|
|
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.clip.winding.evenodd.1
|
|
desc: evenodd winding number rule works in clip
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.beginPath();
|
|
ctx.rect(0, 0, 100, 50);
|
|
ctx.rect(0, 0, 100, 50);
|
|
|
|
ctx.fillStyle = "#f00";
|
|
ctx.clip("evenodd");
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
|
|
- name: 2d.path.clip.winding.evenodd.2
|
|
desc: evenodd winding number rule works in clip
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
let path = new Path2D();
|
|
path.rect(0, 0, 100, 50);
|
|
path.rect(0, 0, 100, 50);
|
|
path.closePath();
|
|
|
|
ctx.fillStyle = "#f00";
|
|
ctx.clip(path, "evenodd");
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
|
|
- name: 2d.path.clip.winding.1
|
|
code: |
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(-10, -10);
|
|
ctx.lineTo(110, -10);
|
|
ctx.lineTo(110, 60);
|
|
ctx.lineTo(-10, 60);
|
|
ctx.lineTo(-10, -10);
|
|
ctx.lineTo(0, 0);
|
|
ctx.lineTo(0, 50);
|
|
ctx.lineTo(100, 50);
|
|
ctx.lineTo(100, 0);
|
|
ctx.clip();
|
|
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.clip.winding.2
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(-10, -10);
|
|
ctx.lineTo(110, -10);
|
|
ctx.lineTo(110, 60);
|
|
ctx.lineTo(-10, 60);
|
|
ctx.lineTo(-10, -10);
|
|
ctx.clip();
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 0);
|
|
ctx.lineTo(0, 50);
|
|
ctx.lineTo(100, 50);
|
|
ctx.lineTo(100, 0);
|
|
ctx.lineTo(0, 0);
|
|
ctx.clip();
|
|
|
|
ctx.fillStyle = '#0f0';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
- name: 2d.path.clip.unaffected
|
|
code: |
|
|
ctx.fillStyle = '#f00';
|
|
ctx.fillRect(0, 0, 100, 50);
|
|
|
|
ctx.fillStyle = '#0f0';
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, 0);
|
|
ctx.lineTo(0, 50);
|
|
ctx.lineTo(100, 50);
|
|
ctx.lineTo(100, 0);
|
|
ctx.clip();
|
|
|
|
ctx.lineTo(0, 0);
|
|
ctx.fill();
|
|
|
|
@assert pixel 50,25 == 0,255,0,255;
|
|
expected: green
|
|
|
|
|
|
|
|
- name: 2d.path.isPointInPath.basic.1
|
|
desc: isPointInPath() detects whether the point is inside the path
|
|
code: |
|
|
ctx.rect(0, 0, 20, 20);
|
|
@assert ctx.isPointInPath(10, 10) === true;
|
|
@assert ctx.isPointInPath(30, 10) === false;
|
|
|
|
- name: 2d.path.isPointInPath.basic.2
|
|
desc: isPointInPath() detects whether the point is inside the path
|
|
code: |
|
|
ctx.rect(20, 0, 20, 20);
|
|
@assert ctx.isPointInPath(10, 10) === false;
|
|
@assert ctx.isPointInPath(30, 10) === true;
|
|
|
|
- name: 2d.path.isPointInPath.edge
|
|
desc: isPointInPath() counts points on the path as being inside
|
|
code: |
|
|
ctx.rect(0, 0, 20, 20);
|
|
@assert ctx.isPointInPath(0, 0) === true;
|
|
@assert ctx.isPointInPath(10, 0) === true;
|
|
@assert ctx.isPointInPath(20, 0) === true;
|
|
@assert ctx.isPointInPath(20, 10) === true;
|
|
@assert ctx.isPointInPath(20, 20) === true;
|
|
@assert ctx.isPointInPath(10, 20) === true;
|
|
@assert ctx.isPointInPath(0, 20) === true;
|
|
@assert ctx.isPointInPath(0, 10) === true;
|
|
@assert ctx.isPointInPath(10, -0.01) === false;
|
|
@assert ctx.isPointInPath(10, 20.01) === false;
|
|
@assert ctx.isPointInPath(-0.01, 10) === false;
|
|
@assert ctx.isPointInPath(20.01, 10) === false;
|
|
|
|
- name: 2d.path.isPointInPath.empty
|
|
desc: isPointInPath() works when there is no path
|
|
code: |
|
|
@assert ctx.isPointInPath(0, 0) === false;
|
|
|
|
- name: 2d.path.isPointInPath.subpath
|
|
desc: isPointInPath() uses the current path, not just the subpath
|
|
code: |
|
|
ctx.rect(0, 0, 20, 20);
|
|
ctx.beginPath();
|
|
ctx.rect(20, 0, 20, 20);
|
|
ctx.closePath();
|
|
ctx.rect(40, 0, 20, 20);
|
|
@assert ctx.isPointInPath(10, 10) === false;
|
|
@assert ctx.isPointInPath(30, 10) === true;
|
|
@assert ctx.isPointInPath(50, 10) === true;
|
|
|
|
- name: 2d.path.isPointInPath.outside
|
|
desc: isPointInPath() works on paths outside the canvas
|
|
code: |
|
|
ctx.rect(0, -100, 20, 20);
|
|
ctx.rect(20, -10, 20, 20);
|
|
@assert ctx.isPointInPath(10, -110) === false;
|
|
@assert ctx.isPointInPath(10, -90) === true;
|
|
@assert ctx.isPointInPath(10, -70) === false;
|
|
@assert ctx.isPointInPath(30, -20) === false;
|
|
@assert ctx.isPointInPath(30, 0) === true;
|
|
@assert ctx.isPointInPath(30, 20) === false;
|
|
|
|
- name: 2d.path.isPointInPath.unclosed
|
|
desc: isPointInPath() works on unclosed subpaths
|
|
code: |
|
|
ctx.moveTo(0, 0);
|
|
ctx.lineTo(20, 0);
|
|
ctx.lineTo(20, 20);
|
|
ctx.lineTo(0, 20);
|
|
@assert ctx.isPointInPath(10, 10) === true;
|
|
@assert ctx.isPointInPath(30, 10) === false;
|
|
|
|
- name: 2d.path.isPointInPath.arc
|
|
desc: isPointInPath() works on arcs
|
|
code: |
|
|
ctx.arc(50, 25, 10, 0, Math.PI, false);
|
|
@assert ctx.isPointInPath(50, 10) === false;
|
|
@assert ctx.isPointInPath(50, 20) === false;
|
|
@assert ctx.isPointInPath(50, 30) === true;
|
|
@assert ctx.isPointInPath(50, 40) === false;
|
|
@assert ctx.isPointInPath(30, 20) === false;
|
|
@assert ctx.isPointInPath(70, 20) === false;
|
|
@assert ctx.isPointInPath(30, 30) === false;
|
|
@assert ctx.isPointInPath(70, 30) === false;
|
|
|
|
- name: 2d.path.isPointInPath.bigarc
|
|
desc: isPointInPath() works on unclosed arcs larger than 2pi
|
|
opera: {bug: 320937}
|
|
code: |
|
|
ctx.arc(50, 25, 10, 0, 7, false);
|
|
@assert ctx.isPointInPath(50, 10) === false;
|
|
@assert ctx.isPointInPath(50, 20) === true;
|
|
@assert ctx.isPointInPath(50, 30) === true;
|
|
@assert ctx.isPointInPath(50, 40) === false;
|
|
@assert ctx.isPointInPath(30, 20) === false;
|
|
@assert ctx.isPointInPath(70, 20) === false;
|
|
@assert ctx.isPointInPath(30, 30) === false;
|
|
@assert ctx.isPointInPath(70, 30) === false;
|
|
|
|
- name: 2d.path.isPointInPath.bezier
|
|
desc: isPointInPath() works on Bezier curves
|
|
code: |
|
|
ctx.moveTo(25, 25);
|
|
ctx.bezierCurveTo(50, -50, 50, 100, 75, 25);
|
|
@assert ctx.isPointInPath(25, 20) === false;
|
|
@assert ctx.isPointInPath(25, 30) === false;
|
|
@assert ctx.isPointInPath(30, 20) === true;
|
|
@assert ctx.isPointInPath(30, 30) === false;
|
|
@assert ctx.isPointInPath(40, 2) === false;
|
|
@assert ctx.isPointInPath(40, 20) === true;
|
|
@assert ctx.isPointInPath(40, 30) === false;
|
|
@assert ctx.isPointInPath(40, 47) === false;
|
|
@assert ctx.isPointInPath(45, 20) === true;
|
|
@assert ctx.isPointInPath(45, 30) === false;
|
|
@assert ctx.isPointInPath(55, 20) === false;
|
|
@assert ctx.isPointInPath(55, 30) === true;
|
|
@assert ctx.isPointInPath(60, 2) === false;
|
|
@assert ctx.isPointInPath(60, 20) === false;
|
|
@assert ctx.isPointInPath(60, 30) === true;
|
|
@assert ctx.isPointInPath(60, 47) === false;
|
|
@assert ctx.isPointInPath(70, 20) === false;
|
|
@assert ctx.isPointInPath(70, 30) === true;
|
|
@assert ctx.isPointInPath(75, 20) === false;
|
|
@assert ctx.isPointInPath(75, 30) === false;
|
|
|
|
- name: 2d.path.isPointInPath.winding
|
|
desc: isPointInPath() uses the non-zero winding number rule
|
|
code: |
|
|
// Create a square ring, using opposite windings to make a hole in the centre
|
|
ctx.moveTo(0, 0);
|
|
ctx.lineTo(50, 0);
|
|
ctx.lineTo(50, 50);
|
|
ctx.lineTo(0, 50);
|
|
ctx.lineTo(0, 0);
|
|
ctx.lineTo(10, 10);
|
|
ctx.lineTo(10, 40);
|
|
ctx.lineTo(40, 40);
|
|
ctx.lineTo(40, 10);
|
|
ctx.lineTo(10, 10);
|
|
|
|
@assert ctx.isPointInPath(5, 5) === true;
|
|
@assert ctx.isPointInPath(25, 5) === true;
|
|
@assert ctx.isPointInPath(45, 5) === true;
|
|
@assert ctx.isPointInPath(5, 25) === true;
|
|
@assert ctx.isPointInPath(25, 25) === false;
|
|
@assert ctx.isPointInPath(45, 25) === true;
|
|
@assert ctx.isPointInPath(5, 45) === true;
|
|
@assert ctx.isPointInPath(25, 45) === true;
|
|
@assert ctx.isPointInPath(45, 45) === true;
|
|
|
|
- name: 2d.path.isPointInPath.transform.1
|
|
desc: isPointInPath() handles transformations correctly
|
|
code: |
|
|
ctx.translate(50, 0);
|
|
ctx.rect(0, 0, 20, 20);
|
|
@assert ctx.isPointInPath(-40, 10) === false;
|
|
@assert ctx.isPointInPath(10, 10) === false;
|
|
@assert ctx.isPointInPath(49, 10) === false;
|
|
@assert ctx.isPointInPath(51, 10) === true;
|
|
@assert ctx.isPointInPath(69, 10) === true;
|
|
@assert ctx.isPointInPath(71, 10) === false;
|
|
|
|
- name: 2d.path.isPointInPath.transform.2
|
|
desc: isPointInPath() handles transformations correctly
|
|
code: |
|
|
ctx.rect(50, 0, 20, 20);
|
|
ctx.translate(50, 0);
|
|
@assert ctx.isPointInPath(-40, 10) === false;
|
|
@assert ctx.isPointInPath(10, 10) === false;
|
|
@assert ctx.isPointInPath(49, 10) === false;
|
|
@assert ctx.isPointInPath(51, 10) === true;
|
|
@assert ctx.isPointInPath(69, 10) === true;
|
|
@assert ctx.isPointInPath(71, 10) === false;
|
|
|
|
- name: 2d.path.isPointInPath.transform.3
|
|
desc: isPointInPath() handles transformations correctly
|
|
code: |
|
|
ctx.scale(-1, 1);
|
|
ctx.rect(-70, 0, 20, 20);
|
|
@assert ctx.isPointInPath(-40, 10) === false;
|
|
@assert ctx.isPointInPath(10, 10) === false;
|
|
@assert ctx.isPointInPath(49, 10) === false;
|
|
@assert ctx.isPointInPath(51, 10) === true;
|
|
@assert ctx.isPointInPath(69, 10) === true;
|
|
@assert ctx.isPointInPath(71, 10) === false;
|
|
|
|
- name: 2d.path.isPointInPath.transform.4
|
|
desc: isPointInPath() handles transformations correctly
|
|
code: |
|
|
ctx.translate(50, 0);
|
|
ctx.rect(50, 0, 20, 20);
|
|
ctx.translate(0, 50);
|
|
@assert ctx.isPointInPath(60, 10) === false;
|
|
@assert ctx.isPointInPath(110, 10) === true;
|
|
@assert ctx.isPointInPath(110, 60) === false;
|
|
|
|
- name: 2d.path.isPointInPath.nonfinite
|
|
desc: isPointInPath() returns false for non-finite arguments
|
|
code: |
|
|
ctx.rect(-100, -50, 200, 100);
|
|
@assert ctx.isPointInPath(Infinity, 0) === false;
|
|
@assert ctx.isPointInPath(-Infinity, 0) === false;
|
|
@assert ctx.isPointInPath(NaN, 0) === false;
|
|
@assert ctx.isPointInPath(0, Infinity) === false;
|
|
@assert ctx.isPointInPath(0, -Infinity) === false;
|
|
@assert ctx.isPointInPath(0, NaN) === false;
|
|
@assert ctx.isPointInPath(NaN, NaN) === false;
|
|
|
|
|
|
- name: 2d.path.isPointInStroke.scaleddashes
|
|
desc: isPointInStroke() should return correct results on dashed paths at high scale
|
|
factors
|
|
code: |
|
|
var scale = 20;
|
|
ctx.setLineDash([10, 21.4159]); // dash from t=0 to t=10 along the circle
|
|
ctx.scale(scale, scale);
|
|
ctx.ellipse(6, 10, 5, 5, 0, 2*Math.PI, false);
|
|
ctx.stroke();
|
|
|
|
// hit-test the beginning of the dash (t=0)
|
|
@assert ctx.isPointInStroke(11*scale, 10*scale) === true;
|
|
// hit-test the middle of the dash (t=5)
|
|
@assert ctx.isPointInStroke(8.70*scale, 14.21*scale) === true;
|
|
// hit-test the end of the dash (t=9.8)
|
|
@assert ctx.isPointInStroke(4.10*scale, 14.63*scale) === true;
|
|
// hit-test past the end of the dash (t=10.2)
|
|
@assert ctx.isPointInStroke(3.74*scale, 14.46*scale) === false;
|
|
|
|
- name: 2d.path.isPointInPath.basic
|
|
desc: Verify the winding rule in isPointInPath works for for rect path.
|
|
code: |
|
|
canvas.width = 200;
|
|
canvas.height = 200;
|
|
|
|
// Testing default isPointInPath
|
|
ctx.beginPath();
|
|
ctx.rect(0, 0, 100, 100);
|
|
ctx.rect(25, 25, 50, 50);
|
|
@assert ctx.isPointInPath(50, 50) === true;
|
|
@assert ctx.isPointInPath(NaN, 50) === false;
|
|
@assert ctx.isPointInPath(50, NaN) === false;
|
|
|
|
// Testing nonzero isPointInPath
|
|
ctx.beginPath();
|
|
ctx.rect(0, 0, 100, 100);
|
|
ctx.rect(25, 25, 50, 50);
|
|
@assert ctx.isPointInPath(50, 50, 'nonzero') === true;
|
|
|
|
// Testing evenodd isPointInPath
|
|
ctx.beginPath();
|
|
ctx.rect(0, 0, 100, 100);
|
|
ctx.rect(25, 25, 50, 50);
|
|
@assert ctx.isPointInPath(50, 50, 'evenodd') === false;
|
|
|
|
// Testing extremely large scale
|
|
ctx.save();
|
|
ctx.scale(Number.MAX_VALUE, Number.MAX_VALUE);
|
|
ctx.beginPath();
|
|
ctx.rect(-10, -10, 20, 20);
|
|
@assert ctx.isPointInPath(0, 0, 'nonzero') === true;
|
|
@assert ctx.isPointInPath(0, 0, 'evenodd') === true;
|
|
ctx.restore();
|
|
|
|
// Check with non-invertible ctm.
|
|
ctx.save();
|
|
ctx.scale(0, 0);
|
|
ctx.beginPath();
|
|
ctx.rect(-10, -10, 20, 20);
|
|
@assert ctx.isPointInPath(0, 0, 'nonzero') === false;
|
|
@assert ctx.isPointInPath(0, 0, 'evenodd') === false;
|
|
ctx.restore();
|
|
|
|
- name: 2d.path.isPointInpath.multi.path
|
|
desc: Verify the winding rule in isPointInPath works for path object.
|
|
code: |
|
|
canvas.width = 200;
|
|
canvas.height = 200;
|
|
|
|
// Testing default isPointInPath with Path object');
|
|
path = new Path2D();
|
|
path.rect(0, 0, 100, 100);
|
|
path.rect(25, 25, 50, 50);
|
|
@assert ctx.isPointInPath(path, 50, 50) === true;
|
|
@assert ctx.isPointInPath(path, 50, 50, undefined) === true;
|
|
@assert ctx.isPointInPath(path, NaN, 50) === false;
|
|
@assert ctx.isPointInPath(path, 50, NaN) === false;
|
|
|
|
// Testing nonzero isPointInPath with Path object');
|
|
path = new Path2D();
|
|
path.rect(0, 0, 100, 100);
|
|
path.rect(25, 25, 50, 50);
|
|
@assert ctx.isPointInPath(path, 50, 50, 'nonzero') === true;
|
|
|
|
// Testing evenodd isPointInPath with Path object');
|
|
path = new Path2D();
|
|
path.rect(0, 0, 100, 100);
|
|
path.rect(25, 25, 50, 50);
|
|
assert_false(ctx.isPointInPath(path, 50, 50, 'evenodd'));
|
|
|
|
- name: 2d.path.isPointInpath.invalid
|
|
desc: Verify isPointInPath throws exceptions with invalid inputs.
|
|
code: |
|
|
canvas.width = 200;
|
|
canvas.height = 200;
|
|
path = new Path2D();
|
|
path.rect(0, 0, 100, 100);
|
|
path.rect(25, 25, 50, 50);
|
|
// Testing invalid enumeration isPointInPath (w/ and w/o Path object');
|
|
@assert throws TypeError ctx.isPointInPath(path, 50, 50, 'gazonk');
|
|
@assert throws TypeError ctx.isPointInPath(50, 50, 'gazonk');
|
|
|
|
// Testing invalid type isPointInPath with Path object');
|
|
@assert throws TypeError ctx.isPointInPath(null, 50, 50);
|
|
@assert throws TypeError ctx.isPointInPath(null, 50, 50, 'nonzero');
|
|
@assert throws TypeError ctx.isPointInPath(null, 50, 50, 'evenodd');
|
|
@assert throws TypeError ctx.isPointInPath(null, 50, 50, null);
|
|
@assert throws TypeError ctx.isPointInPath(path, 50, 50, null);
|
|
@assert throws TypeError ctx.isPointInPath(undefined, 50, 50);
|
|
@assert throws TypeError ctx.isPointInPath(undefined, 50, 50, 'nonzero');
|
|
@assert throws TypeError ctx.isPointInPath(undefined, 50, 50, 'evenodd');
|
|
@assert throws TypeError ctx.isPointInPath(undefined, 50, 50, undefined);
|
|
@assert throws TypeError ctx.isPointInPath([], 50, 50);
|
|
@assert throws TypeError ctx.isPointInPath([], 50, 50, 'nonzero');
|
|
@assert throws TypeError ctx.isPointInPath([], 50, 50, 'evenodd');
|
|
@assert throws TypeError ctx.isPointInPath({}, 50, 50);
|
|
@assert throws TypeError ctx.isPointInPath({}, 50, 50, 'nonzero');
|
|
@assert throws TypeError ctx.isPointInPath({}, 50, 50, 'evenodd');
|
|
|
|
- name: 2d.path.clip.scale
|
|
desc: clip() with non-identity transform applies the correct clip region
|
|
size: [200, 200]
|
|
code: |
|
|
ctx.scale(2, 2);
|
|
ctx.beginPath();
|
|
ctx.rect(0, 0, 100, 200);
|
|
ctx.clip();
|
|
|
|
// Earlier in Servo, a regression was introduced.
|
|
// This only had fill the left half of square, as clip rect
|
|
// stored was not transformed.
|
|
ctx.fillStyle = 'green';
|
|
ctx.fillRect(0, 0, 200, 200);
|
|
reference: |
|
|
ctx.fillStyle = 'green';
|
|
ctx.fillRect(0, 0, 200, 200);
|