| 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 * @extends {WebInspector.SDKModel} | 32 */ |
| 34 */ | 33 WebInspector.LayerTreeModel = class extends WebInspector.SDKModel { |
| 35 WebInspector.LayerTreeModel = function(target) | 34 constructor(target) { |
| 36 { | 35 super(WebInspector.LayerTreeModel, target); |
| 37 WebInspector.SDKModel.call(this, WebInspector.LayerTreeModel, target); | |
| 38 target.registerLayerTreeDispatcher(new WebInspector.LayerTreeDispatcher(this
)); | 36 target.registerLayerTreeDispatcher(new WebInspector.LayerTreeDispatcher(this
)); |
| 39 WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Event
s.MainFrameNavigated, this._onMainFrameNavigated, this); | 37 WebInspector.targetManager.addEventListener( |
| 38 WebInspector.TargetManager.Events.MainFrameNavigated, this._onMainFrameN
avigated, this); |
| 40 /** @type {?WebInspector.LayerTreeBase} */ | 39 /** @type {?WebInspector.LayerTreeBase} */ |
| 41 this._layerTree = null; | 40 this._layerTree = null; |
| 41 } |
| 42 |
| 43 /** |
| 44 * @param {!WebInspector.Target} target |
| 45 * @return {?WebInspector.LayerTreeModel} |
| 46 */ |
| 47 static fromTarget(target) { |
| 48 if (!target.hasDOMCapability()) |
| 49 return null; |
| 50 |
| 51 var model = /** @type {?WebInspector.LayerTreeModel} */ (target.model(WebIns
pector.LayerTreeModel)); |
| 52 if (!model) |
| 53 model = new WebInspector.LayerTreeModel(target); |
| 54 return model; |
| 55 } |
| 56 |
| 57 disable() { |
| 58 if (!this._enabled) |
| 59 return; |
| 60 this._enabled = false; |
| 61 this.target().layerTreeAgent().disable(); |
| 62 } |
| 63 |
| 64 enable() { |
| 65 if (this._enabled) |
| 66 return; |
| 67 this._enabled = true; |
| 68 this._forceEnable(); |
| 69 } |
| 70 |
| 71 _forceEnable() { |
| 72 this._lastPaintRectByLayerId = {}; |
| 73 if (!this._layerTree) |
| 74 this._layerTree = new WebInspector.AgentLayerTree(this.target()); |
| 75 this.target().layerTreeAgent().enable(); |
| 76 } |
| 77 |
| 78 /** |
| 79 * @return {?WebInspector.LayerTreeBase} |
| 80 */ |
| 81 layerTree() { |
| 82 return this._layerTree; |
| 83 } |
| 84 |
| 85 /** |
| 86 * @param {?Array.<!LayerTreeAgent.Layer>} layers |
| 87 */ |
| 88 _layerTreeChanged(layers) { |
| 89 if (!this._enabled) |
| 90 return; |
| 91 var layerTree = /** @type {!WebInspector.AgentLayerTree} */ (this._layerTree
); |
| 92 layerTree.setLayers(layers, onLayersSet.bind(this)); |
| 93 |
| 94 /** |
| 95 * @this {WebInspector.LayerTreeModel} |
| 96 */ |
| 97 function onLayersSet() { |
| 98 for (var layerId in this._lastPaintRectByLayerId) { |
| 99 var lastPaintRect = this._lastPaintRectByLayerId[layerId]; |
| 100 var layer = layerTree.layerById(layerId); |
| 101 if (layer) |
| 102 layer._lastPaintRect = lastPaintRect; |
| 103 } |
| 104 this._lastPaintRectByLayerId = {}; |
| 105 |
| 106 this.dispatchEventToListeners(WebInspector.LayerTreeModel.Events.LayerTree
Changed); |
| 107 } |
| 108 } |
| 109 |
| 110 /** |
| 111 * @param {!LayerTreeAgent.LayerId} layerId |
| 112 * @param {!DOMAgent.Rect} clipRect |
| 113 */ |
| 114 _layerPainted(layerId, clipRect) { |
| 115 if (!this._enabled) |
| 116 return; |
| 117 var layerTree = /** @type {!WebInspector.AgentLayerTree} */ (this._layerTree
); |
| 118 var layer = layerTree.layerById(layerId); |
| 119 if (!layer) { |
| 120 this._lastPaintRectByLayerId[layerId] = clipRect; |
| 121 return; |
| 122 } |
| 123 layer._didPaint(clipRect); |
| 124 this.dispatchEventToListeners(WebInspector.LayerTreeModel.Events.LayerPainte
d, layer); |
| 125 } |
| 126 |
| 127 _onMainFrameNavigated() { |
| 128 this._layerTree = null; |
| 129 if (this._enabled) |
| 130 this._forceEnable(); |
| 131 } |
| 42 }; | 132 }; |
| 43 | 133 |
| 44 /** @enum {symbol} */ | 134 /** @enum {symbol} */ |
| 45 WebInspector.LayerTreeModel.Events = { | 135 WebInspector.LayerTreeModel.Events = { |
| 46 LayerTreeChanged: Symbol("LayerTreeChanged"), | 136 LayerTreeChanged: Symbol('LayerTreeChanged'), |
| 47 LayerPainted: Symbol("LayerPainted"), | 137 LayerPainted: Symbol('LayerPainted'), |
| 48 }; | 138 }; |
| 49 | 139 |
| 50 WebInspector.LayerTreeModel.prototype = { | 140 /** |
| 51 disable: function() | 141 * @unrestricted |
| 52 { | 142 */ |
| 53 if (!this._enabled) | 143 WebInspector.AgentLayerTree = class extends WebInspector.LayerTreeBase { |
| 54 return; | 144 /** |
| 55 this._enabled = false; | 145 * @param {?WebInspector.Target} target |
| 56 this.target().layerTreeAgent().disable(); | 146 */ |
| 57 }, | 147 constructor(target) { |
| 58 | 148 super(target); |
| 59 enable: function() | 149 } |
| 60 { | 150 |
| 61 if (this._enabled) | 151 /** |
| 62 return; | 152 * @param {?Array.<!LayerTreeAgent.Layer>} payload |
| 63 this._enabled = true; | 153 * @param {function()} callback |
| 64 this._forceEnable(); | 154 */ |
| 65 }, | 155 setLayers(payload, callback) { |
| 66 | 156 if (!payload) { |
| 67 _forceEnable: function() | 157 onBackendNodeIdsResolved.call(this); |
| 68 { | 158 return; |
| 69 this._lastPaintRectByLayerId = {}; | 159 } |
| 70 if (!this._layerTree) | 160 |
| 71 this._layerTree = new WebInspector.AgentLayerTree(this.target()); | 161 var idsToResolve = new Set(); |
| 72 this.target().layerTreeAgent().enable(); | 162 for (var i = 0; i < payload.length; ++i) { |
| 73 }, | 163 var backendNodeId = payload[i].backendNodeId; |
| 164 if (!backendNodeId || this._backendNodeIdToNode.has(backendNodeId)) |
| 165 continue; |
| 166 idsToResolve.add(backendNodeId); |
| 167 } |
| 168 this._resolveBackendNodeIds(idsToResolve, onBackendNodeIdsResolved.bind(this
)); |
| 74 | 169 |
| 75 /** | 170 /** |
| 76 * @return {?WebInspector.LayerTreeBase} | 171 * @this {WebInspector.AgentLayerTree} |
| 77 */ | 172 */ |
| 78 layerTree: function() | 173 function onBackendNodeIdsResolved() { |
| 79 { | 174 this._innerSetLayers(payload); |
| 80 return this._layerTree; | 175 callback(); |
| 81 }, | 176 } |
| 82 | 177 } |
| 83 /** | 178 |
| 84 * @param {?Array.<!LayerTreeAgent.Layer>} layers | 179 /** |
| 85 */ | 180 * @param {?Array.<!LayerTreeAgent.Layer>} layers |
| 86 _layerTreeChanged: function(layers) | 181 */ |
| 87 { | 182 _innerSetLayers(layers) { |
| 88 if (!this._enabled) | 183 this.setRoot(null); |
| 89 return; | 184 this.setContentRoot(null); |
| 90 var layerTree = /** @type {!WebInspector.AgentLayerTree} */ (this._layer
Tree); | 185 // Payload will be null when not in the composited mode. |
| 91 layerTree.setLayers(layers, onLayersSet.bind(this)); | 186 if (!layers) |
| 92 | 187 return; |
| 93 /** | 188 var root; |
| 94 * @this {WebInspector.LayerTreeModel} | 189 var oldLayersById = this._layersById; |
| 95 */ | 190 this._layersById = {}; |
| 96 function onLayersSet() | 191 for (var i = 0; i < layers.length; ++i) { |
| 97 { | 192 var layerId = layers[i].layerId; |
| 98 for (var layerId in this._lastPaintRectByLayerId) { | 193 var layer = oldLayersById[layerId]; |
| 99 var lastPaintRect = this._lastPaintRectByLayerId[layerId]; | 194 if (layer) |
| 100 var layer = layerTree.layerById(layerId); | 195 layer._reset(layers[i]); |
| 101 if (layer) | 196 else |
| 102 layer._lastPaintRect = lastPaintRect; | 197 layer = new WebInspector.AgentLayer(this._target, layers[i]); |
| 103 } | 198 this._layersById[layerId] = layer; |
| 104 this._lastPaintRectByLayerId = {}; | 199 var backendNodeId = layers[i].backendNodeId; |
| 105 | 200 if (backendNodeId) |
| 106 this.dispatchEventToListeners(WebInspector.LayerTreeModel.Events.Lay
erTreeChanged); | 201 layer._setNode(this._backendNodeIdToNode.get(backendNodeId)); |
| 107 } | 202 if (!this.contentRoot() && layer.drawsContent()) |
| 108 }, | 203 this.setContentRoot(layer); |
| 109 | 204 var parentId = layer.parentId(); |
| 110 /** | 205 if (parentId) { |
| 111 * @param {!LayerTreeAgent.LayerId} layerId | 206 var parent = this._layersById[parentId]; |
| 112 * @param {!DOMAgent.Rect} clipRect | 207 if (!parent) |
| 113 */ | 208 console.assert(parent, 'missing parent ' + parentId + ' for layer ' +
layerId); |
| 114 _layerPainted: function(layerId, clipRect) | 209 parent.addChild(layer); |
| 115 { | 210 } else { |
| 116 if (!this._enabled) | 211 if (root) |
| 117 return; | 212 console.assert(false, 'Multiple root layers'); |
| 118 var layerTree = /** @type {!WebInspector.AgentLayerTree} */ (this._layer
Tree); | 213 root = layer; |
| 119 var layer = layerTree.layerById(layerId); | 214 } |
| 120 if (!layer) { | 215 } |
| 121 this._lastPaintRectByLayerId[layerId] = clipRect; | 216 if (root) { |
| 122 return; | 217 this.setRoot(root); |
| 123 } | 218 root._calculateQuad(new WebKitCSSMatrix()); |
| 124 layer._didPaint(clipRect); | 219 } |
| 125 this.dispatchEventToListeners(WebInspector.LayerTreeModel.Events.LayerPa
inted, layer); | 220 } |
| 126 }, | |
| 127 | |
| 128 _onMainFrameNavigated: function() | |
| 129 { | |
| 130 this._layerTree = null; | |
| 131 if (this._enabled) | |
| 132 this._forceEnable(); | |
| 133 }, | |
| 134 | |
| 135 __proto__: WebInspector.SDKModel.prototype | |
| 136 }; | 221 }; |
| 137 | 222 |
| 138 /** | 223 /** |
| 139 * @constructor | |
| 140 * @param {?WebInspector.Target} target | |
| 141 * @extends {WebInspector.LayerTreeBase} | |
| 142 */ | |
| 143 WebInspector.AgentLayerTree = function(target) | |
| 144 { | |
| 145 WebInspector.LayerTreeBase.call(this, target); | |
| 146 }; | |
| 147 | |
| 148 WebInspector.AgentLayerTree.prototype = { | |
| 149 /** | |
| 150 * @param {?Array.<!LayerTreeAgent.Layer>} payload | |
| 151 * @param {function()} callback | |
| 152 */ | |
| 153 setLayers: function(payload, callback) | |
| 154 { | |
| 155 if (!payload) { | |
| 156 onBackendNodeIdsResolved.call(this); | |
| 157 return; | |
| 158 } | |
| 159 | |
| 160 var idsToResolve = new Set(); | |
| 161 for (var i = 0; i < payload.length; ++i) { | |
| 162 var backendNodeId = payload[i].backendNodeId; | |
| 163 if (!backendNodeId || this._backendNodeIdToNode.has(backendNodeId)) | |
| 164 continue; | |
| 165 idsToResolve.add(backendNodeId); | |
| 166 } | |
| 167 this._resolveBackendNodeIds(idsToResolve, onBackendNodeIdsResolved.bind(
this)); | |
| 168 | |
| 169 /** | |
| 170 * @this {WebInspector.AgentLayerTree} | |
| 171 */ | |
| 172 function onBackendNodeIdsResolved() | |
| 173 { | |
| 174 this._innerSetLayers(payload); | |
| 175 callback(); | |
| 176 } | |
| 177 }, | |
| 178 | |
| 179 /** | |
| 180 * @param {?Array.<!LayerTreeAgent.Layer>} layers | |
| 181 */ | |
| 182 _innerSetLayers: function(layers) | |
| 183 { | |
| 184 this.setRoot(null); | |
| 185 this.setContentRoot(null); | |
| 186 // Payload will be null when not in the composited mode. | |
| 187 if (!layers) | |
| 188 return; | |
| 189 var root; | |
| 190 var oldLayersById = this._layersById; | |
| 191 this._layersById = {}; | |
| 192 for (var i = 0; i < layers.length; ++i) { | |
| 193 var layerId = layers[i].layerId; | |
| 194 var layer = oldLayersById[layerId]; | |
| 195 if (layer) | |
| 196 layer._reset(layers[i]); | |
| 197 else | |
| 198 layer = new WebInspector.AgentLayer(this._target, layers[i]); | |
| 199 this._layersById[layerId] = layer; | |
| 200 var backendNodeId = layers[i].backendNodeId; | |
| 201 if (backendNodeId) | |
| 202 layer._setNode(this._backendNodeIdToNode.get(backendNodeId)); | |
| 203 if (!this.contentRoot() && layer.drawsContent()) | |
| 204 this.setContentRoot(layer); | |
| 205 var parentId = layer.parentId(); | |
| 206 if (parentId) { | |
| 207 var parent = this._layersById[parentId]; | |
| 208 if (!parent) | |
| 209 console.assert(parent, "missing parent " + parentId + " for
layer " + layerId); | |
| 210 parent.addChild(layer); | |
| 211 } else { | |
| 212 if (root) | |
| 213 console.assert(false, "Multiple root layers"); | |
| 214 root = layer; | |
| 215 } | |
| 216 } | |
| 217 if (root) { | |
| 218 this.setRoot(root); | |
| 219 root._calculateQuad(new WebKitCSSMatrix()); | |
| 220 } | |
| 221 }, | |
| 222 | |
| 223 __proto__: WebInspector.LayerTreeBase.prototype | |
| 224 }; | |
| 225 | |
| 226 /** | |
| 227 * @constructor | |
| 228 * @implements {WebInspector.Layer} | 224 * @implements {WebInspector.Layer} |
| 229 * @param {?WebInspector.Target} target | 225 * @unrestricted |
| 230 * @param {!LayerTreeAgent.Layer} layerPayload | |
| 231 */ | 226 */ |
| 232 WebInspector.AgentLayer = function(target, layerPayload) | 227 WebInspector.AgentLayer = class { |
| 233 { | 228 /** |
| 229 * @param {?WebInspector.Target} target |
| 230 * @param {!LayerTreeAgent.Layer} layerPayload |
| 231 */ |
| 232 constructor(target, layerPayload) { |
| 234 this._target = target; | 233 this._target = target; |
| 235 this._reset(layerPayload); | 234 this._reset(layerPayload); |
| 235 } |
| 236 |
| 237 /** |
| 238 * @override |
| 239 * @return {string} |
| 240 */ |
| 241 id() { |
| 242 return this._layerPayload.layerId; |
| 243 } |
| 244 |
| 245 /** |
| 246 * @override |
| 247 * @return {?string} |
| 248 */ |
| 249 parentId() { |
| 250 return this._layerPayload.parentLayerId; |
| 251 } |
| 252 |
| 253 /** |
| 254 * @override |
| 255 * @return {?WebInspector.Layer} |
| 256 */ |
| 257 parent() { |
| 258 return this._parent; |
| 259 } |
| 260 |
| 261 /** |
| 262 * @override |
| 263 * @return {boolean} |
| 264 */ |
| 265 isRoot() { |
| 266 return !this.parentId(); |
| 267 } |
| 268 |
| 269 /** |
| 270 * @override |
| 271 * @return {!Array.<!WebInspector.Layer>} |
| 272 */ |
| 273 children() { |
| 274 return this._children; |
| 275 } |
| 276 |
| 277 /** |
| 278 * @override |
| 279 * @param {!WebInspector.Layer} child |
| 280 */ |
| 281 addChild(child) { |
| 282 if (child._parent) |
| 283 console.assert(false, 'Child already has a parent'); |
| 284 this._children.push(child); |
| 285 child._parent = this; |
| 286 } |
| 287 |
| 288 /** |
| 289 * @param {?WebInspector.DOMNode} node |
| 290 */ |
| 291 _setNode(node) { |
| 292 this._node = node; |
| 293 } |
| 294 |
| 295 /** |
| 296 * @override |
| 297 * @return {?WebInspector.DOMNode} |
| 298 */ |
| 299 node() { |
| 300 return this._node; |
| 301 } |
| 302 |
| 303 /** |
| 304 * @override |
| 305 * @return {?WebInspector.DOMNode} |
| 306 */ |
| 307 nodeForSelfOrAncestor() { |
| 308 for (var layer = this; layer; layer = layer._parent) { |
| 309 if (layer._node) |
| 310 return layer._node; |
| 311 } |
| 312 return null; |
| 313 } |
| 314 |
| 315 /** |
| 316 * @override |
| 317 * @return {number} |
| 318 */ |
| 319 offsetX() { |
| 320 return this._layerPayload.offsetX; |
| 321 } |
| 322 |
| 323 /** |
| 324 * @override |
| 325 * @return {number} |
| 326 */ |
| 327 offsetY() { |
| 328 return this._layerPayload.offsetY; |
| 329 } |
| 330 |
| 331 /** |
| 332 * @override |
| 333 * @return {number} |
| 334 */ |
| 335 width() { |
| 336 return this._layerPayload.width; |
| 337 } |
| 338 |
| 339 /** |
| 340 * @override |
| 341 * @return {number} |
| 342 */ |
| 343 height() { |
| 344 return this._layerPayload.height; |
| 345 } |
| 346 |
| 347 /** |
| 348 * @override |
| 349 * @return {?Array.<number>} |
| 350 */ |
| 351 transform() { |
| 352 return this._layerPayload.transform; |
| 353 } |
| 354 |
| 355 /** |
| 356 * @override |
| 357 * @return {!Array.<number>} |
| 358 */ |
| 359 quad() { |
| 360 return this._quad; |
| 361 } |
| 362 |
| 363 /** |
| 364 * @override |
| 365 * @return {!Array.<number>} |
| 366 */ |
| 367 anchorPoint() { |
| 368 return [ |
| 369 this._layerPayload.anchorX || 0, |
| 370 this._layerPayload.anchorY || 0, |
| 371 this._layerPayload.anchorZ || 0, |
| 372 ]; |
| 373 } |
| 374 |
| 375 /** |
| 376 * @override |
| 377 * @return {boolean} |
| 378 */ |
| 379 invisible() { |
| 380 return this._layerPayload.invisible; |
| 381 } |
| 382 |
| 383 /** |
| 384 * @override |
| 385 * @return {number} |
| 386 */ |
| 387 paintCount() { |
| 388 return this._paintCount || this._layerPayload.paintCount; |
| 389 } |
| 390 |
| 391 /** |
| 392 * @override |
| 393 * @return {?DOMAgent.Rect} |
| 394 */ |
| 395 lastPaintRect() { |
| 396 return this._lastPaintRect; |
| 397 } |
| 398 |
| 399 /** |
| 400 * @override |
| 401 * @return {!Array.<!LayerTreeAgent.ScrollRect>} |
| 402 */ |
| 403 scrollRects() { |
| 404 return this._scrollRects; |
| 405 } |
| 406 |
| 407 /** |
| 408 * @override |
| 409 * @param {function(!Array.<string>)} callback |
| 410 */ |
| 411 requestCompositingReasons(callback) { |
| 412 if (!this._target) { |
| 413 callback([]); |
| 414 return; |
| 415 } |
| 416 |
| 417 var wrappedCallback = |
| 418 InspectorBackend.wrapClientCallback(callback, 'LayerTreeAgent.reasonsFor
CompositingLayer(): ', undefined, []); |
| 419 this._target.layerTreeAgent().compositingReasons(this.id(), wrappedCallback)
; |
| 420 } |
| 421 |
| 422 /** |
| 423 * @override |
| 424 * @return {boolean} |
| 425 */ |
| 426 drawsContent() { |
| 427 return this._layerPayload.drawsContent; |
| 428 } |
| 429 |
| 430 /** |
| 431 * @override |
| 432 * @return {number} |
| 433 */ |
| 434 gpuMemoryUsage() { |
| 435 /** |
| 436 * @const |
| 437 */ |
| 438 var bytesPerPixel = 4; |
| 439 return this.drawsContent() ? this.width() * this.height() * bytesPerPixel :
0; |
| 440 } |
| 441 |
| 442 /** |
| 443 * @override |
| 444 * @return {!Array<!Promise<?WebInspector.SnapshotWithRect>>} |
| 445 */ |
| 446 snapshots() { |
| 447 var rect = {x: 0, y: 0, width: this.width(), height: this.height()}; |
| 448 var promise = this._target.layerTreeAgent().makeSnapshot( |
| 449 this.id(), (error, snapshotId) => error || !this._target ? |
| 450 null : |
| 451 {rect: rect, snapshot: new WebInspector.PaintProfilerSnapshot(this._
target, snapshotId)}); |
| 452 return [promise]; |
| 453 } |
| 454 |
| 455 /** |
| 456 * @param {!DOMAgent.Rect} rect |
| 457 */ |
| 458 _didPaint(rect) { |
| 459 this._lastPaintRect = rect; |
| 460 this._paintCount = this.paintCount() + 1; |
| 461 this._image = null; |
| 462 } |
| 463 |
| 464 /** |
| 465 * @param {!LayerTreeAgent.Layer} layerPayload |
| 466 */ |
| 467 _reset(layerPayload) { |
| 468 /** @type {?WebInspector.DOMNode} */ |
| 469 this._node = null; |
| 470 this._children = []; |
| 471 this._parent = null; |
| 472 this._paintCount = 0; |
| 473 this._layerPayload = layerPayload; |
| 474 this._image = null; |
| 475 this._scrollRects = this._layerPayload.scrollRects || []; |
| 476 } |
| 477 |
| 478 /** |
| 479 * @param {!Array.<number>} a |
| 480 * @return {!CSSMatrix} |
| 481 */ |
| 482 _matrixFromArray(a) { |
| 483 function toFixed9(x) { |
| 484 return x.toFixed(9); |
| 485 } |
| 486 return new WebKitCSSMatrix('matrix3d(' + a.map(toFixed9).join(',') + ')'); |
| 487 } |
| 488 |
| 489 /** |
| 490 * @param {!CSSMatrix} parentTransform |
| 491 * @return {!CSSMatrix} |
| 492 */ |
| 493 _calculateTransformToViewport(parentTransform) { |
| 494 var offsetMatrix = new WebKitCSSMatrix().translate(this._layerPayload.offset
X, this._layerPayload.offsetY); |
| 495 var matrix = offsetMatrix; |
| 496 |
| 497 if (this._layerPayload.transform) { |
| 498 var transformMatrix = this._matrixFromArray(this._layerPayload.transform); |
| 499 var anchorVector = new WebInspector.Geometry.Vector( |
| 500 this._layerPayload.width * this.anchorPoint()[0], this._layerPayload.h
eight * this.anchorPoint()[1], |
| 501 this.anchorPoint()[2]); |
| 502 var anchorPoint = WebInspector.Geometry.multiplyVectorByMatrixAndNormalize
(anchorVector, matrix); |
| 503 var anchorMatrix = new WebKitCSSMatrix().translate(-anchorPoint.x, -anchor
Point.y, -anchorPoint.z); |
| 504 matrix = anchorMatrix.inverse().multiply(transformMatrix.multiply(anchorMa
trix.multiply(matrix))); |
| 505 } |
| 506 |
| 507 matrix = parentTransform.multiply(matrix); |
| 508 return matrix; |
| 509 } |
| 510 |
| 511 /** |
| 512 * @param {number} width |
| 513 * @param {number} height |
| 514 * @return {!Array.<number>} |
| 515 */ |
| 516 _createVertexArrayForRect(width, height) { |
| 517 return [0, 0, 0, width, 0, 0, width, height, 0, 0, height, 0]; |
| 518 } |
| 519 |
| 520 /** |
| 521 * @param {!CSSMatrix} parentTransform |
| 522 */ |
| 523 _calculateQuad(parentTransform) { |
| 524 var matrix = this._calculateTransformToViewport(parentTransform); |
| 525 this._quad = []; |
| 526 var vertices = this._createVertexArrayForRect(this._layerPayload.width, this
._layerPayload.height); |
| 527 for (var i = 0; i < 4; ++i) { |
| 528 var point = WebInspector.Geometry.multiplyVectorByMatrixAndNormalize( |
| 529 new WebInspector.Geometry.Vector(vertices[i * 3], vertices[i * 3 + 1],
vertices[i * 3 + 2]), matrix); |
| 530 this._quad.push(point.x, point.y); |
| 531 } |
| 532 |
| 533 function calculateQuadForLayer(layer) { |
| 534 layer._calculateQuad(matrix); |
| 535 } |
| 536 |
| 537 this._children.forEach(calculateQuadForLayer); |
| 538 } |
| 236 }; | 539 }; |
| 237 | 540 |
| 238 WebInspector.AgentLayer.prototype = { | 541 /** |
| 239 /** | 542 * @implements {LayerTreeAgent.Dispatcher} |
| 240 * @override | 543 * @unrestricted |
| 241 * @return {string} | 544 */ |
| 242 */ | 545 WebInspector.LayerTreeDispatcher = class { |
| 243 id: function() | 546 /** |
| 244 { | 547 * @param {!WebInspector.LayerTreeModel} layerTreeModel |
| 245 return this._layerPayload.layerId; | 548 */ |
| 246 }, | 549 constructor(layerTreeModel) { |
| 247 | 550 this._layerTreeModel = layerTreeModel; |
| 248 /** | 551 } |
| 249 * @override | 552 |
| 250 * @return {?string} | 553 /** |
| 251 */ | 554 * @override |
| 252 parentId: function() | 555 * @param {!Array.<!LayerTreeAgent.Layer>=} layers |
| 253 { | 556 */ |
| 254 return this._layerPayload.parentLayerId; | 557 layerTreeDidChange(layers) { |
| 255 }, | 558 this._layerTreeModel._layerTreeChanged(layers || null); |
| 256 | 559 } |
| 257 /** | 560 |
| 258 * @override | 561 /** |
| 259 * @return {?WebInspector.Layer} | 562 * @override |
| 260 */ | 563 * @param {!LayerTreeAgent.LayerId} layerId |
| 261 parent: function() | 564 * @param {!DOMAgent.Rect} clipRect |
| 262 { | 565 */ |
| 263 return this._parent; | 566 layerPainted(layerId, clipRect) { |
| 264 }, | 567 this._layerTreeModel._layerPainted(layerId, clipRect); |
| 265 | 568 } |
| 266 /** | |
| 267 * @override | |
| 268 * @return {boolean} | |
| 269 */ | |
| 270 isRoot: function() | |
| 271 { | |
| 272 return !this.parentId(); | |
| 273 }, | |
| 274 | |
| 275 /** | |
| 276 * @override | |
| 277 * @return {!Array.<!WebInspector.Layer>} | |
| 278 */ | |
| 279 children: function() | |
| 280 { | |
| 281 return this._children; | |
| 282 }, | |
| 283 | |
| 284 /** | |
| 285 * @override | |
| 286 * @param {!WebInspector.Layer} child | |
| 287 */ | |
| 288 addChild: function(child) | |
| 289 { | |
| 290 if (child._parent) | |
| 291 console.assert(false, "Child already has a parent"); | |
| 292 this._children.push(child); | |
| 293 child._parent = this; | |
| 294 }, | |
| 295 | |
| 296 /** | |
| 297 * @param {?WebInspector.DOMNode} node | |
| 298 */ | |
| 299 _setNode: function(node) | |
| 300 { | |
| 301 this._node = node; | |
| 302 }, | |
| 303 | |
| 304 /** | |
| 305 * @override | |
| 306 * @return {?WebInspector.DOMNode} | |
| 307 */ | |
| 308 node: function() | |
| 309 { | |
| 310 return this._node; | |
| 311 }, | |
| 312 | |
| 313 /** | |
| 314 * @override | |
| 315 * @return {?WebInspector.DOMNode} | |
| 316 */ | |
| 317 nodeForSelfOrAncestor: function() | |
| 318 { | |
| 319 for (var layer = this; layer; layer = layer._parent) { | |
| 320 if (layer._node) | |
| 321 return layer._node; | |
| 322 } | |
| 323 return null; | |
| 324 }, | |
| 325 | |
| 326 /** | |
| 327 * @override | |
| 328 * @return {number} | |
| 329 */ | |
| 330 offsetX: function() | |
| 331 { | |
| 332 return this._layerPayload.offsetX; | |
| 333 }, | |
| 334 | |
| 335 /** | |
| 336 * @override | |
| 337 * @return {number} | |
| 338 */ | |
| 339 offsetY: function() | |
| 340 { | |
| 341 return this._layerPayload.offsetY; | |
| 342 }, | |
| 343 | |
| 344 /** | |
| 345 * @override | |
| 346 * @return {number} | |
| 347 */ | |
| 348 width: function() | |
| 349 { | |
| 350 return this._layerPayload.width; | |
| 351 }, | |
| 352 | |
| 353 /** | |
| 354 * @override | |
| 355 * @return {number} | |
| 356 */ | |
| 357 height: function() | |
| 358 { | |
| 359 return this._layerPayload.height; | |
| 360 }, | |
| 361 | |
| 362 /** | |
| 363 * @override | |
| 364 * @return {?Array.<number>} | |
| 365 */ | |
| 366 transform: function() | |
| 367 { | |
| 368 return this._layerPayload.transform; | |
| 369 }, | |
| 370 | |
| 371 /** | |
| 372 * @override | |
| 373 * @return {!Array.<number>} | |
| 374 */ | |
| 375 quad: function() | |
| 376 { | |
| 377 return this._quad; | |
| 378 }, | |
| 379 | |
| 380 /** | |
| 381 * @override | |
| 382 * @return {!Array.<number>} | |
| 383 */ | |
| 384 anchorPoint: function() | |
| 385 { | |
| 386 return [ | |
| 387 this._layerPayload.anchorX || 0, | |
| 388 this._layerPayload.anchorY || 0, | |
| 389 this._layerPayload.anchorZ || 0, | |
| 390 ]; | |
| 391 }, | |
| 392 | |
| 393 /** | |
| 394 * @override | |
| 395 * @return {boolean} | |
| 396 */ | |
| 397 invisible: function() | |
| 398 { | |
| 399 return this._layerPayload.invisible; | |
| 400 }, | |
| 401 | |
| 402 /** | |
| 403 * @override | |
| 404 * @return {number} | |
| 405 */ | |
| 406 paintCount: function() | |
| 407 { | |
| 408 return this._paintCount || this._layerPayload.paintCount; | |
| 409 }, | |
| 410 | |
| 411 /** | |
| 412 * @override | |
| 413 * @return {?DOMAgent.Rect} | |
| 414 */ | |
| 415 lastPaintRect: function() | |
| 416 { | |
| 417 return this._lastPaintRect; | |
| 418 }, | |
| 419 | |
| 420 /** | |
| 421 * @override | |
| 422 * @return {!Array.<!LayerTreeAgent.ScrollRect>} | |
| 423 */ | |
| 424 scrollRects: function() | |
| 425 { | |
| 426 return this._scrollRects; | |
| 427 }, | |
| 428 | |
| 429 /** | |
| 430 * @override | |
| 431 * @param {function(!Array.<string>)} callback | |
| 432 */ | |
| 433 requestCompositingReasons: function(callback) | |
| 434 { | |
| 435 if (!this._target) { | |
| 436 callback([]); | |
| 437 return; | |
| 438 } | |
| 439 | |
| 440 var wrappedCallback = InspectorBackend.wrapClientCallback(callback, "Lay
erTreeAgent.reasonsForCompositingLayer(): ", undefined, []); | |
| 441 this._target.layerTreeAgent().compositingReasons(this.id(), wrappedCallb
ack); | |
| 442 }, | |
| 443 | |
| 444 /** | |
| 445 * @override | |
| 446 * @return {boolean} | |
| 447 */ | |
| 448 drawsContent: function() | |
| 449 { | |
| 450 return this._layerPayload.drawsContent; | |
| 451 }, | |
| 452 | |
| 453 /** | |
| 454 * @override | |
| 455 * @return {number} | |
| 456 */ | |
| 457 gpuMemoryUsage: function() | |
| 458 { | |
| 459 /** | |
| 460 * @const | |
| 461 */ | |
| 462 var bytesPerPixel = 4; | |
| 463 return this.drawsContent() ? this.width() * this.height() * bytesPerPixe
l : 0; | |
| 464 }, | |
| 465 | |
| 466 /** | |
| 467 * @override | |
| 468 * @return {!Array<!Promise<?WebInspector.SnapshotWithRect>>} | |
| 469 */ | |
| 470 snapshots: function() | |
| 471 { | |
| 472 var rect = {x: 0, y: 0, width: this.width(), height: this.height()}; | |
| 473 var promise = this._target.layerTreeAgent().makeSnapshot(this.id(), | |
| 474 (error, snapshotId) => error || !this._target ? null : {rect: rect,
snapshot: new WebInspector.PaintProfilerSnapshot(this._target, snapshotId)}); | |
| 475 return [promise]; | |
| 476 }, | |
| 477 | |
| 478 /** | |
| 479 * @param {!DOMAgent.Rect} rect | |
| 480 */ | |
| 481 _didPaint: function(rect) | |
| 482 { | |
| 483 this._lastPaintRect = rect; | |
| 484 this._paintCount = this.paintCount() + 1; | |
| 485 this._image = null; | |
| 486 }, | |
| 487 | |
| 488 /** | |
| 489 * @param {!LayerTreeAgent.Layer} layerPayload | |
| 490 */ | |
| 491 _reset: function(layerPayload) | |
| 492 { | |
| 493 /** @type {?WebInspector.DOMNode} */ | |
| 494 this._node = null; | |
| 495 this._children = []; | |
| 496 this._parent = null; | |
| 497 this._paintCount = 0; | |
| 498 this._layerPayload = layerPayload; | |
| 499 this._image = null; | |
| 500 this._scrollRects = this._layerPayload.scrollRects || []; | |
| 501 }, | |
| 502 | |
| 503 /** | |
| 504 * @param {!Array.<number>} a | |
| 505 * @return {!CSSMatrix} | |
| 506 */ | |
| 507 _matrixFromArray: function(a) | |
| 508 { | |
| 509 function toFixed9(x) { return x.toFixed(9); } | |
| 510 return new WebKitCSSMatrix("matrix3d(" + a.map(toFixed9).join(",") + ")"
); | |
| 511 }, | |
| 512 | |
| 513 /** | |
| 514 * @param {!CSSMatrix} parentTransform | |
| 515 * @return {!CSSMatrix} | |
| 516 */ | |
| 517 _calculateTransformToViewport: function(parentTransform) | |
| 518 { | |
| 519 var offsetMatrix = new WebKitCSSMatrix().translate(this._layerPayload.of
fsetX, this._layerPayload.offsetY); | |
| 520 var matrix = offsetMatrix; | |
| 521 | |
| 522 if (this._layerPayload.transform) { | |
| 523 var transformMatrix = this._matrixFromArray(this._layerPayload.trans
form); | |
| 524 var anchorVector = new WebInspector.Geometry.Vector(this._layerPaylo
ad.width * this.anchorPoint()[0], this._layerPayload.height * this.anchorPoint()
[1], this.anchorPoint()[2]); | |
| 525 var anchorPoint = WebInspector.Geometry.multiplyVectorByMatrixAndNor
malize(anchorVector, matrix); | |
| 526 var anchorMatrix = new WebKitCSSMatrix().translate(-anchorPoint.x, -
anchorPoint.y, -anchorPoint.z); | |
| 527 matrix = anchorMatrix.inverse().multiply(transformMatrix.multiply(an
chorMatrix.multiply(matrix))); | |
| 528 } | |
| 529 | |
| 530 matrix = parentTransform.multiply(matrix); | |
| 531 return matrix; | |
| 532 }, | |
| 533 | |
| 534 /** | |
| 535 * @param {number} width | |
| 536 * @param {number} height | |
| 537 * @return {!Array.<number>} | |
| 538 */ | |
| 539 _createVertexArrayForRect: function(width, height) | |
| 540 { | |
| 541 return [0, 0, 0, width, 0, 0, width, height, 0, 0, height, 0]; | |
| 542 }, | |
| 543 | |
| 544 /** | |
| 545 * @param {!CSSMatrix} parentTransform | |
| 546 */ | |
| 547 _calculateQuad: function(parentTransform) | |
| 548 { | |
| 549 var matrix = this._calculateTransformToViewport(parentTransform); | |
| 550 this._quad = []; | |
| 551 var vertices = this._createVertexArrayForRect(this._layerPayload.width,
this._layerPayload.height); | |
| 552 for (var i = 0; i < 4; ++i) { | |
| 553 var point = WebInspector.Geometry.multiplyVectorByMatrixAndNormalize
(new WebInspector.Geometry.Vector(vertices[i * 3], vertices[i * 3 + 1], vertices
[i * 3 + 2]), matrix); | |
| 554 this._quad.push(point.x, point.y); | |
| 555 } | |
| 556 | |
| 557 function calculateQuadForLayer(layer) | |
| 558 { | |
| 559 layer._calculateQuad(matrix); | |
| 560 } | |
| 561 | |
| 562 this._children.forEach(calculateQuadForLayer); | |
| 563 } | |
| 564 }; | 569 }; |
| 565 | 570 |
| 566 /** | 571 |
| 567 * @constructor | |
| 568 * @implements {LayerTreeAgent.Dispatcher} | |
| 569 * @param {!WebInspector.LayerTreeModel} layerTreeModel | |
| 570 */ | |
| 571 WebInspector.LayerTreeDispatcher = function(layerTreeModel) | |
| 572 { | |
| 573 this._layerTreeModel = layerTreeModel; | |
| 574 }; | |
| 575 | |
| 576 WebInspector.LayerTreeDispatcher.prototype = { | |
| 577 /** | |
| 578 * @override | |
| 579 * @param {!Array.<!LayerTreeAgent.Layer>=} layers | |
| 580 */ | |
| 581 layerTreeDidChange: function(layers) | |
| 582 { | |
| 583 this._layerTreeModel._layerTreeChanged(layers || null); | |
| 584 }, | |
| 585 | |
| 586 /** | |
| 587 * @override | |
| 588 * @param {!LayerTreeAgent.LayerId} layerId | |
| 589 * @param {!DOMAgent.Rect} clipRect | |
| 590 */ | |
| 591 layerPainted: function(layerId, clipRect) | |
| 592 { | |
| 593 this._layerTreeModel._layerPainted(layerId, clipRect); | |
| 594 } | |
| 595 }; | |
| 596 | |
| 597 /** | |
| 598 * @param {!WebInspector.Target} target | |
| 599 * @return {?WebInspector.LayerTreeModel} | |
| 600 */ | |
| 601 WebInspector.LayerTreeModel.fromTarget = function(target) | |
| 602 { | |
| 603 if (!target.hasDOMCapability()) | |
| 604 return null; | |
| 605 | |
| 606 var model = /** @type {?WebInspector.LayerTreeModel} */ (target.model(WebIns
pector.LayerTreeModel)); | |
| 607 if (!model) | |
| 608 model = new WebInspector.LayerTreeModel(target); | |
| 609 return model; | |
| 610 }; | |
| OLD | NEW |