1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// found in the LICENSE file. 4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen/** 7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @fileoverview Renders an array of slices into the provided div, 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * using a child canvas element. Uses a FastRectRenderer to draw only 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * the visible slices. 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */ 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsencr.define('gpu', function() { 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const palletteBase = [ 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen {r: 0x45, g: 0x85, b: 0xaa}, 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen {r: 0xdc, g: 0x73, b: 0xa8}, 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen {r: 0x77, g: 0xb6, b: 0x94}, 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen {r: 0x23, g: 0xae, b: 0x6e}, 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen {r: 0x76, g: 0x5d, b: 0x9e}, 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen {r: 0x48, g: 0xd8, b: 0xfb}, 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen {r: 0xa9, g: 0xd7, b: 0x93}, 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen {r: 0x7c, g: 0x2d, b: 0x52}, 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen {r: 0x69, g: 0xc2, b: 0x75}, 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen {r: 0x76, g: 0xcf, b: 0xee}, 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen {r: 0x3d, g: 0x85, b: 0xd1}, 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen {r: 0x71, g: 0x0b, b: 0x54}]; 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen function brighten(c) { 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return {r: Math.min(255, c.r + Math.floor(c.r * 0.45)), 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen g: Math.min(255, c.g + Math.floor(c.g * 0.45)), 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen b: Math.min(255, c.b + Math.floor(c.b * 0.45))}; 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen function colorToString(c) { 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return 'rgb(' + c.r + ',' + c.g + ',' + c.b + ')'; 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const selectedIdBoost = palletteBase.length; 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const pallette = palletteBase.concat(palletteBase.map(brighten)). 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen map(colorToString); 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var textWidthMap = { }; 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen function quickMeasureText(ctx, text) { 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var w = textWidthMap[text]; 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!w) { 45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen w = ctx.measureText(text).width; 46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen textWidthMap[text] = w; 47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return w; 49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen /** 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Generic base class for timeline tracks 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */ 54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimelineThreadTrack = cr.ui.define('div'); 55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimelineThreadTrack.prototype = { 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen __proto__: HTMLDivElement.prototype, 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen decorate: function() { 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.className = 'timeline-thread-track'; 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen set thread(thread) { 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.thread_ = thread; 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.updateChildTracks_(); 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen set viewport(v) { 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.viewport_ = v; 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (var i = 0; i < this.tracks_.length; i++) 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.tracks_[i].viewport = v; 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.invalidate(); 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen invalidate: function() { 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (this.parentNode) 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.parentNode.invalidate(); 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen onResize: function() { 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (var i = 0; i < this.tracks_.length; i++) 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.tracks_[i].onResize(); 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen get firstCanvas() { 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (this.tracks_.length) 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return this.tracks_[0].firstCanvas; 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return undefined; 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen redraw: function() { 91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (var i = 0; i < this.tracks_.length; i++) 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.tracks_[i].redraw(); 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen updateChildTracks_: function() { 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.textContent = ''; 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.tracks_ = []; 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (this.thread_) { 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (var srI = 0; srI < this.thread_.subRows.length; ++srI) { 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var track = new TimelineSliceTrack(); 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (srI == 0) 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen track.heading = this.thread_.parent.pid + ': ' + 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.thread_.tid + ': '; 105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen else 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen track.heading = ''; 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen track.slices = this.thread_.subRows[srI]; 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen track.viewport = this.viewport_; 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.tracks_.push(track); 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.appendChild(track); 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen /** 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Picks a slice, if any, at a given location. 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {number} wX X location to search at, in worldspace. 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {number} wY Y location to search at, in offset space. 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * offset space. 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {function():*} onHitCallback Callback to call with the slice, 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * if one is found. 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @return {boolean} true if a slice was found, otherwise false. 124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */ 125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pick: function(wX, wY, onHitCallback) { 126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (var i = 0; i < this.tracks_.length; i++) { 127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var track = this.tracks_[i]; 128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (wY >= track.offsetTop && wY < track.offsetTop + track.offsetHeight) 129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return track.pick(wX, onHitCallback); 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen /** 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Finds slices intersecting the given interval. 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {number} loWX Lower X bound of the interval to search, in 137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * worldspace. 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {number} hiWX Upper X bound of the interval to search, in 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * worldspace. 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {number} loY Lower Y bound of the interval to search, in 141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * offset space. 142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {number} hiY Upper Y bound of the interval to search, in 143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * offset space. 144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {function():*} onHitCallback Function to call for each slice 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * intersecting the interval. 146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */ 147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pickRange: function(loWX, hiWX, loY, hiY, onHitCallback) { 148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (var i = 0; i < this.tracks_.length; i++) { 149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var a = Math.max(loY, this.tracks_[i].offsetTop); 150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var b = Math.min(hiY, this.tracks_[i].offsetTop + 151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.tracks_[i].offsetHeight); 152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (a <= b) 153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.tracks_[i].pickRange(loWX, hiWX, loY, hiY, onHitCallback); 154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }; 157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen /** 159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Creates a new timeline track div element 160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @constructor 161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @extends {HTMLDivElement} 162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */ 163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimelineSliceTrack = cr.ui.define('div'); 164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimelineSliceTrack.prototype = { 166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen __proto__: HTMLDivElement.prototype, 167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen decorate: function() { 169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.className = 'timeline-slice-track'; 170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.slices_ = null; 171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.titleDiv_ = document.createElement('div'); 173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.titleDiv_.className = 'timeline-slice-track-title'; 174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.appendChild(this.titleDiv_); 175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.canvasContainer_ = document.createElement('div'); 177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.canvasContainer_.className = 'timeline-slice-track-canvas-container'; 178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.appendChild(this.canvasContainer_); 179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.canvas_ = document.createElement('canvas'); 180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.canvas_.className = 'timeline-slice-track-canvas'; 181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.canvasContainer_.appendChild(this.canvas_); 182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.ctx_ = this.canvas_.getContext('2d'); 184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen set heading(text) { 187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.titleDiv_.textContent = text; 188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen set slices(slices) { 191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.slices_ = slices; 192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.invalidate(); 193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen set viewport(v) { 196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.viewport_ = v; 197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.invalidate(); 198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen invalidate: function() { 201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (this.parentNode) 202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.parentNode.invalidate(); 203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen get firstCanvas() { 206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return this.canvas_; 207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen onResize: function() { 210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.canvas_.width = this.canvasContainer_.clientWidth; 211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.canvas_.height = this.canvasContainer_.clientHeight; 212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.invalidate(); 213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen redraw: function() { 216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!this.viewport_) 217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var ctx = this.ctx_; 219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var canvasW = this.canvas_.width; 220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var canvasH = this.canvas_.height; 221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ctx.clearRect(0, 0, canvasW, canvasH); 223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // culling... 225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var vp = this.viewport_; 226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var pixWidth = vp.xViewVectorToWorld(1); 227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var viewLWorld = vp.xViewToWorld(0); 228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var viewRWorld = vp.xViewToWorld(this.width); 229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // begin rendering in world space 231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ctx.save(); 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen vp.applyTransformToCanavs(ctx); 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // tracks 235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var tr = new gpu.FastRectRenderer(ctx, viewLWorld, 2 * pixWidth, 236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2 * pixWidth, viewRWorld, pallette); 237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tr.setYandH(0, canvasH); 238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var slices = this.slices_; 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (var i = 0; i < slices.length; ++i) { 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var slice = slices[i]; 241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var x = slice.start; 242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var w = slice.duration; 243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var colorId; 244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen colorId = slice.selected ? 245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen slice.colorId + selectedIdBoost : 246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen slice.colorId; 247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (w < pixWidth) 249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen w = pixWidth; 250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tr.fillRect(x, w, colorId); 251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tr.flush(); 253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ctx.restore(); 254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // labels 256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ctx.textAlign = 'center'; 257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ctx.textBaseline = 'top'; 258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ctx.font = '10px sans-serif'; 259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ctx.strokeStyle = 'rgb(0,0,0)'; 260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ctx.fillStyle = 'rgb(0,0,0)'; 261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var quickDiscardThresshold = pixWidth * 20; // dont render until 20px wide 262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (var i = 0; i < slices.length; ++i) { 263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var slice = slices[i]; 264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (slice.duration > quickDiscardThresshold) { 265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var labelWidth = quickMeasureText(ctx, slice.title) + 2; 266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var labelWidthWorld = pixWidth * labelWidth; 267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (labelWidthWorld < slice.duration) { 268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var cX = vp.xWorldToView(slice.start + 0.5 * slice.duration); 269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ctx.fillText(slice.title, cX, 2.5); 270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen /** 276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Picks a slice, if any, at a given location. 277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {number} wX X location to search at, in worldspace. 278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {number} wY Y location to search at, in offset space. 279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * offset space. 280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {function():*} onHitCallback Callback to call with the slice, 281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * if one is found. 282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @return {boolean} true if a slice was found, otherwise false. 283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */ 284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pick: function(wX, wY, onHitCallback) { 285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (wY < this.offsetTop || wY >= this.offsetTop + this.offsetHeight) 286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var x = gpu.findLowIndexInSortedIntervals(this.slices_, 288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen function(x) { return x.start; }, 289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen function(x) { return x.duration; }, 290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen wX); 291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (x >= 0 && x < this.slices_.length) { 292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen onHitCallback('slice', this, this.slices_[x]); 293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen /** 299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Finds slices intersecting the given interval. 300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {number} loWX Lower X bound of the interval to search, in 301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * worldspace. 302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {number} hiWX Upper X bound of the interval to search, in 303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * worldspace. 304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {number} loY Lower Y bound of the interval to search, in 305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * offset space. 306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {number} hiY Upper Y bound of the interval to search, in 307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * offset space. 308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {function():*} onHitCallback Function to call for each slice 309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * intersecting the interval. 310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */ 311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen pickRange: function(loWX, hiWX, loY, hiY, onHitCallback) { 312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var a = Math.max(loY, this.offsetTop); 313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var b = Math.min(hiY, this.offsetTop + this.offsetHeight); 314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (a > b) 315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen function onPickHit(slice) { 318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen onHitCallback('slice', this, slice); 319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gpu.iterateOverIntersectingIntervals(this.slices_, 321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen function(x) { return x.start; }, 322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen function(x) { return x.duration; }, 323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen loWX, hiWX, 324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen onPickHit); 325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }; 328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return { 330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimelineSliceTrack: TimelineSliceTrack, 331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimelineThreadTrack: TimelineThreadTrack 332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }; 333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}); 334