<!DOCTYPE HTML> <title>Canvas Tests</title> <script src="/tests/SimpleTest/SimpleTest.js"></script> <link rel="stylesheet" href="/tests/SimpleTest/test.css"> <body> <script> SimpleTest.waitForExplicitFinish(); const Cc = SpecialPowers.Cc; const Cr = SpecialPowers.Cr; function isPixel(ctx, x,y, c, d) { var pos = x + "," + y; var color = c[0] + "," + c[1] + "," + c[2] + "," + c[3]; var pixel = ctx.getImageData(x, y, 1, 1); var pr = pixel.data[0], pg = pixel.data[1], pb = pixel.data[2], pa = pixel.data[3]; ok(c[0]-d <= pr && pr <= c[0]+d && c[1]-d <= pg && pg <= c[1]+d && c[2]-d <= pb && pb <= c[2]+d && c[3]-d <= pa && pa <= c[3]+d, "pixel "+pos+" of "+ctx.canvas.id+" is "+pr+","+pg+","+pb+","+pa+"; expected "+color+" +/- "+d); } </script> <p>Canvas test: test_drawClipPath_canvas</p> <canvas id="c1" class="output" width="100" height="100">+ </canvas> <script type="text/javascript"> function test_drawClipPath_canvas() { var c = document.getElementById("c1"); var ctx = c.getContext("2d"); var path = new Path2D(); path.rect(0, 0, 100, 100); path.rect(25, 25, 50, 50); ctx.fillStyle = 'rgb(255,0,0)'; ctx.beginPath(); ctx.fillRect(0, 0, 100, 100); ctx.fillStyle = 'rgb(0,255,0)'; ctx.save(); ctx.clip(path); ctx.fillRect(0, 0, 100, 100); isPixel(ctx, 50, 50, [0, 255, 0, 255], 5); ctx.restore(); ctx.fillStyle = 'rgb(255,0,0)'; ctx.beginPath(); ctx.fillRect(0, 0, 100, 100); ctx.fillStyle = 'rgb(0,255,0)'; ctx.save(); ctx.clip(path, 'nonzero'); ctx.fillRect(0, 0, 100, 100); isPixel(ctx, 50, 50, [0, 255, 0, 255], 5); ctx.restore(); ctx.fillStyle = 'rgb(255,0,0)'; ctx.beginPath(); ctx.fillRect(0, 0, 100, 100); ctx.fillStyle = 'rgb(0,255,0)'; ctx.save(); ctx.clip(path, 'evenodd'); ctx.fillRect(0, 0, 100, 100); isPixel(ctx, 50, 50, [255, 0, 0, 255], 5); ctx.restore(); } </script> <p>Canvas test: test_drawFillPath_canvas</p> <canvas id="c2" class="output" width="100" height="100">+ </canvas> <script type="text/javascript"> function test_drawFillPath_canvas() { var c = document.getElementById("c2"); var ctx = c.getContext("2d"); var path = new Path2D(); path.rect(0, 0, 100, 100); path.rect(25, 25, 50, 50); ctx.fillStyle = 'rgb(255,0,0)'; ctx.fillRect(0, 0, 100, 100); ctx.fillStyle = 'rgb(0,255,0)'; ctx.fill(path); isPixel(ctx, 50, 50, [0, 255, 0, 255], 5); ctx.fillStyle = 'rgb(255,0,0)'; ctx.fillRect(0, 0, 100, 100); ctx.fillStyle = 'rgb(0,255,0)'; ctx.fill(path, 'nonzero'); isPixel(ctx, 50, 50, [0, 255, 0, 255], 5); ctx.fillStyle = 'rgb(255,0,0)'; ctx.fillRect(0, 0, 100, 100); ctx.fillStyle = 'rgb(0,255,0)'; ctx.fill(path, 'evenodd'); isPixel(ctx, 50, 50, [255, 0, 0, 255], 5); } </script> <p>Canvas test: test_drawStrokePath_canvas</p> <canvas id="c3" class="output" width="100" height="100">+ </canvas> <script type="text/javascript"> function test_drawStrokePath_canvas() { var c = document.getElementById("c3"); var ctx = c.getContext("2d"); var path = new Path2D(); path.rect(0, 0, 100, 100); path.rect(25, 25, 50, 50); ctx.fillStyle = 'rgb(255,0,0)'; ctx.fillRect(0, 0, 100, 100); ctx.strokeStyle = 'rgb(0,255,0)'; ctx.lineWidth = 5; ctx.stroke(path); isPixel(ctx, 0, 0, [0, 255, 0, 255], 5); isPixel(ctx, 25, 25, [0, 255, 0, 255], 5); isPixel(ctx, 10, 10, [255, 0, 0, 255], 5); } </script> <p>Canvas test: test_large_canvas</p> <canvas id="c4" class="output" width="10000" height="100">+ </canvas> <script type="text/javascript"> function test_large_canvas() { // test paths on large canvases. On certain platforms this will // trigger retargeting of the backend var c = document.getElementById("c4"); var ctx = c.getContext("2d"); var path = new Path2D(); path.rect(0, 0, 100, 100); path.rect(25, 25, 50, 50); ctx.fillStyle = 'rgb(255,0,0)'; ctx.fillRect(0, 0, 100, 100); ctx.fillStyle = 'rgb(0,255,0)'; ctx.fill(path); isPixel(ctx, 50, 50, [0, 255, 0, 255], 5); ctx.fillStyle = 'rgb(255,0,0)'; ctx.fillRect(0, 0, 100, 100); ctx.fillStyle = 'rgb(0,255,0)'; ctx.fill(path, 'nonzero'); isPixel(ctx, 50, 50, [0, 255, 0, 255], 5); ctx.fillStyle = 'rgb(255,0,0)'; ctx.fillRect(0, 0, 100, 100); ctx.fillStyle = 'rgb(0,255,0)'; ctx.fill(path, 'evenodd'); isPixel(ctx, 50, 50, [255, 0, 0, 255], 5); } </script> <p>Canvas test: test_isPointInPath_canvas</p> <canvas id="c5" class="output" width="100" height="100">+ </canvas> <script type="text/javascript"> function shouldThrow(ctx, s) { var _ok = false; try { eval(s); } catch(e) { _ok = true; } ok(_ok, s); } function shouldBeTrue(ctx, path, s) { var _ok = eval(s); ok(_ok, s); } function shouldBeFalse(ctx, path, s) { var _ok = !eval(s); ok(_ok, s); } function test_isPointInPath_canvas() { var c = document.getElementById("c5"); var ctx = c.getContext("2d"); var path = new Path2D(); path.rect(0, 0, 100, 100); path.rect(25, 25, 50, 50); shouldBeTrue(ctx, path, "ctx.isPointInPath(path, 50, 50)"); shouldBeFalse(ctx, path, "ctx.isPointInPath(path, NaN, 50)"); shouldBeFalse(ctx, path, "ctx.isPointInPath(path, 50, NaN)"); path = new Path2D(); path.rect(0, 0, 100, 100); path.rect(25, 25, 50, 50); shouldBeTrue(ctx, path, "ctx.isPointInPath(path, 50, 50, 'nonzero')"); path = new Path2D(); path.rect(0, 0, 100, 100); path.rect(25, 25, 50, 50); shouldBeFalse(ctx, path, "ctx.isPointInPath(path, 50, 50, 'evenodd')"); shouldThrow(ctx, "ctx.isPointInPath(null, 50, 50)"); shouldThrow(ctx, "ctx.isPointInPath(null, 50, 50, 'nonzero')"); shouldThrow(ctx, "ctx.isPointInPath(null, 50, 50, 'evenodd')"); shouldThrow(ctx, "ctx.isPointInPath(path, 50, 50)"); shouldThrow(ctx, "ctx.isPointInPath(path, 50, 50, 'nonzero')"); shouldThrow(ctx, "ctx.isPointInPath(path, 50, 50, 'evenodd')"); shouldThrow(ctx, "ctx.isPointInPath([], 50, 50)"); shouldThrow(ctx, "ctx.isPointInPath([], 50, 50, 'nonzero')"); shouldThrow(ctx, "ctx.isPointInPath([], 50, 50, 'evenodd')"); shouldThrow(ctx, "ctx.isPointInPath({}, 50, 50)"); shouldThrow(ctx, "ctx.isPointInPath({}, 50, 50, 'nonzero')"); shouldThrow(ctx, "ctx.isPointInPath({}, 50, 50, 'evenodd')"); } </script> <p>Canvas test: test_isPointInStroke_canvas</p> <canvas id="c6" class="output" width="100" height="100">+ </canvas> <script type="text/javascript"> function test_isPointInStroke_canvas() { var c = document.getElementById("c6"); var ctx = c.getContext("2d"); ctx.strokeStyle = '#0ff'; var path = new Path2D(); path.rect(20,20,100,100); shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,20,20)"); shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,120,20)"); shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,20,120)"); shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,120,120)"); shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,70,20)"); shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,20,70)"); shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,120,70)"); shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,70,120)"); shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,22,22)"); shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,118,22)"); shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,22,118)"); shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,118,118)"); shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,70,18)"); shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,122,70)"); shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,70,122)"); shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,18,70)"); shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,NaN,122)"); shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,18,NaN)"); shouldThrow(ctx, "ctx.isPointInStroke(null,70,20)"); shouldThrow(ctx, "ctx.isPointInStroke([],20,70)"); shouldThrow(ctx, "ctx.isPointInStroke({},120,70)"); ctx.lineWidth = 10; shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,22,22)"); shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,118,22)"); shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,22,118)"); shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,118,118)"); shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,70,18)"); shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,122,70)"); shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,70,122)"); shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,18,70)"); shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,26,70)"); shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,70,26)"); shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,70,114)"); shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,114,70)"); path = new Path2D(); path.moveTo(10,10); path.lineTo(110,20); path.lineTo(10,30); ctx.lineJoin = "bevel"; shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,113,20)"); ctx.miterLimit = 40.0; ctx.lineJoin = "miter"; shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,113,20)"); ctx.miterLimit = 2.0; shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,113,20)"); path = new Path2D(); path.moveTo(10,10); path.lineTo(110,10); ctx.lineCap = "butt"; shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,112,10)"); ctx.lineCap = "round"; shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,112,10)"); shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,117,10)"); ctx.lineCap = "square"; shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,112,10)"); shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,117,10)"); ctx.lineCap = "butt"; ctx.setLineDash([10,10]); shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,15,10)"); shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,25,10)"); shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,35,10)"); ctx.lineDashOffset = 10; shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,15,10)"); shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,25,10)"); shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,35,10)"); } </script> <p>Canvas test: test_pathconstructor_canvas</p> <canvas id="c7" class="output" width="200" height="100">+ </canvas> <script type="text/javascript"> function test_pathconstructor_canvas() { var c = document.getElementById("c7"); var ctx = c.getContext("2d"); var p = new Path2D("M100,0L200,0L200,100L100,100z"); ctx.fillStyle = 'blue'; ctx.fill(p); isPixel(ctx, 105, 5, [0, 0, 255, 255], 0); isPixel(ctx, 5, 5, [0, 0, 0, 0], 0); // copy constructor. This should not crash. var p1 = new Path2D(); var _p2 = new Path2D(p1); p1.arcTo(0, 0, 1, 1, 2); } </script> <p>Canvas test: test_addpath_canvas</p> <canvas id="c8" class="output" width="200" height="200">+ </canvas> <script type="text/javascript"> function test_addpath_canvas() { var c = document.getElementById("c8"); var ctx = c.getContext("2d"); ctx.beginPath(); var p1 = new Path2D(); p1.rect(0,0,100,100); var p2 = new Path2D(); p2.rect(0,100,100,100); var m = ctx.currentTransform; p1.addPath(p2, m); ctx.fillStyle = 'yellow'; ctx.fill(p1); isPixel(ctx, 0, 100, [255, 255, 0, 255], 0); ctx.clearRect(0,0,200,200); ctx.beginPath(); var p3 = new Path2D(); p3.rect(0,0,100,100); var p4 = new Path2D(); p4.rect(0,100,100,100); var m = document.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGMatrix(); m.a = 1; m.b = 0; m.c = 0; m.d = 1; m.e = 100; m.f = -100; p3.addPath(p4, m); ctx.fillStyle = 'yellow'; ctx.fill(p3); isPixel(ctx, 50, 50, [255, 255, 0, 255], 0); isPixel(ctx, 150, 150, [0, 0, 0, 0], 0); var p5 = new Path2D(); p5.rect(0,0,100,100); shouldThrow(ctx, "p5.addPath(null, m)"); shouldThrow(ctx, "p5.addPath([], m)"); shouldThrow(ctx, "p5.addPath({}, m)"); p5 = p5.addPath(p5); } </script> <script> function runTests() { try { test_drawClipPath_canvas(); } catch(e) { ok(false, "unexpected exception thrown in: test_drawClipPath_canvas"); throw e; } try { test_drawFillPath_canvas(); } catch(e) { ok(false, "unexpected exception thrown in: test_drawFillPath_canvas"); throw e; } try { test_drawStrokePath_canvas(); } catch(e) { ok(false, "unexpected exception thrown in: test_drawStrokePath_canvas"); throw e; } try { test_large_canvas(); } catch(e) { ok(false, "unexpected exception thrown in: test_large_canvas"); throw e; } try { test_isPointInPath_canvas(); } catch(e) { ok(false, "unexpected exception thrown in: test_isPointInPath_canvas"); throw e; } try { test_isPointInStroke_canvas(); } catch(e) { ok(false, "unexpected exception thrown in: test_isPointInStroke_canvas"); throw e; } try { test_pathconstructor_canvas(); } catch(e) { ok(false, "unexpected exception thrown in: test_pathconstructor_canvas"); throw e; } try { test_addpath_canvas(); } catch(e) { ok(false, "unexpected exception thrown in: test_addpath_canvas"); throw e; } SimpleTest.finish(); } addLoadEvent(function() { SpecialPowers.pushPrefEnv({"set":[["canvas.path.enabled", true]]}, runTests); }); // Don't leak the world via the Path2D reference to its window. document.all; window.p = new Path2D(); </script>