Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: samples/openglui/src/openglui_canvas_tests.dart

Issue 12186002: Canvas API. There are still a number of things to do: (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « samples/openglui/src/gl.dart ('k') | samples/openglui/src/openglui_raytrace.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4 //
5 // Canvas API tests. Some of these are adapted from:
6 //
7 // http://www.html5canvastutorials.com/
8
9 library openglui_canvas_tests;
10
11 import 'gl.dart';
12 import 'dart:math' as Math;
13
14 var ctx;
15 var width, height;
16 bool isDirty = true;
17 var canvas;
18
19 void resize(int w, int h) {
20 width = w;
21 height = h;
22 }
23
24 void setup(canvasp, int w, int h) {
25 if (canvasp == null) {
26 canvas = new CanvasElement(width: w, height: h);
27 } else {
28 canvas = canvasp;
29 // called from gl_driver.dart.
30 // This is a kludge; we need a clean way of handling events.
31 canvas.on.mouseDown.add((e) {
32 ++testnum;
33 });
34 }
35 ctx = canvas.getContext("2d");
36 if (ctx == null) {
37 throw "Failed to get 2D context";
38 }
39 resize(w, h);
40 log("Done setup");
41 }
42
43 resetCanvas() {
44 ctx.globalCompositeOperation = "source-over";
45 ctx.setTransform(1, 0, 0, 1, 0, 0);
46 ctx.fillStyle = "#FFFFFF";
47 ctx.clearRect(0, 0, width, height);
48 ctx.shadowOffsetX = ctx.shadowOffsetY = ctx.shadowBlur = 0.0;
49 ctx.beginPath();
50 }
51
52 initTest(title) {
53 resetCanvas();
54 ctx.font = "15px Courier";
55 ctx.textAlign = 'left';
56 ctx.fillStyle = "black";
57 ctx.fillText(title, 20, 20);
58 }
59
60 helloWorld() {
61 initTest("Hello world");
62 ctx.font = "30px Courier";
63 ctx.strokeStyle = "#7F7F7F";
64 ctx.fillStyle = "#7F7F7F";
65 ctx.textAlign = "center";
66 ctx.lineWidth = 2;
67 ctx.strokeText("Align Center", width / 2, height / 4);
68 ctx.textAlign = "left";
69 ctx.fillText("Align Left", width / 2, height / 2);
70 ctx.textAlign = "right";
71 ctx.fillText("Align Right", width / 2, 3 * height / 4);
72 }
73
74 blocks() {
75 initTest("fillRect/strokeRect");
76 ctx.fillStyle = "#FF0000";
77 ctx.fillRect(width / 10, height / 10, width / 2, height / 25);
78 ctx.fillStyle = "#00FF00";
79 ctx.fillRect(width / 4, height / 5, width / 20, height / 8);
80 //ctx.fillStyle = "rgba(0,0,255,0.8)";
81 ctx.strokeStyle = "rgba(128,128,128, 0.5)";
82 //ctx.fillStyle = "#7F7F7F";
83 ctx.strokeRect(width / 5, height / 10, width / 2, height / 8);
84 }
85
86 square(left, top, width, height) {
87 ctx.beginPath();
88 ctx.moveTo(left, top);
89 ctx.lineTo(left + width, top);
90 ctx.lineTo(left + width, top + height);
91 ctx.lineTo(left, top + height);
92 ctx.closePath(); //lineTo(left, top);
93 }
94
95 squares() {
96 initTest("fill/stroke paths");
97 ctx.strokeStyle = "black";
98 ctx.fillStyle = "#FF0000";
99 ctx.lineWidth = 4;
100 square(width / 10, height / 10, width / 2, height / 25);
101 ctx.fill();
102 ctx.stroke();
103 ctx.fillStyle = "#00FF00";
104 square(width / 4, height / 5, width / 20, height / 8);
105 ctx.fill();
106 ctx.stroke();
107 ctx.fillStyle = "rgba(128,128,128, 0.5)";
108 square(width / 5, height / 10, width / 2, height / 8);
109 ctx.fill();
110 ctx.stroke();
111 }
112
113 lineJoin() {
114 initTest("Line joins");
115 ctx.strokeStyle = "black";
116 ctx.fillStyle = "#FF0000";
117 ctx.lineWidth = 8;
118 ctx.lineJoin = "round";
119 square(width / 10, height / 10, width / 2, height / 25);
120 ctx.stroke();
121 ctx.fillStyle = "#00FF00";
122 ctx.lineJoin = "bevel";
123 square(width / 4, height / 5, width / 20, height / 8);
124 ctx.stroke();
125 ctx.fillStyle = "rgba(128,128,128, 0.5)";
126 ctx.lineJoin = "miter";
127 square(width / 5, height / 10, width / 2, height / 8);
128 ctx.stroke();
129 }
130
131 grid() {
132 initTest("line strokes");
133 ctx.lineWidth = 1;
134 for (var x = 0.5; x < width; x += 10) {
135 ctx.moveTo(x, 0);
136 ctx.lineTo(x, height);
137 }
138 for (var y = 0.5; y < height; y += 10) {
139 ctx.moveTo(0, y);
140 ctx.lineTo(width, y);
141 }
142 ctx.strokeStyle = "#eee";
143 ctx.stroke();
144 }
145
146 line(x1, y1, x2, y2) {
147 ctx.beginPath();
148 ctx.moveTo(x1, y1);
149 ctx.lineTo(x2, y2);
150 }
151
152 strokeLines() {
153 initTest("line caps");
154 ctx.lineWidth = height / 40;
155 ctx.strokeStyle = '#0000ff';
156 // butt line cap (top line)
157 line(width / 4, height / 4, 3 * width / 4, height / 4);
158 ctx.lineCap = 'butt';
159 ctx.stroke();
160
161 // round line cap (middle line)
162 line(width / 4, height / 2, 3 * width / 4, height / 2);
163 ctx.lineCap = 'round';
164 ctx.stroke();
165
166 // square line cap (bottom line)
167 line(width / 4, 3 * height / 4, 3 * width / 4, 3 * height / 4);
168 ctx.lineCap = 'square';
169 ctx.stroke();
170 }
171
172 colors() {
173 initTest("Colors");
174 var colors = [
175 "maroon",
176 "red",
177 "orange",
178 "yellow",
179 "olive",
180 "purple",
181 "fuschia",
182 "white",
183 "lime",
184 "green",
185 "navy",
186 "blue",
187 "aqua",
188 "teal",
189 "silver",
190 "gray",
191 "black"
192 ];
193
194 var i = 1;
195 var yinc = height / (2 * colors.length + 1);
196
197 ctx.textAlign = "center";
198 ctx.font = "${yinc}px Courier";
199
200 for (var color in colors) {
201 ctx.fillStyle = color;
202 ctx.fillRect(width / 4, i * 2 * yinc, width / 2, 3 * yinc / 2);
203 ctx.fillStyle = (color == "gray") ? "white" : "gray";
204 ctx.fillText(color, width / 2, i * 2 * yinc + 7 * yinc / 8);
205 ++i;
206 }
207 }
208
209 smiley() {
210 initTest("arcs");
211 ctx.translate(width / 2 - 80, height / 2 - 75);
212
213 ctx.beginPath();
214 ctx.arc(100,80,75,0,Math.PI*2,true);
215 ctx.fillStyle = "rgb(255,255,204)";
216 ctx.fill();
217 ctx.stroke();
218
219 ctx.fillStyle = "black";
220 ctx.beginPath();
221 ctx.arc(80,55,8,0,Math.PI*2,true);
222 ctx.fill();
223
224 ctx.beginPath();
225 ctx.arc(120,55,8,0,Math.PI*2,true);
226 ctx.fill();
227
228 ctx.beginPath();
229 ctx.arc(100,85,10,4,Math.PI*2,true);
230 ctx.stroke();
231
232 ctx.beginPath();
233 ctx.arc(100,95,30,0,Math.PI,false);
234 ctx.stroke();
235
236 ctx.setTransform(1, 0, 0, 1, 0, 0);
237 }
238
239 rot(txt1, [txt2, sx = 1.0, sy = 1.0]) {
240 if (txt2 == null) txt2 = txt1;
241 ctx.font = "50px sans serif";
242 ctx.translate(width / 2, height / 2);
243 ctx.textAlign = "right";
244 ctx.fillStyle = "red";
245 ctx.fillText(txt1, 0, 0);
246 ctx.rotate(Math.PI / 2);
247 ctx.scale(sx, sy);
248 ctx.fillStyle = "green";
249 ctx.fillText(txt2, 0, 0);
250 ctx.scale(sx, sy);
251 ctx.rotate(Math.PI / 2);
252 ctx.fillStyle = "blue";
253 ctx.fillText(txt1, 0, 0);
254 ctx.scale(sx, sy);
255 ctx.rotate(Math.PI / 2);
256 ctx.fillStyle = "yellow";
257 ctx.fillText(txt2, 0, 0);
258 ctx.setTransform(1, 0, 0, 1, 0, 0);
259 }
260
261 rotate() {
262 initTest("Rotation");
263 rot("Dart");
264 }
265
266 alpha() {
267 initTest("Global alpha");
268 ctx.fillStyle = "gray";
269 ctx.fillRect(0, 0, width, height);
270 grid();
271 ctx.globalAlpha = 0.5;
272 rot("Global", "Alpha");
273 ctx.globalAlpha = 1.0;
274 }
275
276 scale() {
277 initTest("Scale");
278 rot("Scale", "Test", 0.8, 0.5);
279 }
280
281 curves() {
282 initTest("Curves");
283 ctx.beginPath();
284 ctx.moveTo(188, 150);
285 ctx.quadraticCurveTo(288, 0, 388, 150);
286 ctx.lineWidth = 2;
287 ctx.strokeStyle = 'red';
288 ctx.stroke();
289 ctx.beginPath();
290 ctx.moveTo(188, 130);
291 ctx.bezierCurveTo(140, 10, 388, 10, 388, 170);
292 ctx.lineWidth = 5;
293 ctx.strokeStyle = 'blue';
294 ctx.stroke();
295 var x1, x2, y1, y2, ex, ey;
296 ctx.beginPath();
297 x1 = width / 4;
298 y1 = height / 2;
299 x2 = width / 2;
300 y2 = height / 4;
301 ex = 3 * width / 4;
302 ey = y1;
303 ctx.moveTo(x1, x2);
304 ctx.quadraticCurveTo(x2, y2, ex, ey);
305 ctx.lineWidth = 10;
306 ctx.strokeStyle = 'green';
307 ctx.stroke();
308
309 ctx.beginPath();
310 ctx.moveTo(188, 130);
311 x1 = width / 8;
312 x2 = 7 * width / 8;
313 y1 = height / 50;
314 y2 = y1;
315 ex = x2;
316 ey = height / 2;
317 ctx.bezierCurveTo(x1, y1, x2, y2, ex, ey);
318 ctx.lineWidth = 7;
319 ctx.strokeStyle = 'black';
320 ctx.stroke();
321
322 // Draw a cloud
323 ctx.beginPath();
324 var wscale = width / 578;
325 var hscale = height / 800;
326 ctx.translate(0, height / 2);
327 ctx.moveTo(170 * wscale, 80 * hscale);
328 ctx.bezierCurveTo(130 * wscale, 100 * hscale,
329 130 * wscale, 150 * hscale,
330 230 * wscale, 150 * hscale);
331 ctx.bezierCurveTo(250 * wscale, 180 * hscale,
332 320 * wscale, 180 * hscale,
333 340 * wscale, 150 * hscale);
334 ctx.bezierCurveTo(420 * wscale, 150 * hscale,
335 420 * wscale, 120 * hscale,
336 390 * wscale, 100 * hscale);
337 ctx.bezierCurveTo(430 * wscale, 40 * hscale,
338 370 * wscale, 30 * hscale,
339 340 * wscale, 50 * hscale);
340 ctx.bezierCurveTo(320 * wscale, 5 * hscale,
341 250 * wscale, 20 * hscale,
342 250 * wscale, 50 * hscale);
343 ctx.bezierCurveTo(200 * wscale, 5 * hscale,
344 150 * wscale, 20 * hscale,
345 170 * wscale, 80 * hscale);
346 ctx.closePath();
347 ctx.lineWidth = 5;
348 ctx.fillStyle = 'gray';
349 ctx.fill();
350 }
351
352 void shadows() {
353 initTest("Shadows");
354 ctx.shadowBlur=20;
355 ctx.shadowColor="black";
356 ctx.fillStyle="red";
357 var w = width / 2;
358 if (w > height / 2) w = height / 2;
359 ctx.fillRect(width / 2 - w / 2, height / 4 - w / 2, w, w);
360 ctx.shadowOffsetX = 10;
361 ctx.shadowOffsetY = 10;
362 ctx.shadowColor="green";
363 ctx.fillRect(width / 2 - w / 2, 3 * height / 4 - w / 2, w, w);
364 }
365
366 void lineJoins() {
367 initTest("Line joins");
368 ctx.lineWidth=10;
369 ctx.lineJoin="miter";
370 ctx.moveTo(width / 2 - 25, height / 4 - 10);
371 ctx.lineTo(width /2 + 25, height / 4);
372 ctx.lineTo(width / 2 - 25, height / 4 + 10);
373 ctx.stroke();
374 ctx.lineJoin="round";
375 ctx.moveTo(width / 2 - 25, height / 2 - 10);
376 ctx.lineTo(width /2 + 25, height / 2);
377 ctx.lineTo(width / 2 - 25, height / 2 + 10);
378 ctx.stroke();
379 ctx.lineJoin="bevel";
380 ctx.moveTo(width / 2 - 25, 3 * height / 4 - 10);
381 ctx.lineTo(width /2 + 25, 3 * height / 4);
382 ctx.lineTo(width / 2 - 25, 3 * height / 4 + 10);
383 ctx.stroke();
384 }
385
386 void saveRestore() {
387 initTest("Save/restore state");
388 ctx.font = "30px courier";
389 ctx.fillStyle = "red";
390 ctx.strokeStyle = "black";
391 ctx.shadowBlur = 5;
392 ctx.shadowColor = "green";
393 ctx.lineWidth = 1;
394 ctx.textAlign = "left";
395 ctx.rotate(Math.PI / 30);
396 ctx.fillText("State 1", width /2, height / 6);
397 ctx.strokeText("State 1", width /2, height / 6);
398 ctx.save();
399
400 ctx.font = "40px sans serif";
401 ctx.fillStyle = "blue";
402 ctx.strokeStyle = "orange";
403 ctx.shadowBlur = 8;
404 ctx.shadowOffsetX = 5;
405 ctx.shadowColor = "black";
406 ctx.lineWidth = 2;
407 ctx.textAlign = "right";
408 ctx.rotate(Math.PI / 30);
409 ctx.fillText("State 2", width /2, 2 * height / 6);
410 ctx.strokeText("State 2", width /2, 2 * height / 6);
411 ctx.save();
412
413 ctx.font = "50px times roman";
414 ctx.fillStyle = "yellow";
415 ctx.strokeStyle = "gray";
416 ctx.shadowBlur = 8;
417 ctx.shadowOffsetX = 5;
418 ctx.shadowColor = "red";
419 ctx.lineWidth = 3;
420 ctx.textAlign = "center";
421 ctx.rotate(-Math.PI / 15);
422 ctx.fillText("State 3", width /2, 3 * height / 6);
423 ctx.strokeText("State 3", width /2, 3 * height / 6);
424
425 ctx.restore();
426 ctx.fillText("State 2", width /2, 4 * height / 6);
427 ctx.strokeText("State 2", width /2, 4 * height / 6);
428
429 ctx.restore();
430 ctx.fillText("State 1", width /2, 5 * height / 6);
431 ctx.strokeText("State 1", width /2, 5 * height / 6);
432 }
433
434 void mirror() {
435 initTest("Mirror");
436 // translate context to center of canvas
437 ctx.translate(width / 2, height / 2);
438
439 // flip context horizontally
440 ctx.scale(-1, 1);
441
442 ctx.font = '30pt Calibri';
443 ctx.textAlign = 'center';
444 ctx.fillStyle = 'blue';
445 ctx.fillText('Magic Mirror', 0, 0);
446 }
447
448 void oval() {
449 initTest("Path - pop state - stroke");
450 var centerX = 0;
451 var centerY = 0;
452 var radius = 50;
453
454 // save state
455 ctx.save();
456
457 // translate context
458 ctx.translate(width / 2, height / 2);
459
460 // scale context horizontally
461 ctx.scale(2, 1);
462
463 // draw circle which will be stretched into an oval
464 ctx.beginPath();
465 ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
466
467 // restore to original state
468 ctx.restore();
469
470 // apply styling
471 ctx.fillStyle = '#8ED6FF';
472 ctx.fill();
473 ctx.lineWidth = 5;
474 ctx.strokeStyle = 'black';
475 ctx.stroke();
476 }
477
478 void lineDash() {
479 initTest("Line dash");
480 ctx.setLineDash([ 5, 8, 3 ]);
481 ctx.strokeStyle = "#FF0000";
482 ctx.strokeRect(width / 10, height / 10, width / 2, height / 25);
483 ctx.lineDashOffset = 1;
484 ctx.strokeStyle = "#00FF00";
485 ctx.strokeRect(width / 4, height / 5, width / 20, height / 8);
486 ctx.setLineDash([]);
487 ctx.strokeStyle = "#0000FF";
488 ctx.strokeStyle = "rgba(128,128,128, 0.5)";
489 ctx.strokeRect(width / 5, height / 10, width / 2, height / 8);
490 log("Width = $width");
491 }
492
493 // TODO(gram) - apparently a canvas can have only one op in its lifetime,
494 // so this test won't work until we can use off-screen canvases.
495 void compositeOp() {
496 initTest("Composition");
497 var num = 0;
498 ctx.font = '10pt Verdana';
499 var numPerRow = width ~/ 95;
500 log("Width = $width, numPerRow = $numPerRow\n");
501 for (var mode in [ 'source-atop', 'source-in',
502 'source-out', 'source-over',
503 'destination-atop', 'destination-in',
504 'destination-out', 'destination-over',
505 'lighter', 'darker',
506 'xor', 'copy']) {
507 var col = num % numPerRow;
508 var row = num ~/ numPerRow;
509 ctx.globalCompositeOperation = mode;
510 ctx.translate(95 * col, 100 * row);
511 log("Doing $mode at row $row, col $col\n");
512 ctx.beginPath();
513 ctx.rect(0, 0, 55, 55);
514 ctx.fillStyle = 'blue';
515 ctx.fill();
516 ctx.beginPath();
517 ctx.arc(50, 50, 35, 0, 2 * Math.PI, false);
518 ctx.fillStyle = 'red';
519 ctx.fill();
520 ctx.fillStyle = 'black';
521 ctx.fillText(mode, 0, 100);
522 ctx.setTransform(1, 0, 0, 1, 0, 0);
523 ++num;
524 }
525 }
526
527 void loadImage() {
528 initTest("Image loading");
529 var imageObj = new ImageElement();
530 imageObj.on.load.add((e) {
531 ctx.drawImage(imageObj, 69, 50);
532 });
533 imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.b mp';
534 }
535
536 void clip() {
537 initTest("Clipping");
538 var x = width / 2;
539 var y = height / 2;
540 var radius = height / 4;
541 var offset = 2 * radius / 3;
542
543 ctx.save();
544 ctx.beginPath();
545 ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
546 ctx.clip();
547
548 // draw blue circle inside clipping region
549 ctx.beginPath();
550 ctx.arc(x - offset, y - offset, radius, 0, 2 * Math.PI, false);
551 ctx.fillStyle = 'blue';
552 ctx.fill();
553
554 // draw yellow circle inside clipping region
555 ctx.beginPath();
556 ctx.arc(x + offset, y, radius, 0, 2 * Math.PI, false);
557 ctx.fillStyle = 'yellow';
558 ctx.fill();
559
560 // draw red circle inside clipping region
561 ctx.beginPath();
562 ctx.arc(x, y + offset, radius, 0, 2 * Math.PI, false);
563 ctx.fillStyle = 'red';
564 ctx.fill();
565
566 // Restore the canvas context to its original state
567 // before we defined the clipping region
568 ctx.restore();
569 ctx.beginPath();
570 ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
571 ctx.lineWidth = 10;
572 ctx.strokeStyle = 'blue';
573 ctx.stroke();
574 }
575
576 void shear() {
577 initTest("Transform");
578 var rectWidth = width / 4;
579 var rectHeight = height / 8;
580
581 // shear matrix:
582 // 1 sx 0
583 // sy 1 0
584 // 0 0 1
585
586 var sx = 0.75;
587 // .75 horizontal shear
588 var sy = 0;
589 // no vertical shear
590
591 // translate context to center of canvas
592 ctx.translate(width / 2, height / 2);
593
594 // apply custom transform
595 ctx.transform(1, sy, sx, 1, 0, 0);
596
597 ctx.fillStyle = 'blue';
598 ctx.fillRect(-rectWidth / 2, rectHeight / -2, rectWidth, rectHeight);
599 }
600
601 int numtests = 21;
602 int testnum = numtests - 1; // Start with latest.
603
604 void update() {
605 if (!isDirty) return;
606 switch(testnum) {
607 case 0:
608 helloWorld();
609 break;
610 case 1:
611 smiley();
612 break;
613 case 2:
614 blocks();
615 break;
616 case 3:
617 squares();
618 break;
619 case 4:
620 grid();
621 break;
622 case 5:
623 strokeLines();
624 break;
625 case 6:
626 lineJoin();
627 break;
628 case 7:
629 colors();
630 break;
631 case 8:
632 rotate();
633 break;
634 case 9:
635 alpha();
636 break;
637 case 10:
638 scale();
639 break;
640 case 11:
641 curves();
642 break;
643 case 12:
644 shadows();
645 break;
646 case 13:
647 lineJoins();
648 break;
649 case 14:
650 saveRestore();
651 break;
652 case 15:
653 mirror();
654 break;
655 case 16:
656 oval();
657 break;
658 case 17:
659 lineDash();
660 break;
661 case 18:
662 loadImage();
663 break;
664 case 19:
665 clip();
666 break;
667 case 20:
668 shear();
669 break;
670 default:
671 testnum = 0;
672 update();
673 break;
674 }
675 isDirty = false;
676 }
677
678 /*
679 TODO(gram): below are the current entry points for input events for the
680 native code version. We need to integrate these somehow with the WebGL
681 version:
682 */
683 onMotionDown(num when, num x, num y) {
684 ++testnum;
685 isDirty = true;
686 log("Marking dirty");
687 }
688 onMotionUp(num when, num x, num y) {}
689 onMotionMove(num when, num x, num y) {}
690 onMotionCancel(num when, num x, num y) {}
691 onMotionOutside(num when, num x, num y) {}
692 onMotionPointerDown(num when, num x, num y) {
693 ++testnum;
694 isDirty = true;
695 log("Marking dirty");
696 }
697
698 onMotionPointerUp(num when, num x, num y) {}
699
700 onKeyDown(num when, int flags, int keycode, int metastate, int repeat) {
701 ++testnum;
702 isDirty = true;
703 log("Marking dirty");
704 }
705
706 onKeyUp(num when, int flags, int keycode, int metastate, int repeat) {}
707
708 onKeyMultiple(num when, int flags, int keycode, int metastate, int repeat) {
709 }
710
711
OLDNEW
« no previous file with comments | « samples/openglui/src/gl.dart ('k') | samples/openglui/src/openglui_raytrace.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698