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 |