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