Enhance existing Animometer tests
[WebKit-https.git] / PerformanceTests / Animometer / tests / master / resources / canvas-tests.js
1 (function() {
2
3 // === PAINT OBJECTS ===
4
5 CanvasLineSegment = Utilities.createClass(
6     function(stage)
7     {
8         var circle = Stage.randomInt(0, 3);
9         this._color = ["#e01040", "#10c030", "#744CBA", "#e05010"][circle];
10         this._lineWidth = Math.pow(Pseudo.random(), 12) * 20 + 3;
11         this._omega = Pseudo.random() * 3 + 0.2;
12         var theta = Stage.randomAngle();
13         this._cosTheta = Math.cos(theta);
14         this._sinTheta = Math.sin(theta);
15         this._startX = stage.circleRadius * this._cosTheta + stage.circleX[circle];
16         this._startY = stage.circleRadius * this._sinTheta + stage.circleY[circle];
17         this._length = Math.pow(Pseudo.random(), 8) * stage.lineLengthMaximum + stage.lineMinimum;
18         this._segmentDirection = Pseudo.random() > 0.5 ? -1 : 1;
19     }, {
20
21     draw: function(context)
22     {
23         context.strokeStyle = this._color;
24         context.lineWidth = this._lineWidth;
25
26         this._length += Math.sin(Stage.dateCounterValue(100) * this._omega);
27
28         context.beginPath();
29         context.moveTo(this._startX, this._startY);
30         context.lineTo(this._startX + this._segmentDirection * this._length * this._cosTheta,
31                        this._startY + this._segmentDirection * this._length * this._sinTheta);
32         context.stroke();
33     }
34 });
35
36 CanvasArc = Utilities.createClass(
37     function(stage)
38     {
39         var maxX = 6, maxY = 3;
40         var distanceX = stage.size.x / maxX;
41         var distanceY = stage.size.y / (maxY + 1);
42         var randY = Stage.randomInt(0, maxY);
43         var randX = Stage.randomInt(0, maxX - 1 * (randY % 2));
44
45         this._point = new Point(distanceX * (randX + (randY % 2) / 2), distanceY * (randY + .5));
46
47         this._radius = 20 + Math.pow(Pseudo.random(), 5) * (Math.min(distanceX, distanceY) / 1.8);
48         this._startAngle = Stage.randomAngle();
49         this._endAngle = Stage.randomAngle();
50         this._omega = (Pseudo.random() - 0.5) * 0.3;
51         this._counterclockwise = Stage.randomBool();
52         var colors = ["#101010", "#808080", "#c0c0c0"];
53         colors.push(["#e01040", "#10c030", "#e05010"][(randX + Math.ceil(randY / 2)) % 3]);
54         this._color = colors[Math.floor(Pseudo.random() * colors.length)];
55         this._lineWidth = 1 + Math.pow(Pseudo.random(), 5) * 30;
56         this._doStroke = Stage.randomInt(0, 3) != 0;
57     }, {
58
59     draw: function(context)
60     {
61         this._startAngle += this._omega;
62         this._endAngle += this._omega / 2;
63
64         if (this._doStroke) {
65             context.strokeStyle = this._color;
66             context.lineWidth = this._lineWidth;
67             context.beginPath();
68             context.arc(this._point.x, this._point.y, this._radius, this._startAngle, this._endAngle, this._counterclockwise);
69             context.stroke();
70         } else {
71             context.fillStyle = this._color;
72             context.beginPath();
73             context.lineTo(this._point.x, this._point.y);
74             context.arc(this._point.x, this._point.y, this._radius, this._startAngle, this._endAngle, this._counterclockwise);
75             context.lineTo(this._point.x, this._point.y);
76             context.fill();
77         }
78     }
79 });
80
81 // CanvasLinePoint contains no draw() method since it is either moveTo or
82 // lineTo depending on its index.
83 CanvasLinePoint = Utilities.createClass(
84     function(stage, coordinateMaximum)
85     {
86         var X_LOOPS = 40;
87         var Y_LOOPS = 20;
88
89         var offsets = [[-2, -1], [2, 1], [-1, 0], [1, 0], [-1, 2], [1, -2]];
90         var offset = offsets[Math.floor(Pseudo.random() * offsets.length)];
91
92         this.coordinate = new Point(X_LOOPS/2, Y_LOOPS/2);
93         if (stage.objects.length) {
94             var head = stage.objects[stage.objects.length - 1].coordinate;
95             this.coordinate.x = head.x;
96             this.coordinate.y = head.y;
97         }
98
99         var nextCoordinate = this.coordinate.x + offset[0];
100         if (nextCoordinate < 0 || nextCoordinate > X_LOOPS)
101             this.coordinate.x -= offset[0];
102         else
103             this.coordinate.x = nextCoordinate;
104         nextCoordinate = this.coordinate.y + offset[1];
105         if (nextCoordinate < 0 || nextCoordinate > Y_LOOPS)
106             this.coordinate.y -= offset[1];
107         else
108             this.coordinate.y = nextCoordinate;
109
110         var xOff = .25 * (this.coordinate.y % 2);
111         var randX = (xOff + this.coordinate.x) * stage.size.x / X_LOOPS;
112         var randY = this.coordinate.y * stage.size.y / Y_LOOPS;
113         var colors = ["#101010", "#808080", "#c0c0c0", "#101010", "#808080", "#c0c0c0", "#e01040"];
114         this.color = colors[Math.floor(Pseudo.random() * colors.length)];
115
116         this.width = Math.pow(Pseudo.random(), 5) * 20 + 1;
117         this.isSplit = Pseudo.random() > 0.9;
118         this.point = new Point(randX, randY);
119     }
120 );
121
122 // === STAGES ===
123
124 CanvasLineSegmentStage = Utilities.createSubclass(SimpleCanvasStage,
125     function()
126     {
127         SimpleCanvasStage.call(this, CanvasLineSegment);
128     }, {
129
130     initialize: function(benchmark, options)
131     {
132         SimpleCanvasStage.prototype.initialize.call(this, benchmark, options);
133         this.context.lineCap = options["lineCap"] || "butt";
134         this.lineMinimum = 20;
135         this.lineLengthMaximum = 40;
136         this.circleRadius = this.size.x / 8 - .4 * (this.lineMinimum + this.lineLengthMaximum);
137         this.circleX = [
138             5.5 / 32 * this.size.x,
139             12.5 / 32 * this.size.x,
140             19.5 / 32 * this.size.x,
141             26.5 / 32 * this.size.x,
142         ];
143         this.circleY = [
144             2.1 / 3 * this.size.y,
145             0.9 / 3 * this.size.y,
146             2.1 / 3 * this.size.y,
147             0.9 / 3 * this.size.y
148         ];
149         this.halfSize = this.size.multiply(.5);
150         this.twoFifthsSizeX = this.size.x * .4;
151     },
152
153     animate: function()
154     {
155         var context = this.context;
156         context.clearRect(0, 0, this.size.x, this.size.y);
157
158         var angle = Stage.dateFractionalValue(3000) * Math.PI * 2;
159         var dx = this.twoFifthsSizeX * Math.cos(angle);
160         var dy = this.twoFifthsSizeX * Math.sin(angle);
161
162         var gradient = context.createLinearGradient(this.halfSize.x + dx, this.halfSize.y + dy, this.halfSize.x - dx, this.halfSize.y - dy);
163         var gradientStep = 0.5 + 0.5 * Math.sin(Stage.dateFractionalValue(5000) * Math.PI * 2);
164         var colorStopStep = Utilities.lerp(gradientStep, -.1, .1);
165         var brightnessStep = Math.round(Utilities.lerp(gradientStep, 32, 64));
166         var color1Step = "rgba(" + brightnessStep + "," + brightnessStep + "," + (brightnessStep << 1) + ",.4)";
167         var color2Step = "rgba(" + (brightnessStep << 1) + "," + (brightnessStep << 1) + "," + brightnessStep + ",.4)";
168         gradient.addColorStop(0, color1Step);
169         gradient.addColorStop(.2 + colorStopStep, color1Step);
170         gradient.addColorStop(.8 - colorStopStep, color2Step);
171         gradient.addColorStop(1, color2Step);
172
173         context.lineWidth = 15;
174         for(var i = 0; i < 4; i++) {
175             context.strokeStyle = ["#e01040", "#10c030", "#744CBA", "#e05010"][i];
176             context.fillStyle = ["#70051d", "#016112", "#2F0C6E", "#702701"][i];
177             context.beginPath();
178                 context.arc(this.circleX[i], this.circleY[i], this.circleRadius, 0, Math.PI*2);
179                 context.stroke();
180                 context.fill();
181             context.fillStyle = gradient;
182                 context.fill();
183         }
184
185         for (var i = this.offsetIndex, length = this.objects.length; i < length; ++i)
186             this.objects[i].draw(context);
187     }
188 });
189
190 CanvasLinePathStage = Utilities.createSubclass(SimpleCanvasStage,
191     function()
192     {
193         SimpleCanvasStage.call(this, CanvasLinePoint);
194     }, {
195
196     initialize: function(benchmark, options)
197     {
198         SimpleCanvasStage.prototype.initialize.call(this, benchmark, options);
199         this.context.lineJoin = options["lineJoin"] || "bevel";
200         this.context.lineCap = options["lineCap"] || "butt";
201     },
202
203     animate: function() {
204         var context = this.context;
205
206         context.clearRect(0, 0, this.size.x, this.size.y);
207         context.beginPath();
208         for (var i = this.offsetIndex, length = this.objects.length; i < length; ++i) {
209             var object = this.objects[i];
210             if (i == this.offsetIndex) {
211                 context.lineWidth = object.width;
212                 context.strokeStyle = object.color;
213                 context.moveTo(object.point.x, object.point.y);
214             } else {
215                 if (object.isSplit) {
216                     context.stroke();
217
218                     context.lineWidth = object.width;
219                     context.strokeStyle = object.color;
220                     context.beginPath();
221                 }
222
223                 context.lineTo(object.point.x, object.point.y);
224
225                 if (Pseudo.random() > 0.999)
226                     object.isSplit = !object.isSplit;
227             }
228         }
229         context.stroke();
230     }
231 });
232
233 // === BENCHMARK ===
234
235 CanvasPathBenchmark = Utilities.createSubclass(Benchmark,
236     function(options)
237     {
238         var stage;
239         switch (options["pathType"]) {
240         case "line":
241             stage = new CanvasLineSegmentStage();
242             break;
243         case "linePath":
244             stage = new CanvasLinePathStage();
245             break;
246         case "arcs":
247             stage = new SimpleCanvasStage(CanvasArc);
248             break;
249         }
250
251         Benchmark.call(this, stage, options);
252     }
253 );
254
255 window.benchmarkClass = CanvasPathBenchmark;
256
257 })();