| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| 11 * copyright notice, this list of conditions and the following disclaimer | 11 * copyright notice, this list of conditions and the following disclaimer |
| 12 * in the documentation and/or other materials provided with the | 12 * in the documentation and/or other materials provided with the |
| 13 * distribution. | 13 * distribution. |
| 14 * * Neither the name of Google Inc. nor the names of its | 14 * * Neither the name of Google Inc. nor the names of its |
| 15 * contributors may be used to endorse or promote products derived from | 15 * contributors may be used to endorse or promote products derived from |
| 16 * this software without specific prior written permission. | 16 * this software without specific prior written permission. |
| 17 * | 17 * |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | |
| 31 /** | 30 /** |
| 32 * @constructor | 31 * @unrestricted |
| 33 * @param {function(string=)} showImageCallback | |
| 34 * @extends {WebInspector.HBox} | |
| 35 */ | 32 */ |
| 36 WebInspector.PaintProfilerView = function(showImageCallback) | 33 WebInspector.PaintProfilerView = class extends WebInspector.HBox { |
| 37 { | 34 /** |
| 38 WebInspector.HBox.call(this, true); | 35 * @param {function(string=)} showImageCallback |
| 39 this.registerRequiredCSS("layer_viewer/paintProfiler.css"); | 36 */ |
| 40 this.contentElement.classList.add("paint-profiler-overview"); | 37 constructor(showImageCallback) { |
| 41 this._canvasContainer = this.contentElement.createChild("div", "paint-profil
er-canvas-container"); | 38 super(true); |
| 42 this._progressBanner = this.contentElement.createChild("div", "full-widget-d
immed-banner hidden"); | 39 this.registerRequiredCSS('layer_viewer/paintProfiler.css'); |
| 43 this._progressBanner.textContent = WebInspector.UIString("Profiling\u2026"); | 40 this.contentElement.classList.add('paint-profiler-overview'); |
| 41 this._canvasContainer = this.contentElement.createChild('div', 'paint-profil
er-canvas-container'); |
| 42 this._progressBanner = this.contentElement.createChild('div', 'full-widget-d
immed-banner hidden'); |
| 43 this._progressBanner.textContent = WebInspector.UIString('Profiling\u2026'); |
| 44 this._pieChart = new WebInspector.PieChart(55, this._formatPieChartTime.bind
(this), true); | 44 this._pieChart = new WebInspector.PieChart(55, this._formatPieChartTime.bind
(this), true); |
| 45 this._pieChart.element.classList.add("paint-profiler-pie-chart"); | 45 this._pieChart.element.classList.add('paint-profiler-pie-chart'); |
| 46 this.contentElement.appendChild(this._pieChart.element); | 46 this.contentElement.appendChild(this._pieChart.element); |
| 47 | 47 |
| 48 this._showImageCallback = showImageCallback; | 48 this._showImageCallback = showImageCallback; |
| 49 | 49 |
| 50 this._canvas = this._canvasContainer.createChild("canvas", "fill"); | 50 this._canvas = this._canvasContainer.createChild('canvas', 'fill'); |
| 51 this._context = this._canvas.getContext("2d"); | 51 this._context = this._canvas.getContext('2d'); |
| 52 this._selectionWindow = new WebInspector.OverviewGrid.Window(this._canvasCon
tainer); | 52 this._selectionWindow = new WebInspector.OverviewGrid.Window(this._canvasCon
tainer); |
| 53 this._selectionWindow.addEventListener(WebInspector.OverviewGrid.Events.Wind
owChanged, this._onWindowChanged, this); | 53 this._selectionWindow.addEventListener(WebInspector.OverviewGrid.Events.Wind
owChanged, this._onWindowChanged, this); |
| 54 | 54 |
| 55 this._innerBarWidth = 4 * window.devicePixelRatio; | 55 this._innerBarWidth = 4 * window.devicePixelRatio; |
| 56 this._minBarHeight = window.devicePixelRatio; | 56 this._minBarHeight = window.devicePixelRatio; |
| 57 this._barPaddingWidth = 2 * window.devicePixelRatio; | 57 this._barPaddingWidth = 2 * window.devicePixelRatio; |
| 58 this._outerBarWidth = this._innerBarWidth + this._barPaddingWidth; | 58 this._outerBarWidth = this._innerBarWidth + this._barPaddingWidth; |
| 59 this._pendingScale = 1; | 59 this._pendingScale = 1; |
| 60 this._scale = this._pendingScale; | 60 this._scale = this._pendingScale; |
| 61 | 61 |
| 62 this._reset(); | 62 this._reset(); |
| 63 } |
| 64 |
| 65 /** |
| 66 * @return {!Object.<string, !WebInspector.PaintProfilerCategory>} |
| 67 */ |
| 68 static categories() { |
| 69 if (WebInspector.PaintProfilerView._categories) |
| 70 return WebInspector.PaintProfilerView._categories; |
| 71 WebInspector.PaintProfilerView._categories = { |
| 72 shapes: new WebInspector.PaintProfilerCategory('shapes', WebInspector.UISt
ring('Shapes'), 'rgb(255, 161, 129)'), |
| 73 bitmap: new WebInspector.PaintProfilerCategory('bitmap', WebInspector.UISt
ring('Bitmap'), 'rgb(136, 196, 255)'), |
| 74 text: new WebInspector.PaintProfilerCategory('text', WebInspector.UIString
('Text'), 'rgb(180, 255, 137)'), |
| 75 misc: new WebInspector.PaintProfilerCategory('misc', WebInspector.UIString
('Misc'), 'rgb(206, 160, 255)') |
| 76 }; |
| 77 return WebInspector.PaintProfilerView._categories; |
| 78 } |
| 79 |
| 80 /** |
| 81 * @return {!Object.<string, !WebInspector.PaintProfilerCategory>} |
| 82 */ |
| 83 static _initLogItemCategories() { |
| 84 if (WebInspector.PaintProfilerView._logItemCategoriesMap) |
| 85 return WebInspector.PaintProfilerView._logItemCategoriesMap; |
| 86 |
| 87 var categories = WebInspector.PaintProfilerView.categories(); |
| 88 |
| 89 var logItemCategories = {}; |
| 90 logItemCategories['Clear'] = categories['misc']; |
| 91 logItemCategories['DrawPaint'] = categories['misc']; |
| 92 logItemCategories['DrawData'] = categories['misc']; |
| 93 logItemCategories['SetMatrix'] = categories['misc']; |
| 94 logItemCategories['PushCull'] = categories['misc']; |
| 95 logItemCategories['PopCull'] = categories['misc']; |
| 96 logItemCategories['Translate'] = categories['misc']; |
| 97 logItemCategories['Scale'] = categories['misc']; |
| 98 logItemCategories['Concat'] = categories['misc']; |
| 99 logItemCategories['Restore'] = categories['misc']; |
| 100 logItemCategories['SaveLayer'] = categories['misc']; |
| 101 logItemCategories['Save'] = categories['misc']; |
| 102 logItemCategories['BeginCommentGroup'] = categories['misc']; |
| 103 logItemCategories['AddComment'] = categories['misc']; |
| 104 logItemCategories['EndCommentGroup'] = categories['misc']; |
| 105 logItemCategories['ClipRect'] = categories['misc']; |
| 106 logItemCategories['ClipRRect'] = categories['misc']; |
| 107 logItemCategories['ClipPath'] = categories['misc']; |
| 108 logItemCategories['ClipRegion'] = categories['misc']; |
| 109 logItemCategories['DrawPoints'] = categories['shapes']; |
| 110 logItemCategories['DrawRect'] = categories['shapes']; |
| 111 logItemCategories['DrawOval'] = categories['shapes']; |
| 112 logItemCategories['DrawRRect'] = categories['shapes']; |
| 113 logItemCategories['DrawPath'] = categories['shapes']; |
| 114 logItemCategories['DrawVertices'] = categories['shapes']; |
| 115 logItemCategories['DrawDRRect'] = categories['shapes']; |
| 116 logItemCategories['DrawBitmap'] = categories['bitmap']; |
| 117 logItemCategories['DrawBitmapRectToRect'] = categories['bitmap']; |
| 118 logItemCategories['DrawBitmapMatrix'] = categories['bitmap']; |
| 119 logItemCategories['DrawBitmapNine'] = categories['bitmap']; |
| 120 logItemCategories['DrawSprite'] = categories['bitmap']; |
| 121 logItemCategories['DrawPicture'] = categories['bitmap']; |
| 122 logItemCategories['DrawText'] = categories['text']; |
| 123 logItemCategories['DrawPosText'] = categories['text']; |
| 124 logItemCategories['DrawPosTextH'] = categories['text']; |
| 125 logItemCategories['DrawTextOnPath'] = categories['text']; |
| 126 |
| 127 WebInspector.PaintProfilerView._logItemCategoriesMap = logItemCategories; |
| 128 return logItemCategories; |
| 129 } |
| 130 |
| 131 /** |
| 132 * @param {!Object} logItem |
| 133 * @return {!WebInspector.PaintProfilerCategory} |
| 134 */ |
| 135 static _categoryForLogItem(logItem) { |
| 136 var method = logItem.method.toTitleCase(); |
| 137 |
| 138 var logItemCategories = WebInspector.PaintProfilerView._initLogItemCategorie
s(); |
| 139 var result = logItemCategories[method]; |
| 140 if (!result) { |
| 141 result = WebInspector.PaintProfilerView.categories()['misc']; |
| 142 logItemCategories[method] = result; |
| 143 } |
| 144 return result; |
| 145 } |
| 146 |
| 147 /** |
| 148 * @override |
| 149 */ |
| 150 onResize() { |
| 151 this._update(); |
| 152 } |
| 153 |
| 154 /** |
| 155 * @param {?WebInspector.PaintProfilerSnapshot} snapshot |
| 156 * @param {!Array.<!WebInspector.PaintProfilerLogItem>} log |
| 157 * @param {?DOMAgent.Rect} clipRect |
| 158 */ |
| 159 setSnapshotAndLog(snapshot, log, clipRect) { |
| 160 this._reset(); |
| 161 this._snapshot = snapshot; |
| 162 if (this._snapshot) |
| 163 this._snapshot.addReference(); |
| 164 this._log = log; |
| 165 this._logCategories = this._log.map(WebInspector.PaintProfilerView._category
ForLogItem); |
| 166 |
| 167 if (!this._snapshot) { |
| 168 this._update(); |
| 169 this._pieChart.setTotal(0); |
| 170 this._selectionWindow.setEnabled(false); |
| 171 return; |
| 172 } |
| 173 this._selectionWindow.setEnabled(true); |
| 174 this._progressBanner.classList.remove('hidden'); |
| 175 this._updateImage(); |
| 176 snapshot.profile(clipRect, onProfileDone.bind(this)); |
| 177 /** |
| 178 * @param {!Array.<!LayerTreeAgent.PaintProfile>=} profiles |
| 179 * @this {WebInspector.PaintProfilerView} |
| 180 */ |
| 181 function onProfileDone(profiles) { |
| 182 this._progressBanner.classList.add('hidden'); |
| 183 this._profiles = profiles; |
| 184 this._update(); |
| 185 this._updatePieChart(); |
| 186 } |
| 187 } |
| 188 |
| 189 /** |
| 190 * @param {number} scale |
| 191 */ |
| 192 setScale(scale) { |
| 193 var needsUpdate = scale > this._scale; |
| 194 var predictiveGrowthFactor = 2; |
| 195 this._pendingScale = Math.min(1, scale * predictiveGrowthFactor); |
| 196 if (needsUpdate && this._snapshot) |
| 197 this._updateImage(); |
| 198 } |
| 199 |
| 200 _update() { |
| 201 this._canvas.width = this._canvasContainer.clientWidth * window.devicePixelR
atio; |
| 202 this._canvas.height = this._canvasContainer.clientHeight * window.devicePixe
lRatio; |
| 203 this._samplesPerBar = 0; |
| 204 if (!this._profiles || !this._profiles.length) |
| 205 return; |
| 206 |
| 207 var maxBars = Math.floor((this._canvas.width - 2 * this._barPaddingWidth) /
this._outerBarWidth); |
| 208 var sampleCount = this._log.length; |
| 209 this._samplesPerBar = Math.ceil(sampleCount / maxBars); |
| 210 |
| 211 var maxBarTime = 0; |
| 212 var barTimes = []; |
| 213 var barHeightByCategory = []; |
| 214 var heightByCategory = {}; |
| 215 for (var i = 0, lastBarIndex = 0, lastBarTime = 0; i < sampleCount;) { |
| 216 var categoryName = (this._logCategories[i] && this._logCategories[i].name)
|| 'misc'; |
| 217 var sampleIndex = this._log[i].commandIndex; |
| 218 for (var row = 0; row < this._profiles.length; row++) { |
| 219 var sample = this._profiles[row][sampleIndex]; |
| 220 lastBarTime += sample; |
| 221 heightByCategory[categoryName] = (heightByCategory[categoryName] || 0) +
sample; |
| 222 } |
| 223 ++i; |
| 224 if (i - lastBarIndex === this._samplesPerBar || i === sampleCount) { |
| 225 // Normalize by total number of samples accumulated. |
| 226 var factor = this._profiles.length * (i - lastBarIndex); |
| 227 lastBarTime /= factor; |
| 228 for (categoryName in heightByCategory) |
| 229 heightByCategory[categoryName] /= factor; |
| 230 |
| 231 barTimes.push(lastBarTime); |
| 232 barHeightByCategory.push(heightByCategory); |
| 233 |
| 234 if (lastBarTime > maxBarTime) |
| 235 maxBarTime = lastBarTime; |
| 236 lastBarTime = 0; |
| 237 heightByCategory = {}; |
| 238 lastBarIndex = i; |
| 239 } |
| 240 } |
| 241 |
| 242 const paddingHeight = 4 * window.devicePixelRatio; |
| 243 var scale = (this._canvas.height - paddingHeight - this._minBarHeight) / max
BarTime; |
| 244 for (var i = 0; i < barTimes.length; ++i) { |
| 245 for (var categoryName in barHeightByCategory[i]) |
| 246 barHeightByCategory[i][categoryName] *= (barTimes[i] * scale + this._min
BarHeight) / barTimes[i]; |
| 247 this._renderBar(i, barHeightByCategory[i]); |
| 248 } |
| 249 } |
| 250 |
| 251 /** |
| 252 * @param {number} index |
| 253 * @param {!Object.<string, number>} heightByCategory |
| 254 */ |
| 255 _renderBar(index, heightByCategory) { |
| 256 var categories = WebInspector.PaintProfilerView.categories(); |
| 257 var currentHeight = 0; |
| 258 var x = this._barPaddingWidth + index * this._outerBarWidth; |
| 259 for (var categoryName in categories) { |
| 260 if (!heightByCategory[categoryName]) |
| 261 continue; |
| 262 currentHeight += heightByCategory[categoryName]; |
| 263 var y = this._canvas.height - currentHeight; |
| 264 this._context.fillStyle = categories[categoryName].color; |
| 265 this._context.fillRect(x, y, this._innerBarWidth, heightByCategory[categor
yName]); |
| 266 } |
| 267 } |
| 268 |
| 269 _onWindowChanged() { |
| 270 this.dispatchEventToListeners(WebInspector.PaintProfilerView.Events.WindowCh
anged); |
| 271 this._updatePieChart(); |
| 272 if (this._updateImageTimer) |
| 273 return; |
| 274 this._updateImageTimer = setTimeout(this._updateImage.bind(this), 100); |
| 275 } |
| 276 |
| 277 _updatePieChart() { |
| 278 var window = this.selectionWindow(); |
| 279 if (!this._profiles || !this._profiles.length || !window) |
| 280 return; |
| 281 var totalTime = 0; |
| 282 var timeByCategory = {}; |
| 283 for (var i = window.left; i < window.right; ++i) { |
| 284 var logEntry = this._log[i]; |
| 285 var category = WebInspector.PaintProfilerView._categoryForLogItem(logEntry
); |
| 286 timeByCategory[category.color] = timeByCategory[category.color] || 0; |
| 287 for (var j = 0; j < this._profiles.length; ++j) { |
| 288 var time = this._profiles[j][logEntry.commandIndex]; |
| 289 totalTime += time; |
| 290 timeByCategory[category.color] += time; |
| 291 } |
| 292 } |
| 293 this._pieChart.setTotal(totalTime / this._profiles.length); |
| 294 for (var color in timeByCategory) |
| 295 this._pieChart.addSlice(timeByCategory[color] / this._profiles.length, col
or); |
| 296 } |
| 297 |
| 298 /** |
| 299 * @param {number} value |
| 300 * @return {string} |
| 301 */ |
| 302 _formatPieChartTime(value) { |
| 303 return Number.millisToString(value * 1000, true); |
| 304 } |
| 305 |
| 306 /** |
| 307 * @return {?{left: number, right: number}} |
| 308 */ |
| 309 selectionWindow() { |
| 310 if (!this._log) |
| 311 return null; |
| 312 |
| 313 var screenLeft = this._selectionWindow.windowLeft * this._canvas.width; |
| 314 var screenRight = this._selectionWindow.windowRight * this._canvas.width; |
| 315 var barLeft = Math.floor(screenLeft / this._outerBarWidth); |
| 316 var barRight = Math.floor((screenRight + this._innerBarWidth - this._barPadd
ingWidth / 2) / this._outerBarWidth); |
| 317 var stepLeft = Number.constrain(barLeft * this._samplesPerBar, 0, this._log.
length - 1); |
| 318 var stepRight = Number.constrain(barRight * this._samplesPerBar, 0, this._lo
g.length); |
| 319 |
| 320 return {left: stepLeft, right: stepRight}; |
| 321 } |
| 322 |
| 323 _updateImage() { |
| 324 delete this._updateImageTimer; |
| 325 var left = null; |
| 326 var right = null; |
| 327 var window = this.selectionWindow(); |
| 328 if (this._profiles && this._profiles.length && window) { |
| 329 left = this._log[window.left].commandIndex; |
| 330 right = this._log[window.right - 1].commandIndex; |
| 331 } |
| 332 var scale = this._pendingScale; |
| 333 this._snapshot.replay(left, right, scale).then(image => { |
| 334 if (!image) |
| 335 return; |
| 336 this._scale = scale; |
| 337 this._showImageCallback(image); |
| 338 }); |
| 339 } |
| 340 |
| 341 _reset() { |
| 342 if (this._snapshot) |
| 343 this._snapshot.release(); |
| 344 this._snapshot = null; |
| 345 this._profiles = null; |
| 346 this._selectionWindow.reset(); |
| 347 this._selectionWindow.setEnabled(false); |
| 348 } |
| 63 }; | 349 }; |
| 64 | 350 |
| 65 /** @enum {symbol} */ | 351 /** @enum {symbol} */ |
| 66 WebInspector.PaintProfilerView.Events = { | 352 WebInspector.PaintProfilerView.Events = { |
| 67 WindowChanged: Symbol("WindowChanged") | 353 WindowChanged: Symbol('WindowChanged') |
| 68 }; | 354 }; |
| 69 | 355 |
| 70 WebInspector.PaintProfilerView.prototype = { | |
| 71 onResize: function() | |
| 72 { | |
| 73 this._update(); | |
| 74 }, | |
| 75 | |
| 76 /** | |
| 77 * @param {?WebInspector.PaintProfilerSnapshot} snapshot | |
| 78 * @param {!Array.<!WebInspector.PaintProfilerLogItem>} log | |
| 79 * @param {?DOMAgent.Rect} clipRect | |
| 80 */ | |
| 81 setSnapshotAndLog: function(snapshot, log, clipRect) | |
| 82 { | |
| 83 this._reset(); | |
| 84 this._snapshot = snapshot; | |
| 85 if (this._snapshot) | |
| 86 this._snapshot.addReference(); | |
| 87 this._log = log; | |
| 88 this._logCategories = this._log.map(WebInspector.PaintProfilerView._cate
goryForLogItem); | |
| 89 | |
| 90 if (!this._snapshot) { | |
| 91 this._update(); | |
| 92 this._pieChart.setTotal(0); | |
| 93 this._selectionWindow.setEnabled(false); | |
| 94 return; | |
| 95 } | |
| 96 this._selectionWindow.setEnabled(true); | |
| 97 this._progressBanner.classList.remove("hidden"); | |
| 98 this._updateImage(); | |
| 99 snapshot.profile(clipRect, onProfileDone.bind(this)); | |
| 100 /** | |
| 101 * @param {!Array.<!LayerTreeAgent.PaintProfile>=} profiles | |
| 102 * @this {WebInspector.PaintProfilerView} | |
| 103 */ | |
| 104 function onProfileDone(profiles) | |
| 105 { | |
| 106 this._progressBanner.classList.add("hidden"); | |
| 107 this._profiles = profiles; | |
| 108 this._update(); | |
| 109 this._updatePieChart(); | |
| 110 } | |
| 111 }, | |
| 112 | |
| 113 /** | |
| 114 * @param {number} scale | |
| 115 */ | |
| 116 setScale: function(scale) | |
| 117 { | |
| 118 var needsUpdate = scale > this._scale; | |
| 119 var predictiveGrowthFactor = 2; | |
| 120 this._pendingScale = Math.min(1, scale * predictiveGrowthFactor); | |
| 121 if (needsUpdate && this._snapshot) | |
| 122 this._updateImage(); | |
| 123 }, | |
| 124 | |
| 125 _update: function() | |
| 126 { | |
| 127 this._canvas.width = this._canvasContainer.clientWidth * window.devicePi
xelRatio; | |
| 128 this._canvas.height = this._canvasContainer.clientHeight * window.device
PixelRatio; | |
| 129 this._samplesPerBar = 0; | |
| 130 if (!this._profiles || !this._profiles.length) | |
| 131 return; | |
| 132 | |
| 133 var maxBars = Math.floor((this._canvas.width - 2 * this._barPaddingWidth
) / this._outerBarWidth); | |
| 134 var sampleCount = this._log.length; | |
| 135 this._samplesPerBar = Math.ceil(sampleCount / maxBars); | |
| 136 | |
| 137 var maxBarTime = 0; | |
| 138 var barTimes = []; | |
| 139 var barHeightByCategory = []; | |
| 140 var heightByCategory = {}; | |
| 141 for (var i = 0, lastBarIndex = 0, lastBarTime = 0; i < sampleCount;) { | |
| 142 var categoryName = (this._logCategories[i] && this._logCategories[i]
.name) || "misc"; | |
| 143 var sampleIndex = this._log[i].commandIndex; | |
| 144 for (var row = 0; row < this._profiles.length; row++) { | |
| 145 var sample = this._profiles[row][sampleIndex]; | |
| 146 lastBarTime += sample; | |
| 147 heightByCategory[categoryName] = (heightByCategory[categoryName]
|| 0) + sample; | |
| 148 } | |
| 149 ++i; | |
| 150 if (i - lastBarIndex === this._samplesPerBar || i === sampleCount) { | |
| 151 // Normalize by total number of samples accumulated. | |
| 152 var factor = this._profiles.length * (i - lastBarIndex); | |
| 153 lastBarTime /= factor; | |
| 154 for (categoryName in heightByCategory) | |
| 155 heightByCategory[categoryName] /= factor; | |
| 156 | |
| 157 barTimes.push(lastBarTime); | |
| 158 barHeightByCategory.push(heightByCategory); | |
| 159 | |
| 160 if (lastBarTime > maxBarTime) | |
| 161 maxBarTime = lastBarTime; | |
| 162 lastBarTime = 0; | |
| 163 heightByCategory = {}; | |
| 164 lastBarIndex = i; | |
| 165 } | |
| 166 } | |
| 167 | |
| 168 const paddingHeight = 4 * window.devicePixelRatio; | |
| 169 var scale = (this._canvas.height - paddingHeight - this._minBarHeight) /
maxBarTime; | |
| 170 for (var i = 0; i < barTimes.length; ++i) { | |
| 171 for (var categoryName in barHeightByCategory[i]) | |
| 172 barHeightByCategory[i][categoryName] *= (barTimes[i] * scale + t
his._minBarHeight) / barTimes[i]; | |
| 173 this._renderBar(i, barHeightByCategory[i]); | |
| 174 } | |
| 175 }, | |
| 176 | |
| 177 /** | |
| 178 * @param {number} index | |
| 179 * @param {!Object.<string, number>} heightByCategory | |
| 180 */ | |
| 181 _renderBar: function(index, heightByCategory) | |
| 182 { | |
| 183 var categories = WebInspector.PaintProfilerView.categories(); | |
| 184 var currentHeight = 0; | |
| 185 var x = this._barPaddingWidth + index * this._outerBarWidth; | |
| 186 for (var categoryName in categories) { | |
| 187 if (!heightByCategory[categoryName]) | |
| 188 continue; | |
| 189 currentHeight += heightByCategory[categoryName]; | |
| 190 var y = this._canvas.height - currentHeight; | |
| 191 this._context.fillStyle = categories[categoryName].color; | |
| 192 this._context.fillRect(x, y, this._innerBarWidth, heightByCategory[c
ategoryName]); | |
| 193 } | |
| 194 }, | |
| 195 | |
| 196 _onWindowChanged: function() | |
| 197 { | |
| 198 this.dispatchEventToListeners(WebInspector.PaintProfilerView.Events.Wind
owChanged); | |
| 199 this._updatePieChart(); | |
| 200 if (this._updateImageTimer) | |
| 201 return; | |
| 202 this._updateImageTimer = setTimeout(this._updateImage.bind(this), 100); | |
| 203 }, | |
| 204 | |
| 205 _updatePieChart: function() | |
| 206 { | |
| 207 var window = this.selectionWindow(); | |
| 208 if (!this._profiles || !this._profiles.length || !window) | |
| 209 return; | |
| 210 var totalTime = 0; | |
| 211 var timeByCategory = {}; | |
| 212 for (var i = window.left; i < window.right; ++i) { | |
| 213 var logEntry = this._log[i]; | |
| 214 var category = WebInspector.PaintProfilerView._categoryForLogItem(lo
gEntry); | |
| 215 timeByCategory[category.color] = timeByCategory[category.color] || 0
; | |
| 216 for (var j = 0; j < this._profiles.length; ++j) { | |
| 217 var time = this._profiles[j][logEntry.commandIndex]; | |
| 218 totalTime += time; | |
| 219 timeByCategory[category.color] += time; | |
| 220 } | |
| 221 } | |
| 222 this._pieChart.setTotal(totalTime / this._profiles.length); | |
| 223 for (var color in timeByCategory) | |
| 224 this._pieChart.addSlice(timeByCategory[color] / this._profiles.lengt
h, color); | |
| 225 }, | |
| 226 | |
| 227 /** | |
| 228 * @param {number} value | |
| 229 * @return {string} | |
| 230 */ | |
| 231 _formatPieChartTime: function(value) | |
| 232 { | |
| 233 return Number.millisToString(value * 1000, true); | |
| 234 }, | |
| 235 | |
| 236 /** | |
| 237 * @return {?{left: number, right: number}} | |
| 238 */ | |
| 239 selectionWindow: function() | |
| 240 { | |
| 241 if (!this._log) | |
| 242 return null; | |
| 243 | |
| 244 var screenLeft = this._selectionWindow.windowLeft * this._canvas.width; | |
| 245 var screenRight = this._selectionWindow.windowRight * this._canvas.width
; | |
| 246 var barLeft = Math.floor(screenLeft / this._outerBarWidth); | |
| 247 var barRight = Math.floor((screenRight + this._innerBarWidth - this._bar
PaddingWidth / 2) / this._outerBarWidth); | |
| 248 var stepLeft = Number.constrain(barLeft * this._samplesPerBar, 0, this._
log.length - 1); | |
| 249 var stepRight = Number.constrain(barRight * this._samplesPerBar, 0, this
._log.length); | |
| 250 | |
| 251 return { left: stepLeft, right: stepRight }; | |
| 252 }, | |
| 253 | |
| 254 _updateImage: function() | |
| 255 { | |
| 256 delete this._updateImageTimer; | |
| 257 var left = null; | |
| 258 var right = null; | |
| 259 var window = this.selectionWindow(); | |
| 260 if (this._profiles && this._profiles.length && window) { | |
| 261 left = this._log[window.left].commandIndex; | |
| 262 right = this._log[window.right - 1].commandIndex; | |
| 263 } | |
| 264 var scale = this._pendingScale; | |
| 265 this._snapshot.replay(left, right, scale).then(image => { | |
| 266 if (!image) | |
| 267 return; | |
| 268 this._scale = scale; | |
| 269 this._showImageCallback(image); | |
| 270 }); | |
| 271 }, | |
| 272 | |
| 273 _reset: function() | |
| 274 { | |
| 275 if (this._snapshot) | |
| 276 this._snapshot.release(); | |
| 277 this._snapshot = null; | |
| 278 this._profiles = null; | |
| 279 this._selectionWindow.reset(); | |
| 280 this._selectionWindow.setEnabled(false); | |
| 281 }, | |
| 282 | |
| 283 __proto__: WebInspector.HBox.prototype | |
| 284 }; | |
| 285 | |
| 286 /** | 356 /** |
| 287 * @constructor | 357 * @unrestricted |
| 288 * @extends {WebInspector.ThrottledWidget} | |
| 289 */ | 358 */ |
| 290 WebInspector.PaintProfilerCommandLogView = function() | 359 WebInspector.PaintProfilerCommandLogView = class extends WebInspector.ThrottledW
idget { |
| 291 { | 360 constructor() { |
| 292 WebInspector.ThrottledWidget.call(this); | 361 super(); |
| 293 this.setMinimumSize(100, 25); | 362 this.setMinimumSize(100, 25); |
| 294 this.element.classList.add("overflow-auto"); | 363 this.element.classList.add('overflow-auto'); |
| 295 | 364 |
| 296 this._treeOutline = new TreeOutlineInShadow(); | 365 this._treeOutline = new TreeOutlineInShadow(); |
| 297 this.element.appendChild(this._treeOutline.element); | 366 this.element.appendChild(this._treeOutline.element); |
| 298 | 367 |
| 299 this._log = []; | 368 this._log = []; |
| 369 } |
| 370 |
| 371 /** |
| 372 * @param {?WebInspector.Target} target |
| 373 * @param {!Array.<!WebInspector.PaintProfilerLogItem>} log |
| 374 */ |
| 375 setCommandLog(target, log) { |
| 376 this._target = target; |
| 377 this._log = log; |
| 378 /** @type {!Map<!WebInspector.PaintProfilerLogItem>} */ |
| 379 this._treeItemCache = new Map(); |
| 380 this.updateWindow({left: 0, right: this._log.length}); |
| 381 } |
| 382 |
| 383 /** |
| 384 * @param {!WebInspector.PaintProfilerLogItem} logItem |
| 385 */ |
| 386 _appendLogItem(logItem) { |
| 387 var treeElement = this._treeItemCache.get(logItem); |
| 388 if (!treeElement) { |
| 389 treeElement = new WebInspector.LogTreeElement(this, logItem); |
| 390 this._treeItemCache.set(logItem, treeElement); |
| 391 } else if (treeElement.parent) { |
| 392 return; |
| 393 } |
| 394 this._treeOutline.appendChild(treeElement); |
| 395 } |
| 396 |
| 397 /** |
| 398 * @param {?{left: number, right: number}} selectionWindow |
| 399 */ |
| 400 updateWindow(selectionWindow) { |
| 401 this._selectionWindow = selectionWindow; |
| 402 this.update(); |
| 403 } |
| 404 |
| 405 /** |
| 406 * @override |
| 407 * @return {!Promise<*>} |
| 408 */ |
| 409 doUpdate() { |
| 410 if (!this._selectionWindow || !this._log.length) { |
| 411 this._treeOutline.removeChildren(); |
| 412 return Promise.resolve(); |
| 413 } |
| 414 var root = this._treeOutline.rootElement(); |
| 415 for (;;) { |
| 416 var child = root.firstChild(); |
| 417 if (!child || child._logItem.commandIndex >= this._selectionWindow.left) |
| 418 break; |
| 419 root.removeChildAtIndex(0); |
| 420 } |
| 421 for (;;) { |
| 422 var child = root.lastChild(); |
| 423 if (!child || child._logItem.commandIndex < this._selectionWindow.right) |
| 424 break; |
| 425 root.removeChildAtIndex(root.children().length - 1); |
| 426 } |
| 427 for (var i = this._selectionWindow.left, right = this._selectionWindow.right
; i < right; ++i) |
| 428 this._appendLogItem(this._log[i]); |
| 429 return Promise.resolve(); |
| 430 } |
| 300 }; | 431 }; |
| 301 | 432 |
| 302 WebInspector.PaintProfilerCommandLogView.prototype = { | |
| 303 /** | |
| 304 * @param {?WebInspector.Target} target | |
| 305 * @param {!Array.<!WebInspector.PaintProfilerLogItem>} log | |
| 306 */ | |
| 307 setCommandLog: function(target, log) | |
| 308 { | |
| 309 this._target = target; | |
| 310 this._log = log; | |
| 311 /** @type {!Map<!WebInspector.PaintProfilerLogItem>} */ | |
| 312 this._treeItemCache = new Map(); | |
| 313 this.updateWindow({left: 0, right: this._log.length}); | |
| 314 }, | |
| 315 | |
| 316 /** | |
| 317 * @param {!WebInspector.PaintProfilerLogItem} logItem | |
| 318 */ | |
| 319 _appendLogItem: function(logItem) | |
| 320 { | |
| 321 var treeElement = this._treeItemCache.get(logItem); | |
| 322 if (!treeElement) { | |
| 323 treeElement = new WebInspector.LogTreeElement(this, logItem); | |
| 324 this._treeItemCache.set(logItem, treeElement); | |
| 325 } else if (treeElement.parent) { | |
| 326 return; | |
| 327 } | |
| 328 this._treeOutline.appendChild(treeElement); | |
| 329 }, | |
| 330 | |
| 331 /** | |
| 332 * @param {?{left: number, right: number}} selectionWindow | |
| 333 */ | |
| 334 updateWindow: function(selectionWindow) | |
| 335 { | |
| 336 this._selectionWindow = selectionWindow; | |
| 337 this.update(); | |
| 338 }, | |
| 339 | |
| 340 /** | |
| 341 * @override | |
| 342 * @return {!Promise<*>} | |
| 343 */ | |
| 344 doUpdate: function() | |
| 345 { | |
| 346 if (!this._selectionWindow || !this._log.length) { | |
| 347 this._treeOutline.removeChildren(); | |
| 348 return Promise.resolve(); | |
| 349 } | |
| 350 var root = this._treeOutline.rootElement(); | |
| 351 for (;;) { | |
| 352 var child = root.firstChild(); | |
| 353 if (!child || child._logItem.commandIndex >= this._selectionWindow.l
eft) | |
| 354 break; | |
| 355 root.removeChildAtIndex(0); | |
| 356 } | |
| 357 for (;;) { | |
| 358 var child = root.lastChild(); | |
| 359 if (!child || child._logItem.commandIndex < this._selectionWindow.ri
ght) | |
| 360 break; | |
| 361 root.removeChildAtIndex(root.children().length - 1); | |
| 362 } | |
| 363 for (var i = this._selectionWindow.left, right = this._selectionWindow.r
ight; i < right; ++i) | |
| 364 this._appendLogItem(this._log[i]); | |
| 365 return Promise.resolve(); | |
| 366 }, | |
| 367 | |
| 368 __proto__: WebInspector.ThrottledWidget.prototype | |
| 369 }; | |
| 370 | |
| 371 /** | 433 /** |
| 372 * @constructor | 434 * @unrestricted |
| 373 * @param {!WebInspector.PaintProfilerCommandLogView} ownerView | 435 */ |
| 374 * @param {!WebInspector.PaintProfilerLogItem} logItem | 436 WebInspector.LogTreeElement = class extends TreeElement { |
| 375 * @extends {TreeElement} | 437 /** |
| 376 */ | 438 * @param {!WebInspector.PaintProfilerCommandLogView} ownerView |
| 377 WebInspector.LogTreeElement = function(ownerView, logItem) | 439 * @param {!WebInspector.PaintProfilerLogItem} logItem |
| 378 { | 440 */ |
| 379 TreeElement.call(this, "", !!logItem.params); | 441 constructor(ownerView, logItem) { |
| 442 super('', !!logItem.params); |
| 380 this._logItem = logItem; | 443 this._logItem = logItem; |
| 381 this._ownerView = ownerView; | 444 this._ownerView = ownerView; |
| 382 this._filled = false; | 445 this._filled = false; |
| 446 } |
| 447 |
| 448 /** |
| 449 * @override |
| 450 */ |
| 451 onattach() { |
| 452 this._update(); |
| 453 } |
| 454 |
| 455 /** |
| 456 * @override |
| 457 */ |
| 458 onpopulate() { |
| 459 for (var param in this._logItem.params) |
| 460 WebInspector.LogPropertyTreeElement._appendLogPropertyItem(this, param, th
is._logItem.params[param]); |
| 461 } |
| 462 |
| 463 /** |
| 464 * @param {*} param |
| 465 * @param {string} name |
| 466 * @return {string} |
| 467 */ |
| 468 _paramToString(param, name) { |
| 469 if (typeof param !== 'object') |
| 470 return typeof param === 'string' && param.length > 100 ? name : JSON.strin
gify(param); |
| 471 var str = ''; |
| 472 var keyCount = 0; |
| 473 for (var key in param) { |
| 474 if (++keyCount > 4 || typeof param[key] === 'object' || |
| 475 (typeof param[key] === 'string' && param[key].length > 100)) |
| 476 return name; |
| 477 if (str) |
| 478 str += ', '; |
| 479 str += param[key]; |
| 480 } |
| 481 return str; |
| 482 } |
| 483 |
| 484 /** |
| 485 * @param {?Object<string, *>} params |
| 486 * @return {string} |
| 487 */ |
| 488 _paramsToString(params) { |
| 489 var str = ''; |
| 490 for (var key in params) { |
| 491 if (str) |
| 492 str += ', '; |
| 493 str += this._paramToString(params[key], key); |
| 494 } |
| 495 return str; |
| 496 } |
| 497 |
| 498 _update() { |
| 499 var title = createDocumentFragment(); |
| 500 title.createTextChild(this._logItem.method + '(' + this._paramsToString(this
._logItem.params) + ')'); |
| 501 this.title = title; |
| 502 } |
| 383 }; | 503 }; |
| 384 | 504 |
| 385 WebInspector.LogTreeElement.prototype = { | |
| 386 onattach: function() | |
| 387 { | |
| 388 this._update(); | |
| 389 }, | |
| 390 | |
| 391 onpopulate: function() | |
| 392 { | |
| 393 for (var param in this._logItem.params) | |
| 394 WebInspector.LogPropertyTreeElement._appendLogPropertyItem(this, par
am, this._logItem.params[param]); | |
| 395 }, | |
| 396 | |
| 397 /** | |
| 398 * @param {*} param | |
| 399 * @param {string} name | |
| 400 * @return {string} | |
| 401 */ | |
| 402 _paramToString: function(param, name) | |
| 403 { | |
| 404 if (typeof param !== "object") | |
| 405 return typeof param === "string" && param.length > 100 ? name : JSON
.stringify(param); | |
| 406 var str = ""; | |
| 407 var keyCount = 0; | |
| 408 for (var key in param) { | |
| 409 if (++keyCount > 4 || typeof param[key] === "object" || (typeof para
m[key] === "string" && param[key].length > 100)) | |
| 410 return name; | |
| 411 if (str) | |
| 412 str += ", "; | |
| 413 str += param[key]; | |
| 414 } | |
| 415 return str; | |
| 416 }, | |
| 417 | |
| 418 /** | |
| 419 * @param {?Object<string, *>} params | |
| 420 * @return {string} | |
| 421 */ | |
| 422 _paramsToString: function(params) | |
| 423 { | |
| 424 var str = ""; | |
| 425 for (var key in params) { | |
| 426 if (str) | |
| 427 str += ", "; | |
| 428 str += this._paramToString(params[key], key); | |
| 429 } | |
| 430 return str; | |
| 431 }, | |
| 432 | |
| 433 _update: function() | |
| 434 { | |
| 435 var title = createDocumentFragment(); | |
| 436 title.createTextChild(this._logItem.method + "(" + this._paramsToString(
this._logItem.params) + ")"); | |
| 437 this.title = title; | |
| 438 }, | |
| 439 | |
| 440 __proto__: TreeElement.prototype | |
| 441 }; | |
| 442 | |
| 443 /** | 505 /** |
| 444 * @constructor | 506 * @unrestricted |
| 445 * @param {!{name: string, value}} property | 507 */ |
| 446 * @extends {TreeElement} | 508 WebInspector.LogPropertyTreeElement = class extends TreeElement { |
| 447 */ | 509 /** |
| 448 WebInspector.LogPropertyTreeElement = function(property) | 510 * @param {!{name: string, value}} property |
| 449 { | 511 */ |
| 450 TreeElement.call(this); | 512 constructor(property) { |
| 513 super(); |
| 451 this._property = property; | 514 this._property = property; |
| 452 }; | 515 } |
| 453 | 516 |
| 454 /** | 517 /** |
| 455 * @param {!TreeElement} element | 518 * @param {!TreeElement} element |
| 456 * @param {string} name | 519 * @param {string} name |
| 457 * @param {*} value | 520 * @param {*} value |
| 458 */ | 521 */ |
| 459 WebInspector.LogPropertyTreeElement._appendLogPropertyItem = function(element, n
ame, value) | 522 static _appendLogPropertyItem(element, name, value) { |
| 460 { | |
| 461 var treeElement = new WebInspector.LogPropertyTreeElement({name: name, value
: value}); | 523 var treeElement = new WebInspector.LogPropertyTreeElement({name: name, value
: value}); |
| 462 element.appendChild(treeElement); | 524 element.appendChild(treeElement); |
| 463 if (value && typeof value === "object") { | 525 if (value && typeof value === 'object') { |
| 464 for (var property in value) | 526 for (var property in value) |
| 465 WebInspector.LogPropertyTreeElement._appendLogPropertyItem(treeEleme
nt, property, value[property]); | 527 WebInspector.LogPropertyTreeElement._appendLogPropertyItem(treeElement,
property, value[property]); |
| 466 } | 528 } |
| 529 } |
| 530 |
| 531 /** |
| 532 * @override |
| 533 */ |
| 534 onattach() { |
| 535 var title = createDocumentFragment(); |
| 536 var nameElement = title.createChild('span', 'name'); |
| 537 nameElement.textContent = this._property.name; |
| 538 var separatorElement = title.createChild('span', 'separator'); |
| 539 separatorElement.textContent = ': '; |
| 540 if (this._property.value === null || typeof this._property.value !== 'object
') { |
| 541 var valueElement = title.createChild('span', 'value'); |
| 542 valueElement.textContent = JSON.stringify(this._property.value); |
| 543 valueElement.classList.add('cm-js-' + (this._property.value === null ? 'nu
ll' : typeof this._property.value)); |
| 544 } |
| 545 this.title = title; |
| 546 } |
| 467 }; | 547 }; |
| 468 | 548 |
| 469 WebInspector.LogPropertyTreeElement.prototype = { | |
| 470 onattach: function() | |
| 471 { | |
| 472 var title = createDocumentFragment(); | |
| 473 var nameElement = title.createChild("span", "name"); | |
| 474 nameElement.textContent = this._property.name; | |
| 475 var separatorElement = title.createChild("span", "separator"); | |
| 476 separatorElement.textContent = ": "; | |
| 477 if (this._property.value === null || typeof this._property.value !== "ob
ject") { | |
| 478 var valueElement = title.createChild("span", "value"); | |
| 479 valueElement.textContent = JSON.stringify(this._property.value); | |
| 480 valueElement.classList.add("cm-js-" + (this._property.value === null
? "null" : typeof this._property.value)); | |
| 481 } | |
| 482 this.title = title; | |
| 483 }, | |
| 484 | |
| 485 __proto__: TreeElement.prototype | |
| 486 }; | |
| 487 | 549 |
| 488 /** | 550 /** |
| 489 * @return {!Object.<string, !WebInspector.PaintProfilerCategory>} | 551 * @unrestricted |
| 490 */ | 552 */ |
| 491 WebInspector.PaintProfilerView.categories = function() | 553 WebInspector.PaintProfilerCategory = class { |
| 492 { | 554 /** |
| 493 if (WebInspector.PaintProfilerView._categories) | 555 * @param {string} name |
| 494 return WebInspector.PaintProfilerView._categories; | 556 * @param {string} title |
| 495 WebInspector.PaintProfilerView._categories = { | 557 * @param {string} color |
| 496 shapes: new WebInspector.PaintProfilerCategory("shapes", WebInspector.UI
String("Shapes"), "rgb(255, 161, 129)"), | 558 */ |
| 497 bitmap: new WebInspector.PaintProfilerCategory("bitmap", WebInspector.UI
String("Bitmap"), "rgb(136, 196, 255)"), | 559 constructor(name, title, color) { |
| 498 text: new WebInspector.PaintProfilerCategory("text", WebInspector.UIStri
ng("Text"), "rgb(180, 255, 137)"), | |
| 499 misc: new WebInspector.PaintProfilerCategory("misc", WebInspector.UIStri
ng("Misc"), "rgb(206, 160, 255)") | |
| 500 }; | |
| 501 return WebInspector.PaintProfilerView._categories; | |
| 502 }; | |
| 503 | |
| 504 /** | |
| 505 * @constructor | |
| 506 * @param {string} name | |
| 507 * @param {string} title | |
| 508 * @param {string} color | |
| 509 */ | |
| 510 WebInspector.PaintProfilerCategory = function(name, title, color) | |
| 511 { | |
| 512 this.name = name; | 560 this.name = name; |
| 513 this.title = title; | 561 this.title = title; |
| 514 this.color = color; | 562 this.color = color; |
| 563 } |
| 515 }; | 564 }; |
| 516 | 565 |
| 517 /** | 566 |
| 518 * @return {!Object.<string, !WebInspector.PaintProfilerCategory>} | |
| 519 */ | |
| 520 WebInspector.PaintProfilerView._initLogItemCategories = function() | |
| 521 { | |
| 522 if (WebInspector.PaintProfilerView._logItemCategoriesMap) | |
| 523 return WebInspector.PaintProfilerView._logItemCategoriesMap; | |
| 524 | |
| 525 var categories = WebInspector.PaintProfilerView.categories(); | |
| 526 | |
| 527 var logItemCategories = {}; | |
| 528 logItemCategories["Clear"] = categories["misc"]; | |
| 529 logItemCategories["DrawPaint"] = categories["misc"]; | |
| 530 logItemCategories["DrawData"] = categories["misc"]; | |
| 531 logItemCategories["SetMatrix"] = categories["misc"]; | |
| 532 logItemCategories["PushCull"] = categories["misc"]; | |
| 533 logItemCategories["PopCull"] = categories["misc"]; | |
| 534 logItemCategories["Translate"] = categories["misc"]; | |
| 535 logItemCategories["Scale"] = categories["misc"]; | |
| 536 logItemCategories["Concat"] = categories["misc"]; | |
| 537 logItemCategories["Restore"] = categories["misc"]; | |
| 538 logItemCategories["SaveLayer"] = categories["misc"]; | |
| 539 logItemCategories["Save"] = categories["misc"]; | |
| 540 logItemCategories["BeginCommentGroup"] = categories["misc"]; | |
| 541 logItemCategories["AddComment"] = categories["misc"]; | |
| 542 logItemCategories["EndCommentGroup"] = categories["misc"]; | |
| 543 logItemCategories["ClipRect"] = categories["misc"]; | |
| 544 logItemCategories["ClipRRect"] = categories["misc"]; | |
| 545 logItemCategories["ClipPath"] = categories["misc"]; | |
| 546 logItemCategories["ClipRegion"] = categories["misc"]; | |
| 547 logItemCategories["DrawPoints"] = categories["shapes"]; | |
| 548 logItemCategories["DrawRect"] = categories["shapes"]; | |
| 549 logItemCategories["DrawOval"] = categories["shapes"]; | |
| 550 logItemCategories["DrawRRect"] = categories["shapes"]; | |
| 551 logItemCategories["DrawPath"] = categories["shapes"]; | |
| 552 logItemCategories["DrawVertices"] = categories["shapes"]; | |
| 553 logItemCategories["DrawDRRect"] = categories["shapes"]; | |
| 554 logItemCategories["DrawBitmap"] = categories["bitmap"]; | |
| 555 logItemCategories["DrawBitmapRectToRect"] = categories["bitmap"]; | |
| 556 logItemCategories["DrawBitmapMatrix"] = categories["bitmap"]; | |
| 557 logItemCategories["DrawBitmapNine"] = categories["bitmap"]; | |
| 558 logItemCategories["DrawSprite"] = categories["bitmap"]; | |
| 559 logItemCategories["DrawPicture"] = categories["bitmap"]; | |
| 560 logItemCategories["DrawText"] = categories["text"]; | |
| 561 logItemCategories["DrawPosText"] = categories["text"]; | |
| 562 logItemCategories["DrawPosTextH"] = categories["text"]; | |
| 563 logItemCategories["DrawTextOnPath"] = categories["text"]; | |
| 564 | |
| 565 WebInspector.PaintProfilerView._logItemCategoriesMap = logItemCategories; | |
| 566 return logItemCategories; | |
| 567 }; | |
| 568 | |
| 569 /** | |
| 570 * @param {!Object} logItem | |
| 571 * @return {!WebInspector.PaintProfilerCategory} | |
| 572 */ | |
| 573 WebInspector.PaintProfilerView._categoryForLogItem = function(logItem) | |
| 574 { | |
| 575 var method = logItem.method.toTitleCase(); | |
| 576 | |
| 577 var logItemCategories = WebInspector.PaintProfilerView._initLogItemCategorie
s(); | |
| 578 var result = logItemCategories[method]; | |
| 579 if (!result) { | |
| 580 result = WebInspector.PaintProfilerView.categories()["misc"]; | |
| 581 logItemCategories[method] = result; | |
| 582 } | |
| 583 return result; | |
| 584 }; | |
| OLD | NEW |