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.
7 tvcm.require('tvcm.sorted_array_utils');
8 tvcm.require('tracing.color_scheme');
9 tvcm.require('tracing.elided_cache');
12 * @fileoverview Provides various helper methods for drawing to a provided
15 tvcm.exportTo('tracing', function() {
16 var elidedTitleCache = new tracing.ElidedTitleCache();
17 var palette = tracing.getColorPalette();
18 var EventPresenter = tracing.EventPresenter;
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.
27 var SHOULD_ELIDE_TEXT = true;
30 * Draw the define line into |ctx|.
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.
38 function drawLine(ctx, x1, y1, x2, y2) {
44 * Draw the defined triangle into |ctx|.
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.
54 function drawTriangle(ctx, x1, y1, x2, y2, x3, y3) {
63 * Draw an arrow into |ctx|.
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.
73 function drawArrow(ctx, x1, y1, x2, y2, arrowLength, arrowWidth) {
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;
82 var ax = uy * arrowWidth;
83 var ay = -ux * arrowWidth;
86 drawLine(ctx, x1, y1, x2, y2);
97 * Draw the provided slices to the screen.
99 * Each of the elements in |slices| must provide the follow methods:
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.
113 function drawSlices(ctx, dt, viewLWorld, viewRWorld, viewHeight, slices,
115 var pixelRatio = window.devicePixelRatio || 1;
116 var pixWidth = dt.xViewVectorToWorld(1);
117 var height = viewHeight * pixelRatio;
119 // Begin rendering in world space.
121 dt.applyTransformToCanvas(ctx);
123 var tr = new tracing.FastRectRenderer(
124 ctx, 2 * pixWidth, 2 * pixWidth, palette);
125 tr.setYandH(0, height);
127 var lowSlice = tvcm.findLowIndexInSortedArray(
129 function(slice) { return slice.start + slice.duration; },
132 for (var i = lowSlice; i < slices.length; ++i) {
133 var slice = slices[i];
139 if (slice.duration > 0) {
140 w = Math.max(slice.duration, 0.001);
145 var colorId = EventPresenter.getSliceColorId(slice);
146 var alpha = EventPresenter.getSliceAlpha(slice, async);
147 tr.fillRect(x, w, colorId, alpha);
154 * Draw the provided instant slices as lines to the screen.
156 * Each of the elements in |slices| must provide the follow methods:
158 * * duration with value of 0.
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.
170 function drawInstantSlicesAsLines(
171 ctx, dt, viewLWorld, viewRWorld, viewHeight, slices, lineWidthInPixels) {
172 var pixelRatio = window.devicePixelRatio || 1;
173 var height = viewHeight * pixelRatio;
175 var pixWidth = dt.xViewVectorToWorld(1);
177 // Begin rendering in world space.
179 ctx.lineWidth = pixWidth * lineWidthInPixels;
180 dt.applyTransformToCanvas(ctx);
183 var lowSlice = tvcm.findLowIndexInSortedArray(
185 function(slice) { return slice.start; },
188 for (var i = lowSlice; i < slices.length; ++i) {
189 var slice = slices[i];
194 ctx.strokeStyle = EventPresenter.getInstantSliceColor(slice);
197 ctx.lineTo(x, height);
204 * Draws the labels for the given slices.
206 * The |slices| array must contain objects with the following API:
210 * * didNotFinish (optional)
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.
219 function drawLabels(ctx, dt, viewLWorld, viewRWorld, slices, async) {
220 var pixelRatio = window.devicePixelRatio || 1;
221 var pixWidth = dt.xViewVectorToWorld(1);
225 ctx.textAlign = 'center';
226 ctx.textBaseline = 'top';
227 ctx.font = (10 * pixelRatio) + 'px sans-serif';
230 ctx.font = 'italic ' + ctx.font;
232 var lowSlice = tvcm.findLowIndexInSortedArray(
234 function(slice) { return slice.start + slice.duration; },
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)
244 if (slice.duration <= quickDiscardThresshold)
247 var title = slice.title +
248 (slice.didNotFinish ? ' (Did Not Finish)' : '');
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(
257 drawnTitle, drawnWidth,
259 drawnTitle = elidedValues.string;
260 drawnWidth = elidedValues.width;
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);
273 drawSlices: drawSlices,
274 drawInstantSlicesAsLines: drawInstantSlicesAsLines,
275 drawLabels: drawLabels,
278 drawTriangle: drawTriangle,
279 drawArrow: drawArrow,
281 elidedTitleCache_: elidedTitleCache