Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / src / tracing / draw_helpers.js
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 'use strict';
6
7 tvcm.require('tvcm.sorted_array_utils');
8 tvcm.require('tracing.color_scheme');
9 tvcm.require('tracing.elided_cache');
10
11 /**
12  * @fileoverview Provides various helper methods for drawing to a provided
13  * canvas.
14  */
15 tvcm.exportTo('tracing', function() {
16   var elidedTitleCache = new tracing.ElidedTitleCache();
17   var palette = tracing.getColorPalette();
18   var EventPresenter = tracing.EventPresenter;
19
20   /**
21    * Should we elide text on trace labels?
22    * Without eliding, text that is too wide isn't drawn at all.
23    * Disable if you feel this causes a performance problem.
24    * This is a default value that can be overridden in tracks for testing.
25    * @const
26    */
27   var SHOULD_ELIDE_TEXT = true;
28
29   /**
30    * Draw the define line into |ctx|.
31    *
32    * @param {Context} ctx The context to draw into.
33    * @param {float} x1 The start x position of the line.
34    * @param {float} y1 The start y position of the line.
35    * @param {float} x2 The end x position of the line.
36    * @param {float} y2 The end y position of the line.
37    */
38   function drawLine(ctx, x1, y1, x2, y2) {
39     ctx.moveTo(x1, y1);
40     ctx.lineTo(x2, y2);
41   }
42
43   /**
44    * Draw the defined triangle into |ctx|.
45    *
46    * @param {Context} ctx The context to draw into.
47    * @param {float} x1 The first corner x.
48    * @param {float} y1 The first corner y.
49    * @param {float} x2 The second corner x.
50    * @param {float} y2 The second corner y.
51    * @param {float} x3 The third corner x.
52    * @param {float} y3 The third corner y.
53    */
54   function drawTriangle(ctx, x1, y1, x2, y2, x3, y3) {
55     ctx.beginPath();
56     ctx.moveTo(x1, y1);
57     ctx.lineTo(x2, y2);
58     ctx.lineTo(x3, y3);
59     ctx.closePath();
60   }
61
62   /**
63    * Draw an arrow into |ctx|.
64    *
65    * @param {Context} ctx The context to draw into.
66    * @param {float} x1 The shaft x.
67    * @param {float} y1 The shaft y.
68    * @param {float} x2 The head x.
69    * @param {float} y2 The head y.
70    * @param {float} arrowLength The length of the head.
71    * @param {float} arrowWidth The width of the head.
72    */
73   function drawArrow(ctx, x1, y1, x2, y2, arrowLength, arrowWidth) {
74     var dx = x2 - x1;
75     var dy = y2 - y1;
76     var len = Math.sqrt(dx * dx + dy * dy);
77     var perc = (len - arrowLength) / len;
78     var bx = x1 + perc * dx;
79     var by = y1 + perc * dy;
80     var ux = dx / len;
81     var uy = dy / len;
82     var ax = uy * arrowWidth;
83     var ay = -ux * arrowWidth;
84
85     ctx.beginPath();
86     drawLine(ctx, x1, y1, x2, y2);
87     ctx.stroke();
88
89     drawTriangle(ctx,
90         bx + ax, by + ay,
91         x2, y2,
92         bx - ax, by - ay);
93     ctx.fill();
94   }
95
96   /**
97    * Draw the provided slices to the screen.
98    *
99    * Each of the elements in |slices| must provide the follow methods:
100    *   * start
101    *   * duration
102    *   * colorId
103    *   * selected
104    *
105    * @param {Context} ctx The canvas context.
106    * @param {TimelineDrawTransform} dt The draw transform.
107    * @param {float} viewLWorld The left most point of the world viewport.
108    * @param {float} viewLWorld The right most point of the world viewport.
109    * @param {float} viewHeight The height of the viewport.
110    * @param {Array} slices The slices to draw.
111    * @param {bool} async Whether the slices are drawn with async style.
112    */
113   function drawSlices(ctx, dt, viewLWorld, viewRWorld, viewHeight, slices,
114                       async) {
115     var pixelRatio = window.devicePixelRatio || 1;
116     var pixWidth = dt.xViewVectorToWorld(1);
117     var height = viewHeight * pixelRatio;
118
119     // Begin rendering in world space.
120     ctx.save();
121     dt.applyTransformToCanvas(ctx);
122
123     var tr = new tracing.FastRectRenderer(
124         ctx, 2 * pixWidth, 2 * pixWidth, palette);
125     tr.setYandH(0, height);
126
127     var lowSlice = tvcm.findLowIndexInSortedArray(
128         slices,
129         function(slice) { return slice.start + slice.duration; },
130         viewLWorld);
131
132     for (var i = lowSlice; i < slices.length; ++i) {
133       var slice = slices[i];
134       var x = slice.start;
135       if (x > viewRWorld)
136         break;
137
138       var w = pixWidth;
139       if (slice.duration > 0) {
140         w = Math.max(slice.duration, 0.001);
141         if (w < pixWidth)
142           w = pixWidth;
143       }
144
145       var colorId = EventPresenter.getSliceColorId(slice);
146       var alpha = EventPresenter.getSliceAlpha(slice, async);
147       tr.fillRect(x, w, colorId, alpha);
148     }
149     tr.flush();
150     ctx.restore();
151   }
152
153   /**
154    * Draw the provided instant slices as lines to the screen.
155    *
156    * Each of the elements in |slices| must provide the follow methods:
157    *   * start
158    *   * duration with value of 0.
159    *   * colorId
160    *   * selected
161    *
162    * @param {Context} ctx The canvas context.
163    * @param {TimelineDrawTransform} dt The draw transform.
164    * @param {float} viewLWorld The left most point of the world viewport.
165    * @param {float} viewLWorld The right most point of the world viewport.
166    * @param {float} viewHeight The height of the viewport.
167    * @param {Array} slices The slices to draw.
168    * @param {Numer} lineWidthInPixels The width of the lines.
169    */
170   function drawInstantSlicesAsLines(
171       ctx, dt, viewLWorld, viewRWorld, viewHeight, slices, lineWidthInPixels) {
172     var pixelRatio = window.devicePixelRatio || 1;
173     var height = viewHeight * pixelRatio;
174
175     var pixWidth = dt.xViewVectorToWorld(1);
176
177     // Begin rendering in world space.
178     ctx.save();
179     ctx.lineWidth = pixWidth * lineWidthInPixels;
180     dt.applyTransformToCanvas(ctx);
181     ctx.beginPath();
182
183     var lowSlice = tvcm.findLowIndexInSortedArray(
184         slices,
185         function(slice) { return slice.start; },
186         viewLWorld);
187
188     for (var i = lowSlice; i < slices.length; ++i) {
189       var slice = slices[i];
190       var x = slice.start;
191       if (x > viewRWorld)
192         break;
193
194       ctx.strokeStyle = EventPresenter.getInstantSliceColor(slice);
195
196       ctx.moveTo(x, 0);
197       ctx.lineTo(x, height);
198     }
199     ctx.stroke();
200     ctx.restore();
201   }
202
203   /**
204    * Draws the labels for the given slices.
205    *
206    * The |slices| array must contain objects with the following API:
207    *   * start
208    *   * duration
209    *   * title
210    *   * didNotFinish (optional)
211    *
212    * @param {Context} ctx The graphics context.
213    * @param {TimelineDrawTransform} dt The draw transform.
214    * @param {float} viewLWorld The left most point of the world viewport.
215    * @param {float} viewLWorld The right most point of the world viewport.
216    * @param {Array} slices The slices to label.
217    * @param {bool} async Whether the slice labels are drawn with async style.
218    */
219   function drawLabels(ctx, dt, viewLWorld, viewRWorld, slices, async) {
220     var pixelRatio = window.devicePixelRatio || 1;
221     var pixWidth = dt.xViewVectorToWorld(1);
222
223     ctx.save();
224
225     ctx.textAlign = 'center';
226     ctx.textBaseline = 'top';
227     ctx.font = (10 * pixelRatio) + 'px sans-serif';
228
229     if (async)
230       ctx.font = 'italic ' + ctx.font;
231
232     var lowSlice = tvcm.findLowIndexInSortedArray(
233         slices,
234         function(slice) { return slice.start + slice.duration; },
235         viewLWorld);
236
237     // Don't render text until until it is 20px wide
238     var quickDiscardThresshold = pixWidth * 20;
239     for (var i = lowSlice; i < slices.length; ++i) {
240       var slice = slices[i];
241       if (slice.start > viewRWorld)
242         break;
243
244       if (slice.duration <= quickDiscardThresshold)
245         continue;
246
247       var title = slice.title +
248           (slice.didNotFinish ? ' (Did Not Finish)' : '');
249
250       var drawnTitle = title;
251       var drawnWidth = elidedTitleCache.labelWidth(ctx, drawnTitle);
252       var fullLabelWidth = elidedTitleCache.labelWidthWorld(
253           ctx, drawnTitle, pixWidth);
254       if (SHOULD_ELIDE_TEXT && fullLabelWidth > slice.duration) {
255         var elidedValues = elidedTitleCache.get(
256             ctx, pixWidth,
257             drawnTitle, drawnWidth,
258             slice.duration);
259         drawnTitle = elidedValues.string;
260         drawnWidth = elidedValues.width;
261       }
262
263       if (drawnWidth * pixWidth < slice.duration) {
264         ctx.fillStyle = EventPresenter.getTextColor(slice);
265         var cX = dt.xWorldToView(slice.start + 0.5 * slice.duration);
266         ctx.fillText(drawnTitle, cX, 2.5 * pixelRatio, drawnWidth);
267       }
268     }
269     ctx.restore();
270   }
271
272   return {
273     drawSlices: drawSlices,
274     drawInstantSlicesAsLines: drawInstantSlicesAsLines,
275     drawLabels: drawLabels,
276
277     drawLine: drawLine,
278     drawTriangle: drawTriangle,
279     drawArrow: drawArrow,
280
281     elidedTitleCache_: elidedTitleCache
282   };
283 });