mh-two-thousand-and-two
2024-04-12 3d2ec2fd0578d3ba0a414b0cc4e4a2ae60878596
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
LayerViewer.LayerDetailsView=class extends UI.Widget{constructor(layerViewHost){super(true);this.registerRequiredCSS('layer_viewer/layerDetailsView.css');this._layerViewHost=layerViewHost;this._layerViewHost.registerView(this);this._emptyWidget=new UI.EmptyWidget(Common.UIString('Select a layer to see its details'));this._buildContent();}
hoverObject(selection){}
selectObject(selection){this._selection=selection;if(this.isShowing())
this.update();}
setLayerTree(layerTree){}
wasShown(){super.wasShown();this.update();}
_onScrollRectClicked(index,event){if(event.which!==1)
return;this._layerViewHost.selectObject(new LayerViewer.LayerView.ScrollRectSelection(this._selection.layer(),index));}
_onPaintProfilerButtonClicked(){if(this._selection.type()===LayerViewer.LayerView.Selection.Type.Snapshot||this._selection.layer())
this.dispatchEventToListeners(LayerViewer.LayerDetailsView.Events.PaintProfilerRequested,this._selection);}
_createScrollRectElement(scrollRect,index){if(index)
this._scrollRectsCell.createTextChild(', ');const element=this._scrollRectsCell.createChild('span','scroll-rect');if(this._selection.scrollRectIndex===index)
element.classList.add('active');element.textContent=Common.UIString('%s %d × %d (at %d, %d)',LayerViewer.LayerDetailsView._slowScrollRectNames.get(scrollRect.type),scrollRect.rect.x,scrollRect.rect.y,scrollRect.rect.width,scrollRect.rect.height);element.addEventListener('click',this._onScrollRectClicked.bind(this,index),false);}
_formatStickyAncestorLayer(title,layer){if(!layer)
return'';const node=layer.nodeForSelfOrAncestor();const name=node?node.simpleSelector():Common.UIString('<unnamed>');return Common.UIString('%s: %s (%s)',title,name,layer.id());}
_createStickyAncestorChild(title,layer){if(!layer)
return;this._stickyPositionConstraintCell.createTextChild(', ');const child=this._stickyPositionConstraintCell.createChild('span');child.textContent=this._formatStickyAncestorLayer(title,layer);}
_populateStickyPositionConstraintCell(constraint){this._stickyPositionConstraintCell.removeChildren();if(!constraint)
return;const stickyBoxRect=constraint.stickyBoxRect();const stickyBoxRectElement=this._stickyPositionConstraintCell.createChild('span');stickyBoxRectElement.textContent=Common.UIString('Sticky Box %d × %d (at %d, %d)',stickyBoxRect.width,stickyBoxRect.height,stickyBoxRect.x,stickyBoxRect.y);this._stickyPositionConstraintCell.createTextChild(', ');const containingBlockRect=constraint.containingBlockRect();const containingBlockRectElement=this._stickyPositionConstraintCell.createChild('span');containingBlockRectElement.textContent=Common.UIString('Containing Block %d × %d (at %d, %d)',containingBlockRect.width,containingBlockRect.height,containingBlockRect.x,containingBlockRect.y);this._createStickyAncestorChild(Common.UIString('Nearest Layer Shifting Sticky Box'),constraint.nearestLayerShiftingStickyBox());this._createStickyAncestorChild(Common.UIString('Nearest Layer Shifting Containing Block'),constraint.nearestLayerShiftingContainingBlock());}
update(){const layer=this._selection&&this._selection.layer();if(!layer){this._tableElement.remove();this._paintProfilerButton.remove();this._emptyWidget.show(this.contentElement);return;}
this._emptyWidget.detach();this.contentElement.appendChild(this._tableElement);this.contentElement.appendChild(this._paintProfilerButton);this._sizeCell.textContent=Common.UIString('%d × %d (at %d,%d)',layer.width(),layer.height(),layer.offsetX(),layer.offsetY());this._paintCountCell.parentElement.classList.toggle('hidden',!layer.paintCount());this._paintCountCell.textContent=layer.paintCount();this._memoryEstimateCell.textContent=Number.bytesToString(layer.gpuMemoryUsage());layer.requestCompositingReasons().then(this._updateCompositingReasons.bind(this));this._scrollRectsCell.removeChildren();layer.scrollRects().forEach(this._createScrollRectElement.bind(this));this._populateStickyPositionConstraintCell(layer.stickyPositionConstraint());const snapshot=this._selection.type()===LayerViewer.LayerView.Selection.Type.Snapshot?(this._selection).snapshot():null;this._paintProfilerButton.classList.toggle('hidden',!snapshot);}
_buildContent(){this._tableElement=this.contentElement.createChild('table');this._tbodyElement=this._tableElement.createChild('tbody');this._sizeCell=this._createRow(Common.UIString('Size'));this._compositingReasonsCell=this._createRow(Common.UIString('Compositing Reasons'));this._memoryEstimateCell=this._createRow(Common.UIString('Memory estimate'));this._paintCountCell=this._createRow(Common.UIString('Paint count'));this._scrollRectsCell=this._createRow(Common.UIString('Slow scroll regions'));this._stickyPositionConstraintCell=this._createRow(Common.UIString('Sticky position constraint'));this._paintProfilerButton=this.contentElement.createChild('a','hidden link');this._paintProfilerButton.textContent=Common.UIString('Paint Profiler');this._paintProfilerButton.addEventListener('click',this._onPaintProfilerButtonClicked.bind(this));}
_createRow(title){const tr=this._tbodyElement.createChild('tr');const titleCell=tr.createChild('td');titleCell.textContent=title;return tr.createChild('td');}
_updateCompositingReasons(compositingReasons){if(!compositingReasons||!compositingReasons.length){this._compositingReasonsCell.textContent='n/a';return;}
this._compositingReasonsCell.removeChildren();const list=this._compositingReasonsCell.createChild('ul');for(let i=0;i<compositingReasons.length;++i){let text=LayerViewer.LayerDetailsView.CompositingReasonDetail[compositingReasons[i]]||compositingReasons[i];if(/\s.*[^.]$/.test(text))
text+='.';list.createChild('li').textContent=text;}}};LayerViewer.LayerDetailsView.Events={PaintProfilerRequested:Symbol('PaintProfilerRequested')};LayerViewer.LayerDetailsView.CompositingReasonDetail={'transform3D':Common.UIString('Composition due to association with an element with a CSS 3D transform.'),'video':Common.UIString('Composition due to association with a <video> element.'),'canvas':Common.UIString('Composition due to the element being a <canvas> element.'),'plugin':Common.UIString('Composition due to association with a plugin.'),'iFrame':Common.UIString('Composition due to association with an <iframe> element.'),'backfaceVisibilityHidden':Common.UIString('Composition due to association with an element with a "backface-visibility: hidden" style.'),'animation':Common.UIString('Composition due to association with an animated element.'),'filters':Common.UIString('Composition due to association with an element with CSS filters applied.'),'scrollDependentPosition':Common.UIString('Composition due to association with an element with a "position: fixed" or "position: sticky" style.'),'overflowScrollingTouch':Common.UIString('Composition due to association with an element with a "overflow-scrolling: touch" style.'),'blending':Common.UIString('Composition due to association with an element that has blend mode other than "normal".'),'assumedOverlap':Common.UIString('Composition due to association with an element that may overlap other composited elements.'),'overlap':Common.UIString('Composition due to association with an element overlapping other composited elements.'),'negativeZIndexChildren':Common.UIString('Composition due to association with an element with descendants that have a negative z-index.'),'transformWithCompositedDescendants':Common.UIString('Composition due to association with an element with composited descendants.'),'opacityWithCompositedDescendants':Common.UIString('Composition due to association with an element with opacity applied and composited descendants.'),'maskWithCompositedDescendants':Common.UIString('Composition due to association with a masked element and composited descendants.'),'reflectionWithCompositedDescendants':Common.UIString('Composition due to association with an element with a reflection and composited descendants.'),'filterWithCompositedDescendants':Common.UIString('Composition due to association with an element with CSS filters applied and composited descendants.'),'blendingWithCompositedDescendants':Common.UIString('Composition due to association with an element with CSS blending applied and composited descendants.'),'clipsCompositingDescendants':Common.UIString('Composition due to association with an element clipping compositing descendants.'),'perspective':Common.UIString('Composition due to association with an element with perspective applied.'),'preserve3D':Common.UIString('Composition due to association with an element with a "transform-style: preserve-3d" style.'),'root':Common.UIString('Root layer.'),'layerForClip':Common.UIString('Layer for clip.'),'layerForScrollbar':Common.UIString('Layer for scrollbar.'),'layerForScrollingContainer':Common.UIString('Layer for scrolling container.'),'layerForForeground':Common.UIString('Layer for foreground.'),'layerForBackground':Common.UIString('Layer for background.'),'layerForMask':Common.UIString('Layer for mask.'),'layerForVideoOverlay':Common.UIString('Layer for video overlay.'),};LayerViewer.LayerDetailsView._slowScrollRectNames=new Map([[SDK.Layer.ScrollRectType.NonFastScrollable,Common.UIString('Non fast scrollable')],[SDK.Layer.ScrollRectType.TouchEventHandler,Common.UIString('Touch event handler')],[SDK.Layer.ScrollRectType.WheelEventHandler,Common.UIString('Wheel event handler')],[SDK.Layer.ScrollRectType.RepaintsOnScroll,Common.UIString('Repaints on scroll')]]);;LayerViewer.LayerTreeOutline=class extends Common.Object{constructor(layerViewHost){super();this._layerViewHost=layerViewHost;this._layerViewHost.registerView(this);this._treeOutline=new UI.TreeOutlineInShadow();this._treeOutline.element.classList.add('layer-tree','overflow-auto');this._treeOutline.element.addEventListener('mousemove',this._onMouseMove.bind(this),false);this._treeOutline.element.addEventListener('mouseout',this._onMouseMove.bind(this),false);this._treeOutline.element.addEventListener('contextmenu',this._onContextMenu.bind(this),true);this._lastHoveredNode=null;this.element=this._treeOutline.element;this._layerViewHost.showInternalLayersSetting().addChangeListener(this._update,this);}
focus(){this._treeOutline.focus();}
selectObject(selection){this.hoverObject(null);const layer=selection&&selection.layer();const node=layer&&layer[LayerViewer.LayerTreeElement._symbol];if(node)
node.revealAndSelect(true);else if(this._treeOutline.selectedTreeElement)
this._treeOutline.selectedTreeElement.deselect();}
hoverObject(selection){const layer=selection&&selection.layer();const node=layer&&layer[LayerViewer.LayerTreeElement._symbol];if(node===this._lastHoveredNode)
return;if(this._lastHoveredNode)
this._lastHoveredNode.setHovered(false);if(node)
node.setHovered(true);this._lastHoveredNode=node;}
setLayerTree(layerTree){this._layerTree=layerTree;this._update();}
_update(){const showInternalLayers=this._layerViewHost.showInternalLayersSetting().get();const seenLayers=new Map();let root=null;if(this._layerTree){if(!showInternalLayers)
root=this._layerTree.contentRoot();if(!root)
root=this._layerTree.root();}
function updateLayer(layer){if(!layer.drawsContent()&&!showInternalLayers)
return;if(seenLayers.get(layer))
console.assert(false,'Duplicate layer: '+layer.id());seenLayers.set(layer,true);let node=layer[LayerViewer.LayerTreeElement._symbol];let parentLayer=layer.parent();while(parentLayer&&parentLayer!==root&&!parentLayer.drawsContent()&&!showInternalLayers)
parentLayer=parentLayer.parent();const parent=layer===root?this._treeOutline.rootElement():parentLayer[LayerViewer.LayerTreeElement._symbol];if(!parent){console.assert(false,'Parent is not in the tree');return;}
if(!node){node=new LayerViewer.LayerTreeElement(this,layer);parent.appendChild(node);if(!layer.drawsContent())
node.expand();}else{if(node.parent!==parent){const oldSelection=this._treeOutline.selectedTreeElement;if(node.parent)
node.parent.removeChild(node);parent.appendChild(node);if(oldSelection!==this._treeOutline.selectedTreeElement)
oldSelection.select();}
node._update();}}
if(root)
this._layerTree.forEachLayer(updateLayer.bind(this),root);const rootElement=this._treeOutline.rootElement();for(let node=rootElement.firstChild();node&&!node.root;){if(seenLayers.get(node._layer)){node=node.traverseNextTreeElement(false);}else{const nextNode=node.nextSibling||node.parent;node.parent.removeChild(node);if(node===this._lastHoveredNode)
this._lastHoveredNode=null;node=nextNode;}}
if(!this._treeOutline.selectedTreeElement){const elementToSelect=this._layerTree.contentRoot()||this._layerTree.root();if(elementToSelect)
elementToSelect[LayerViewer.LayerTreeElement._symbol].revealAndSelect(true);}}
_onMouseMove(event){const node=this._treeOutline.treeElementFromEvent(event);if(node===this._lastHoveredNode)
return;this._layerViewHost.hoverObject(this._selectionForNode(node));}
_selectedNodeChanged(node){this._layerViewHost.selectObject(this._selectionForNode(node));}
_onContextMenu(event){const selection=this._selectionForNode(this._treeOutline.treeElementFromEvent(event));const contextMenu=new UI.ContextMenu(event);this._layerViewHost.showContextMenu(contextMenu,selection);}
_selectionForNode(node){return node&&node._layer?new LayerViewer.LayerView.LayerSelection(node._layer):null;}};LayerViewer.LayerTreeElement=class extends UI.TreeElement{constructor(tree,layer){super();this._treeOutline=tree;this._layer=layer;this._layer[LayerViewer.LayerTreeElement._symbol]=this;this._update();}
_update(){const node=this._layer.nodeForSelfOrAncestor();const title=createDocumentFragment();title.createTextChild(node?node.simpleSelector():'#'+this._layer.id());const details=title.createChild('span','dimmed');details.textContent=Common.UIString(' (%d × %d)',this._layer.width(),this._layer.height());this.title=title;}
onselect(){this._treeOutline._selectedNodeChanged(this);return false;}
setHovered(hovered){this.listItemElement.classList.toggle('hovered',hovered);}};LayerViewer.LayerTreeElement._symbol=Symbol('layer');;LayerViewer.LayerView=function(){};LayerViewer.LayerView.prototype={hoverObject(selection){},selectObject(selection){},setLayerTree(layerTree){}};LayerViewer.LayerView.Selection=class{constructor(type,layer){this._type=type;this._layer=layer;}
static isEqual(a,b){return a&&b?a._isEqual(b):a===b;}
type(){return this._type;}
layer(){return this._layer;}
_isEqual(other){return false;}};LayerViewer.LayerView.Selection.Type={Layer:Symbol('Layer'),ScrollRect:Symbol('ScrollRect'),Snapshot:Symbol('Snapshot')};LayerViewer.LayerView.LayerSelection=class extends LayerViewer.LayerView.Selection{constructor(layer){console.assert(layer,'LayerSelection with empty layer');super(LayerViewer.LayerView.Selection.Type.Layer,layer);}
_isEqual(other){return other._type===LayerViewer.LayerView.Selection.Type.Layer&&other.layer().id()===this.layer().id();}};LayerViewer.LayerView.ScrollRectSelection=class extends LayerViewer.LayerView.Selection{constructor(layer,scrollRectIndex){super(LayerViewer.LayerView.Selection.Type.ScrollRect,layer);this.scrollRectIndex=scrollRectIndex;}
_isEqual(other){return other._type===LayerViewer.LayerView.Selection.Type.ScrollRect&&this.layer().id()===other.layer().id()&&this.scrollRectIndex===other.scrollRectIndex;}};LayerViewer.LayerView.SnapshotSelection=class extends LayerViewer.LayerView.Selection{constructor(layer,snapshot){super(LayerViewer.LayerView.Selection.Type.Snapshot,layer);this._snapshot=snapshot;}
_isEqual(other){return other._type===LayerViewer.LayerView.Selection.Type.Snapshot&&this.layer().id()===other.layer().id()&&this._snapshot===other._snapshot;}
snapshot(){return this._snapshot;}};LayerViewer.LayerViewHost=class{constructor(){this._views=[];this._selectedObject=null;this._hoveredObject=null;this._showInternalLayersSetting=Common.settings.createSetting('layersShowInternalLayers',false);}
registerView(layerView){this._views.push(layerView);}
setLayerTree(layerTree){this._target=layerTree.target();const selectedLayer=this._selectedObject&&this._selectedObject.layer();if(selectedLayer&&(!layerTree||!layerTree.layerById(selectedLayer.id())))
this.selectObject(null);const hoveredLayer=this._hoveredObject&&this._hoveredObject.layer();if(hoveredLayer&&(!layerTree||!layerTree.layerById(hoveredLayer.id())))
this.hoverObject(null);for(const view of this._views)
view.setLayerTree(layerTree);}
hoverObject(selection){if(LayerViewer.LayerView.Selection.isEqual(this._hoveredObject,selection))
return;this._hoveredObject=selection;const layer=selection&&selection.layer();this._toggleNodeHighlight(layer?layer.nodeForSelfOrAncestor():null);for(const view of this._views)
view.hoverObject(selection);}
selectObject(selection){if(LayerViewer.LayerView.Selection.isEqual(this._selectedObject,selection))
return;this._selectedObject=selection;for(const view of this._views)
view.selectObject(selection);}
selection(){return this._selectedObject;}
showContextMenu(contextMenu,selection){contextMenu.defaultSection().appendCheckboxItem(Common.UIString('Show internal layers'),this._toggleShowInternalLayers.bind(this),this._showInternalLayersSetting.get());const node=selection&&selection.layer()&&selection.layer().nodeForSelfOrAncestor();if(node)
contextMenu.appendApplicableItems(node);contextMenu.show();}
showInternalLayersSetting(){return this._showInternalLayersSetting;}
_toggleShowInternalLayers(){this._showInternalLayersSetting.set(!this._showInternalLayersSetting.get());}
_toggleNodeHighlight(node){if(node){node.highlightForTwoSeconds();return;}
SDK.OverlayModel.hideDOMNodeHighlight();}};;LayerViewer.Layers3DView=class extends UI.VBox{constructor(layerViewHost){super(true);this.registerRequiredCSS('layer_viewer/layers3DView.css');this.contentElement.classList.add('layers-3d-view');this._failBanner=new UI.VBox();this._failBanner.element.classList.add('full-widget-dimmed-banner');this._failBanner.element.createTextChild(Common.UIString('Layer information is not yet available.'));this._layerViewHost=layerViewHost;this._layerViewHost.registerView(this);this._transformController=new LayerViewer.TransformController(this.contentElement);this._transformController.addEventListener(LayerViewer.TransformController.Events.TransformChanged,this._update,this);this._initToolbar();this._canvasElement=this.contentElement.createChild('canvas');this._canvasElement.tabIndex=0;this._canvasElement.addEventListener('dblclick',this._onDoubleClick.bind(this),false);this._canvasElement.addEventListener('mousedown',this._onMouseDown.bind(this),false);this._canvasElement.addEventListener('mouseup',this._onMouseUp.bind(this),false);this._canvasElement.addEventListener('mouseleave',this._onMouseMove.bind(this),false);this._canvasElement.addEventListener('mousemove',this._onMouseMove.bind(this),false);this._canvasElement.addEventListener('contextmenu',this._onContextMenu.bind(this),false);this._lastSelection={};this._layerTree=null;this._textureManager=new LayerViewer.LayerTextureManager(this._update.bind(this));this._chromeTextures=[];this._rects=[];this._layerViewHost.showInternalLayersSetting().addChangeListener(this._update,this);}
setLayerTree(layerTree){this._layerTree=layerTree;this._layerTexture=null;delete this._oldTextureScale;if(this._showPaints())
this._textureManager.setLayerTree(layerTree);this._update();}
showImageForLayer(layer,imageURL){if(!imageURL){this._layerTexture=null;this._update();return;}
UI.loadImage(imageURL).then(image=>{const texture=image&&LayerViewer.LayerTextureManager._createTextureForImage(this._gl,image);this._layerTexture=texture?{layer:layer,texture:texture}:null;this._update();});}
onResize(){this._resizeCanvas();this._update();}
willHide(){this._textureManager.suspend();}
wasShown(){this._textureManager.resume();if(!this._needsUpdate)
return;this._resizeCanvas();this._update();}
updateLayerSnapshot(layer){this._textureManager.layerNeedsUpdate(layer);}
_setOutline(type,selection){this._lastSelection[type]=selection;this._update();}
hoverObject(selection){this._setOutline(LayerViewer.Layers3DView.OutlineType.Hovered,selection);}
selectObject(selection){this._setOutline(LayerViewer.Layers3DView.OutlineType.Hovered,null);this._setOutline(LayerViewer.Layers3DView.OutlineType.Selected,selection);}
snapshotForSelection(selection){if(selection.type()===LayerViewer.LayerView.Selection.Type.Snapshot){const snapshotWithRect=(selection).snapshot();snapshotWithRect.snapshot.addReference();return(Promise.resolve(snapshotWithRect));}
if(selection.layer()){const promise=selection.layer().snapshots()[0];if(promise)
return promise;}
return(Promise.resolve(null));}
_initGL(canvas){const gl=canvas.getContext('webgl');if(!gl)
return null;gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA);gl.enable(gl.BLEND);gl.clearColor(0.0,0.0,0.0,0.0);gl.enable(gl.DEPTH_TEST);return gl;}
_createShader(type,script){const shader=this._gl.createShader(type);this._gl.shaderSource(shader,script);this._gl.compileShader(shader);this._gl.attachShader(this._shaderProgram,shader);}
_initShaders(){this._shaderProgram=this._gl.createProgram();this._createShader(this._gl.FRAGMENT_SHADER,LayerViewer.Layers3DView.FragmentShader);this._createShader(this._gl.VERTEX_SHADER,LayerViewer.Layers3DView.VertexShader);this._gl.linkProgram(this._shaderProgram);this._gl.useProgram(this._shaderProgram);this._shaderProgram.vertexPositionAttribute=this._gl.getAttribLocation(this._shaderProgram,'aVertexPosition');this._gl.enableVertexAttribArray(this._shaderProgram.vertexPositionAttribute);this._shaderProgram.vertexColorAttribute=this._gl.getAttribLocation(this._shaderProgram,'aVertexColor');this._gl.enableVertexAttribArray(this._shaderProgram.vertexColorAttribute);this._shaderProgram.textureCoordAttribute=this._gl.getAttribLocation(this._shaderProgram,'aTextureCoord');this._gl.enableVertexAttribArray(this._shaderProgram.textureCoordAttribute);this._shaderProgram.pMatrixUniform=this._gl.getUniformLocation(this._shaderProgram,'uPMatrix');this._shaderProgram.samplerUniform=this._gl.getUniformLocation(this._shaderProgram,'uSampler');}
_resizeCanvas(){this._canvasElement.width=this._canvasElement.offsetWidth*window.devicePixelRatio;this._canvasElement.height=this._canvasElement.offsetHeight*window.devicePixelRatio;}
_updateTransformAndConstraints(){const paddingFraction=0.1;const viewport=this._layerTree.viewportSize();const baseWidth=viewport?viewport.width:this._dimensionsForAutoscale.width;const baseHeight=viewport?viewport.height:this._dimensionsForAutoscale.height;const canvasWidth=this._canvasElement.width;const canvasHeight=this._canvasElement.height;const paddingX=canvasWidth*paddingFraction;const paddingY=canvasHeight*paddingFraction;const scaleX=(canvasWidth-2*paddingX)/baseWidth;const scaleY=(canvasHeight-2*paddingY)/baseHeight;const viewScale=Math.min(scaleX,scaleY);const minScaleConstraint=Math.min(baseWidth/this._dimensionsForAutoscale.width,baseHeight/this._dimensionsForAutoscale.width)/2;this._transformController.setScaleConstraints(minScaleConstraint,10/viewScale);const scale=this._transformController.scale();const rotateX=this._transformController.rotateX();const rotateY=this._transformController.rotateY();this._scale=scale*viewScale;const textureScale=Number.constrain(this._scale,0.1,1);if(textureScale!==this._oldTextureScale){this._oldTextureScale=textureScale;this._textureManager.setScale(textureScale);this.dispatchEventToListeners(LayerViewer.Layers3DView.Events.ScaleChanged,textureScale);}
const scaleAndRotationMatrix=new WebKitCSSMatrix().scale(scale,scale,scale).translate(canvasWidth/2,canvasHeight/2,0).rotate(rotateX,rotateY,0).scale(viewScale,viewScale,viewScale).translate(-baseWidth/2,-baseHeight/2,0);let bounds;for(let i=0;i<this._rects.length;++i)
bounds=UI.Geometry.boundsForTransformedPoints(scaleAndRotationMatrix,this._rects[i].vertices,bounds);this._transformController.clampOffsets((paddingX-bounds.maxX)/window.devicePixelRatio,(canvasWidth-paddingX-bounds.minX)/window.devicePixelRatio,(paddingY-bounds.maxY)/window.devicePixelRatio,(canvasHeight-paddingY-bounds.minY)/window.devicePixelRatio);const offsetX=this._transformController.offsetX()*window.devicePixelRatio;const offsetY=this._transformController.offsetY()*window.devicePixelRatio;this._projectionMatrix=new WebKitCSSMatrix().translate(offsetX,offsetY,0).multiply(scaleAndRotationMatrix);const glProjectionMatrix=new WebKitCSSMatrix().scale(1,-1,-1).translate(-1,-1,0).scale(2/this._canvasElement.width,2/this._canvasElement.height,1/1000000).multiply(this._projectionMatrix);this._gl.uniformMatrix4fv(this._shaderProgram.pMatrixUniform,false,this._arrayFromMatrix(glProjectionMatrix));}
_arrayFromMatrix(m){return new Float32Array([m.m11,m.m12,m.m13,m.m14,m.m21,m.m22,m.m23,m.m24,m.m31,m.m32,m.m33,m.m34,m.m41,m.m42,m.m43,m.m44]);}
_initWhiteTexture(){this._whiteTexture=this._gl.createTexture();this._gl.bindTexture(this._gl.TEXTURE_2D,this._whiteTexture);const whitePixel=new Uint8Array([255,255,255,255]);this._gl.texImage2D(this._gl.TEXTURE_2D,0,this._gl.RGBA,1,1,0,this._gl.RGBA,this._gl.UNSIGNED_BYTE,whitePixel);}
_initChromeTextures(){function loadChromeTexture(index,url){UI.loadImage(url).then(image=>{this._chromeTextures[index]=image&&LayerViewer.LayerTextureManager._createTextureForImage(this._gl,image)||undefined;});}
loadChromeTexture.call(this,LayerViewer.Layers3DView.ChromeTexture.Left,'Images/chromeLeft.png');loadChromeTexture.call(this,LayerViewer.Layers3DView.ChromeTexture.Middle,'Images/chromeMiddle.png');loadChromeTexture.call(this,LayerViewer.Layers3DView.ChromeTexture.Right,'Images/chromeRight.png');}
_initGLIfNecessary(){if(this._gl)
return this._gl;this._gl=this._initGL(this._canvasElement);if(!this._gl)
return null;this._initShaders();this._initWhiteTexture();this._initChromeTextures();this._textureManager.setContext(this._gl);return this._gl;}
_calculateDepthsAndVisibility(){this._depthByLayerId={};let depth=0;const showInternalLayers=this._layerViewHost.showInternalLayersSetting().get();const root=showInternalLayers?this._layerTree.root():(this._layerTree.contentRoot()||this._layerTree.root());const queue=[root];this._depthByLayerId[root.id()]=0;this._visibleLayers=new Set();while(queue.length>0){const layer=queue.shift();if(showInternalLayers||layer.drawsContent())
this._visibleLayers.add(layer);const children=layer.children();for(let i=0;i<children.length;++i){this._depthByLayerId[children[i].id()]=++depth;queue.push(children[i]);}}
this._maxDepth=depth;}
_depthForLayer(layer){return this._depthByLayerId[layer.id()]*LayerViewer.Layers3DView.LayerSpacing;}
_calculateScrollRectDepth(layer,index){return this._depthForLayer(layer)+index*LayerViewer.Layers3DView.ScrollRectSpacing+1;}
_updateDimensionsForAutoscale(layer){this._dimensionsForAutoscale.width=Math.max(layer.width(),this._dimensionsForAutoscale.width);this._dimensionsForAutoscale.height=Math.max(layer.height(),this._dimensionsForAutoscale.height);}
_calculateLayerRect(layer){if(!this._visibleLayers.has(layer))
return;const selection=new LayerViewer.LayerView.LayerSelection(layer);const rect=new LayerViewer.Layers3DView.Rectangle(selection);rect.setVertices(layer.quad(),this._depthForLayer(layer));this._appendRect(rect);this._updateDimensionsForAutoscale(layer);}
_appendRect(rect){const selection=rect.relatedObject;const isSelected=LayerViewer.LayerView.Selection.isEqual(this._lastSelection[LayerViewer.Layers3DView.OutlineType.Selected],selection);const isHovered=LayerViewer.LayerView.Selection.isEqual(this._lastSelection[LayerViewer.Layers3DView.OutlineType.Hovered],selection);if(isSelected){rect.borderColor=LayerViewer.Layers3DView.SelectedBorderColor;}else if(isHovered){rect.borderColor=LayerViewer.Layers3DView.HoveredBorderColor;const fillColor=rect.fillColor||[255,255,255,1];const maskColor=LayerViewer.Layers3DView.HoveredImageMaskColor;rect.fillColor=[fillColor[0]*maskColor[0]/255,fillColor[1]*maskColor[1]/255,fillColor[2]*maskColor[2]/255,fillColor[3]*maskColor[3]];}else{rect.borderColor=LayerViewer.Layers3DView.BorderColor;}
rect.lineWidth=isSelected?LayerViewer.Layers3DView.SelectedBorderWidth:LayerViewer.Layers3DView.BorderWidth;this._rects.push(rect);}
_calculateLayerScrollRects(layer){const scrollRects=layer.scrollRects();for(let i=0;i<scrollRects.length;++i){const selection=new LayerViewer.LayerView.ScrollRectSelection(layer,i);const rect=new LayerViewer.Layers3DView.Rectangle(selection);rect.calculateVerticesFromRect(layer,scrollRects[i].rect,this._calculateScrollRectDepth(layer,i));rect.fillColor=LayerViewer.Layers3DView.ScrollRectBackgroundColor;this._appendRect(rect);}}
_calculateLayerTileRects(layer){const tiles=this._textureManager.tilesForLayer(layer);for(let i=0;i<tiles.length;++i){const tile=tiles[i];if(!tile.texture)
continue;const selection=new LayerViewer.LayerView.SnapshotSelection(layer,{rect:tile.rect,snapshot:tile.snapshot});const rect=new LayerViewer.Layers3DView.Rectangle(selection);rect.calculateVerticesFromRect(layer,tile.rect,this._depthForLayer(layer)+1);rect.texture=tile.texture;this._appendRect(rect);}}
_calculateRects(){this._rects=[];this._dimensionsForAutoscale={width:0,height:0};this._layerTree.forEachLayer(this._calculateLayerRect.bind(this));if(this._showSlowScrollRectsSetting.get())
this._layerTree.forEachLayer(this._calculateLayerScrollRects.bind(this));if(this._layerTexture&&this._visibleLayers.has(this._layerTexture.layer)){const layer=this._layerTexture.layer;const selection=new LayerViewer.LayerView.LayerSelection(layer);const rect=new LayerViewer.Layers3DView.Rectangle(selection);rect.setVertices(layer.quad(),this._depthForLayer(layer));rect.texture=this._layerTexture.texture;this._appendRect(rect);}else if(this._showPaints()){this._layerTree.forEachLayer(this._calculateLayerTileRects.bind(this));}}
_makeColorsArray(color){let colors=[];const normalizedColor=[color[0]/255,color[1]/255,color[2]/255,color[3]];for(let i=0;i<4;i++)
colors=colors.concat(normalizedColor);return colors;}
_setVertexAttribute(attribute,array,length){const gl=this._gl;const buffer=gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER,buffer);gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(array),gl.STATIC_DRAW);gl.vertexAttribPointer(attribute,length,gl.FLOAT,false,0,0);}
_drawRectangle(vertices,mode,color,texture){const gl=this._gl;const white=[255,255,255,1];color=color||white;this._setVertexAttribute(this._shaderProgram.vertexPositionAttribute,vertices,3);this._setVertexAttribute(this._shaderProgram.textureCoordAttribute,[0,1,1,1,1,0,0,0],2);this._setVertexAttribute(this._shaderProgram.vertexColorAttribute,this._makeColorsArray(color),color.length);if(texture){gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D,texture);gl.uniform1i(this._shaderProgram.samplerUniform,0);}else{gl.bindTexture(gl.TEXTURE_2D,this._whiteTexture);}
const numberOfVertices=vertices.length/3;gl.drawArrays(mode,0,numberOfVertices);}
_drawTexture(vertices,texture,color){this._drawRectangle(vertices,this._gl.TRIANGLE_FAN,color,texture);}
_drawViewportAndChrome(){const viewport=this._layerTree.viewportSize();if(!viewport)
return;const drawChrome=!Common.moduleSetting('frameViewerHideChromeWindow').get()&&this._chromeTextures.length>=3&&this._chromeTextures.indexOf(undefined)<0;const z=(this._maxDepth+1)*LayerViewer.Layers3DView.LayerSpacing;const borderWidth=Math.ceil(LayerViewer.Layers3DView.ViewportBorderWidth*this._scale);let vertices=[viewport.width,0,z,viewport.width,viewport.height,z,0,viewport.height,z,0,0,z];this._gl.lineWidth(borderWidth);this._drawRectangle(vertices,drawChrome?this._gl.LINE_STRIP:this._gl.LINE_LOOP,LayerViewer.Layers3DView.ViewportBorderColor);if(!drawChrome)
return;const borderAdjustment=LayerViewer.Layers3DView.ViewportBorderWidth/2;const viewportWidth=this._layerTree.viewportSize().width+2*borderAdjustment;const chromeHeight=this._chromeTextures[0].image.naturalHeight;const middleFragmentWidth=viewportWidth-this._chromeTextures[0].image.naturalWidth-this._chromeTextures[2].image.naturalWidth;let x=-borderAdjustment;const y=-chromeHeight;for(let i=0;i<this._chromeTextures.length;++i){const width=i===LayerViewer.Layers3DView.ChromeTexture.Middle?middleFragmentWidth:this._chromeTextures[i].image.naturalWidth;if(width<0||x+width>viewportWidth)
break;vertices=[x,y,z,x+width,y,z,x+width,y+chromeHeight,z,x,y+chromeHeight,z];this._drawTexture(vertices,(this._chromeTextures[i]));x+=width;}}
_drawViewRect(rect){const vertices=rect.vertices;if(rect.texture)
this._drawTexture(vertices,rect.texture,rect.fillColor||undefined);else if(rect.fillColor)
this._drawRectangle(vertices,this._gl.TRIANGLE_FAN,rect.fillColor);this._gl.lineWidth(rect.lineWidth);if(rect.borderColor)
this._drawRectangle(vertices,this._gl.LINE_LOOP,rect.borderColor);}
_update(){if(!this.isShowing()){this._needsUpdate=true;return;}
if(!this._layerTree||!this._layerTree.root()){this._failBanner.show(this.contentElement);return;}
const gl=this._initGLIfNecessary();if(!gl){this._failBanner.element.removeChildren();this._failBanner.element.appendChild(this._webglDisabledBanner());this._failBanner.show(this.contentElement);return;}
this._failBanner.detach();this._gl.viewportWidth=this._canvasElement.width;this._gl.viewportHeight=this._canvasElement.height;this._calculateDepthsAndVisibility();this._calculateRects();this._updateTransformAndConstraints();gl.viewport(0,0,gl.viewportWidth,gl.viewportHeight);gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);this._rects.forEach(this._drawViewRect.bind(this));this._drawViewportAndChrome();}
_webglDisabledBanner(){const fragment=this.contentElement.ownerDocument.createDocumentFragment();fragment.createChild('div').textContent=Common.UIString('Can\'t display layers,');fragment.createChild('div').textContent=Common.UIString('WebGL support is disabled in your browser.');fragment.appendChild(UI.formatLocalized('Check %s for possible reasons.',[UI.XLink.create('about:gpu')]));return fragment;}
_selectionFromEventPoint(event){if(!this._layerTree)
return null;let closestIntersectionPoint=Infinity;let closestObject=null;const projectionMatrix=new WebKitCSSMatrix().scale(1,-1,-1).translate(-1,-1,0).multiply(this._projectionMatrix);const x0=(event.clientX-this._canvasElement.totalOffsetLeft())*window.devicePixelRatio;const y0=-(event.clientY-this._canvasElement.totalOffsetTop())*window.devicePixelRatio;function checkIntersection(rect){if(!rect.relatedObject)
return;const t=rect.intersectWithLine(projectionMatrix,x0,y0);if(t<closestIntersectionPoint){closestIntersectionPoint=t;closestObject=rect.relatedObject;}}
this._rects.forEach(checkIntersection);return closestObject;}
_createVisibilitySetting(caption,name,value,toolbar){const setting=Common.settings.createSetting(name,value);setting.setTitle(Common.UIString(caption));setting.addChangeListener(this._update,this);toolbar.appendToolbarItem(new UI.ToolbarSettingCheckbox(setting));return setting;}
_initToolbar(){this._panelToolbar=this._transformController.toolbar();this.contentElement.appendChild(this._panelToolbar.element);this._showSlowScrollRectsSetting=this._createVisibilitySetting('Slow scroll rects','frameViewerShowSlowScrollRects',true,this._panelToolbar);this._showPaintsSetting=this._createVisibilitySetting('Paints','frameViewerShowPaints',true,this._panelToolbar);this._showPaintsSetting.addChangeListener(this._updatePaints,this);Common.moduleSetting('frameViewerHideChromeWindow').addChangeListener(this._update,this);}
_onContextMenu(event){const contextMenu=new UI.ContextMenu(event);contextMenu.defaultSection().appendItem(Common.UIString('Reset View'),this._transformController.resetAndNotify.bind(this._transformController),false);const selection=this._selectionFromEventPoint(event);if(selection&&selection.type()===LayerViewer.LayerView.Selection.Type.Snapshot){contextMenu.defaultSection().appendItem(Common.UIString('Show Paint Profiler'),this.dispatchEventToListeners.bind(this,LayerViewer.Layers3DView.Events.PaintProfilerRequested,selection),false);}
this._layerViewHost.showContextMenu(contextMenu,selection);}
_onMouseMove(event){if(event.which)
return;this._layerViewHost.hoverObject(this._selectionFromEventPoint(event));}
_onMouseDown(event){this._mouseDownX=event.clientX;this._mouseDownY=event.clientY;}
_onMouseUp(event){const maxDistanceInPixels=6;if(this._mouseDownX&&Math.abs(event.clientX-this._mouseDownX)<maxDistanceInPixels&&Math.abs(event.clientY-this._mouseDownY)<maxDistanceInPixels)
this._layerViewHost.selectObject(this._selectionFromEventPoint(event));delete this._mouseDownX;delete this._mouseDownY;}
_onDoubleClick(event){const selection=this._selectionFromEventPoint(event);if(selection&&(selection.type()===LayerViewer.LayerView.Selection.Type.Snapshot||selection.layer()))
this.dispatchEventToListeners(LayerViewer.Layers3DView.Events.PaintProfilerRequested,selection);event.stopPropagation();}
_updatePaints(){if(this._showPaints()){this._textureManager.setLayerTree(this._layerTree);this._textureManager.forceUpdate();}else{this._textureManager.reset();}
this._update();}
_showPaints(){return this._showPaintsSetting.get();}};LayerViewer.Layers3DView.LayerStyle;LayerViewer.Layers3DView.OutlineType={Hovered:'hovered',Selected:'selected'};LayerViewer.Layers3DView.Events={PaintProfilerRequested:Symbol('PaintProfilerRequested'),ScaleChanged:Symbol('ScaleChanged')};LayerViewer.Layers3DView.ChromeTexture={Left:0,Middle:1,Right:2};LayerViewer.Layers3DView.ScrollRectTitles={RepaintsOnScroll:Common.UIString('repaints on scroll'),TouchEventHandler:Common.UIString('touch event listener'),WheelEventHandler:Common.UIString('mousewheel event listener')};LayerViewer.Layers3DView.FragmentShader=''+'precision mediump float;\n'+'varying vec4 vColor;\n'+'varying vec2 vTextureCoord;\n'+'uniform sampler2D uSampler;\n'+'void main(void)\n'+'{\n'+'    gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t)) * vColor;\n'+'}';LayerViewer.Layers3DView.VertexShader=''+'attribute vec3 aVertexPosition;\n'+'attribute vec2 aTextureCoord;\n'+'attribute vec4 aVertexColor;\n'+'uniform mat4 uPMatrix;\n'+'varying vec2 vTextureCoord;\n'+'varying vec4 vColor;\n'+'void main(void)\n'+'{\n'+'gl_Position = uPMatrix * vec4(aVertexPosition, 1.0);\n'+'vColor = aVertexColor;\n'+'vTextureCoord = aTextureCoord;\n'+'}';LayerViewer.Layers3DView.HoveredBorderColor=[0,0,255,1];LayerViewer.Layers3DView.SelectedBorderColor=[0,255,0,1];LayerViewer.Layers3DView.BorderColor=[0,0,0,1];LayerViewer.Layers3DView.ViewportBorderColor=[160,160,160,1];LayerViewer.Layers3DView.ScrollRectBackgroundColor=[178,100,100,0.6];LayerViewer.Layers3DView.HoveredImageMaskColor=[200,200,255,1];LayerViewer.Layers3DView.BorderWidth=1;LayerViewer.Layers3DView.SelectedBorderWidth=2;LayerViewer.Layers3DView.ViewportBorderWidth=3;LayerViewer.Layers3DView.LayerSpacing=20;LayerViewer.Layers3DView.ScrollRectSpacing=4;LayerViewer.LayerTextureManager=class{constructor(textureUpdatedCallback){this._textureUpdatedCallback=textureUpdatedCallback;this._throttler=new Common.Throttler(0);this._scale=0;this._active=false;this.reset();}
static _createTextureForImage(gl,image){const texture=gl.createTexture();texture.image=image;gl.bindTexture(gl.TEXTURE_2D,texture);gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,1);gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,texture.image);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.bindTexture(gl.TEXTURE_2D,null);return texture;}
reset(){if(this._tilesByLayer)
this.setLayerTree(null);this._tilesByLayer=new Map();this._queue=[];}
setContext(glContext){this._gl=glContext;if(this._scale)
this._updateTextures();}
suspend(){this._active=false;}
resume(){this._active=true;if(this._queue.length)
this._update();}
setLayerTree(layerTree){const newLayers=new Set();const oldLayers=Array.from(this._tilesByLayer.keys());if(layerTree){layerTree.forEachLayer(layer=>{if(!layer.drawsContent())
return;newLayers.add(layer);if(!this._tilesByLayer.has(layer)){this._tilesByLayer.set(layer,[]);this.layerNeedsUpdate(layer);}});}
if(!oldLayers.length)
this.forceUpdate();for(const layer of oldLayers){if(newLayers.has(layer))
continue;this._tilesByLayer.get(layer).forEach(tile=>tile.dispose());this._tilesByLayer.delete(layer);}}
_setSnapshotsForLayer(layer,snapshots){const oldSnapshotsToTiles=new Map((this._tilesByLayer.get(layer)||[]).map(tile=>[tile.snapshot,tile]));const newTiles=[];const reusedTiles=[];for(const snapshot of snapshots){const oldTile=oldSnapshotsToTiles.get(snapshot);if(oldTile){reusedTiles.push(oldTile);oldSnapshotsToTiles.delete(oldTile);}else{newTiles.push(new LayerViewer.LayerTextureManager.Tile(snapshot));}}
this._tilesByLayer.set(layer,reusedTiles.concat(newTiles));for(const tile of oldSnapshotsToTiles.values())
tile.dispose();if(!this._gl||!this._scale)
return Promise.resolve();return Promise.all(newTiles.map(tile=>tile.update(this._gl,this._scale))).then(this._textureUpdatedCallback);}
setScale(scale){if(this._scale&&this._scale>=scale)
return;this._scale=scale;this._updateTextures();}
tilesForLayer(layer){return this._tilesByLayer.get(layer)||[];}
layerNeedsUpdate(layer){if(this._queue.indexOf(layer)<0)
this._queue.push(layer);if(this._active)
this._throttler.schedule(this._update.bind(this));}
forceUpdate(){this._queue.forEach(layer=>this._updateLayer(layer));this._queue=[];this._update();}
_update(){const layer=this._queue.shift();if(!layer)
return Promise.resolve();if(this._queue.length)
this._throttler.schedule(this._update.bind(this));return this._updateLayer(layer);}
_updateLayer(layer){return Promise.all(layer.snapshots()).then(snapshots=>this._setSnapshotsForLayer(layer,snapshots.filter(snapshot=>!!snapshot)));}
_updateTextures(){if(!this._gl)
return;if(!this._scale)
return;for(const tiles of this._tilesByLayer.values()){for(const tile of tiles){const promise=tile.updateScale(this._gl,this._scale);if(promise)
promise.then(this._textureUpdatedCallback);}}}};LayerViewer.Layers3DView.Rectangle=class{constructor(relatedObject){this.relatedObject=relatedObject;this.lineWidth=1;this.borderColor=null;this.fillColor=null;this.texture=null;}
setVertices(quad,z){this.vertices=[quad[0],quad[1],z,quad[2],quad[3],z,quad[4],quad[5],z,quad[6],quad[7],z];}
_calculatePointOnQuad(quad,ratioX,ratioY){const x0=quad[0];const y0=quad[1];const x1=quad[2];const y1=quad[3];const x2=quad[4];const y2=quad[5];const x3=quad[6];const y3=quad[7];const firstSidePointX=x0+ratioX*(x1-x0);const firstSidePointY=y0+ratioX*(y1-y0);const thirdSidePointX=x3+ratioX*(x2-x3);const thirdSidePointY=y3+ratioX*(y2-y3);const x=firstSidePointX+ratioY*(thirdSidePointX-firstSidePointX);const y=firstSidePointY+ratioY*(thirdSidePointY-firstSidePointY);return[x,y];}
calculateVerticesFromRect(layer,rect,z){const quad=layer.quad();const rx1=rect.x/layer.width();const rx2=(rect.x+rect.width)/layer.width();const ry1=rect.y/layer.height();const ry2=(rect.y+rect.height)/layer.height();const rectQuad=this._calculatePointOnQuad(quad,rx1,ry1).concat(this._calculatePointOnQuad(quad,rx2,ry1)).concat(this._calculatePointOnQuad(quad,rx2,ry2)).concat(this._calculatePointOnQuad(quad,rx1,ry2));this.setVertices(rectQuad,z);}
intersectWithLine(matrix,x0,y0){let i;const points=[];for(i=0;i<4;++i){points[i]=UI.Geometry.multiplyVectorByMatrixAndNormalize(new UI.Geometry.Vector(this.vertices[i*3],this.vertices[i*3+1],this.vertices[i*3+2]),matrix);}
const normal=UI.Geometry.crossProduct(UI.Geometry.subtract(points[1],points[0]),UI.Geometry.subtract(points[2],points[1]));const A=normal.x;const B=normal.y;const C=normal.z;const D=-(A*points[0].x+B*points[0].y+C*points[0].z);const t=-(D+A*x0+B*y0)/C;const pt=new UI.Geometry.Vector(x0,y0,t);const tVects=points.map(UI.Geometry.subtract.bind(null,pt));for(i=0;i<tVects.length;++i){const product=UI.Geometry.scalarProduct(normal,UI.Geometry.crossProduct(tVects[i],tVects[(i+1)%tVects.length]));if(product<0)
return undefined;}
return t;}};LayerViewer.LayerTextureManager.Tile=class{constructor(snapshotWithRect){this.snapshot=snapshotWithRect.snapshot;this.rect=snapshotWithRect.rect;this.scale=0;this.texture=null;}
dispose(){this.snapshot.release();if(this.texture){this._gl.deleteTexture(this.texture);this.texture=null;}}
updateScale(glContext,scale){if(this.texture&&this.scale>=scale)
return null;return this.update(glContext,scale);}
async update(glContext,scale){this._gl=glContext;this.scale=scale;const imageURL=await this.snapshot.replay(scale);const image=imageURL&&await UI.loadImage(imageURL);this.texture=image&&LayerViewer.LayerTextureManager._createTextureForImage(glContext,image);}};;LayerViewer.PaintProfilerView=class extends UI.HBox{constructor(showImageCallback){super(true);this.registerRequiredCSS('layer_viewer/paintProfiler.css');this.contentElement.classList.add('paint-profiler-overview');this._canvasContainer=this.contentElement.createChild('div','paint-profiler-canvas-container');this._progressBanner=this.contentElement.createChild('div','full-widget-dimmed-banner hidden');this._progressBanner.textContent=Common.UIString('Profiling\u2026');this._pieChart=new PerfUI.PieChart(55,this._formatPieChartTime.bind(this),true);this._pieChart.element.classList.add('paint-profiler-pie-chart');this.contentElement.appendChild(this._pieChart.element);this._showImageCallback=showImageCallback;this._canvas=this._canvasContainer.createChild('canvas','fill');this._context=this._canvas.getContext('2d');this._selectionWindow=new PerfUI.OverviewGrid.Window(this._canvasContainer);this._selectionWindow.addEventListener(PerfUI.OverviewGrid.Events.WindowChanged,this._onWindowChanged,this);this._innerBarWidth=4*window.devicePixelRatio;this._minBarHeight=window.devicePixelRatio;this._barPaddingWidth=2*window.devicePixelRatio;this._outerBarWidth=this._innerBarWidth+this._barPaddingWidth;this._pendingScale=1;this._scale=this._pendingScale;this._reset();}
static categories(){if(LayerViewer.PaintProfilerView._categories)
return LayerViewer.PaintProfilerView._categories;LayerViewer.PaintProfilerView._categories={shapes:new LayerViewer.PaintProfilerCategory('shapes',Common.UIString('Shapes'),'rgb(255, 161, 129)'),bitmap:new LayerViewer.PaintProfilerCategory('bitmap',Common.UIString('Bitmap'),'rgb(136, 196, 255)'),text:new LayerViewer.PaintProfilerCategory('text',Common.UIString('Text'),'rgb(180, 255, 137)'),misc:new LayerViewer.PaintProfilerCategory('misc',Common.UIString('Misc'),'rgb(206, 160, 255)')};return LayerViewer.PaintProfilerView._categories;}
static _initLogItemCategories(){if(LayerViewer.PaintProfilerView._logItemCategoriesMap)
return LayerViewer.PaintProfilerView._logItemCategoriesMap;const categories=LayerViewer.PaintProfilerView.categories();const logItemCategories={};logItemCategories['Clear']=categories['misc'];logItemCategories['DrawPaint']=categories['misc'];logItemCategories['DrawData']=categories['misc'];logItemCategories['SetMatrix']=categories['misc'];logItemCategories['PushCull']=categories['misc'];logItemCategories['PopCull']=categories['misc'];logItemCategories['Translate']=categories['misc'];logItemCategories['Scale']=categories['misc'];logItemCategories['Concat']=categories['misc'];logItemCategories['Restore']=categories['misc'];logItemCategories['SaveLayer']=categories['misc'];logItemCategories['Save']=categories['misc'];logItemCategories['BeginCommentGroup']=categories['misc'];logItemCategories['AddComment']=categories['misc'];logItemCategories['EndCommentGroup']=categories['misc'];logItemCategories['ClipRect']=categories['misc'];logItemCategories['ClipRRect']=categories['misc'];logItemCategories['ClipPath']=categories['misc'];logItemCategories['ClipRegion']=categories['misc'];logItemCategories['DrawPoints']=categories['shapes'];logItemCategories['DrawRect']=categories['shapes'];logItemCategories['DrawOval']=categories['shapes'];logItemCategories['DrawRRect']=categories['shapes'];logItemCategories['DrawPath']=categories['shapes'];logItemCategories['DrawVertices']=categories['shapes'];logItemCategories['DrawDRRect']=categories['shapes'];logItemCategories['DrawBitmap']=categories['bitmap'];logItemCategories['DrawBitmapRectToRect']=categories['bitmap'];logItemCategories['DrawBitmapMatrix']=categories['bitmap'];logItemCategories['DrawBitmapNine']=categories['bitmap'];logItemCategories['DrawSprite']=categories['bitmap'];logItemCategories['DrawPicture']=categories['bitmap'];logItemCategories['DrawText']=categories['text'];logItemCategories['DrawPosText']=categories['text'];logItemCategories['DrawPosTextH']=categories['text'];logItemCategories['DrawTextOnPath']=categories['text'];LayerViewer.PaintProfilerView._logItemCategoriesMap=logItemCategories;return logItemCategories;}
static _categoryForLogItem(logItem){const method=logItem.method.toTitleCase();const logItemCategories=LayerViewer.PaintProfilerView._initLogItemCategories();let result=logItemCategories[method];if(!result){result=LayerViewer.PaintProfilerView.categories()['misc'];logItemCategories[method]=result;}
return result;}
onResize(){this._update();}
async setSnapshotAndLog(snapshot,log,clipRect){this._reset();this._snapshot=snapshot;if(this._snapshot)
this._snapshot.addReference();this._log=log;this._logCategories=this._log.map(LayerViewer.PaintProfilerView._categoryForLogItem);if(!this._snapshot){this._update();this._pieChart.setTotal(0);this._selectionWindow.setEnabled(false);return;}
this._selectionWindow.setEnabled(true);this._progressBanner.classList.remove('hidden');this._updateImage();const profiles=await snapshot.profile(clipRect);this._progressBanner.classList.add('hidden');this._profiles=profiles;this._update();this._updatePieChart();}
setScale(scale){const needsUpdate=scale>this._scale;const predictiveGrowthFactor=2;this._pendingScale=Math.min(1,scale*predictiveGrowthFactor);if(needsUpdate&&this._snapshot)
this._updateImage();}
_update(){this._canvas.width=this._canvasContainer.clientWidth*window.devicePixelRatio;this._canvas.height=this._canvasContainer.clientHeight*window.devicePixelRatio;this._samplesPerBar=0;if(!this._profiles||!this._profiles.length)
return;const maxBars=Math.floor((this._canvas.width-2*this._barPaddingWidth)/this._outerBarWidth);const sampleCount=this._log.length;this._samplesPerBar=Math.ceil(sampleCount/maxBars);let maxBarTime=0;const barTimes=[];const barHeightByCategory=[];let heightByCategory={};for(let i=0,lastBarIndex=0,lastBarTime=0;i<sampleCount;){let categoryName=(this._logCategories[i]&&this._logCategories[i].name)||'misc';const sampleIndex=this._log[i].commandIndex;for(let row=0;row<this._profiles.length;row++){const sample=this._profiles[row][sampleIndex];lastBarTime+=sample;heightByCategory[categoryName]=(heightByCategory[categoryName]||0)+sample;}
++i;if(i-lastBarIndex===this._samplesPerBar||i===sampleCount){const factor=this._profiles.length*(i-lastBarIndex);lastBarTime/=factor;for(categoryName in heightByCategory)
heightByCategory[categoryName]/=factor;barTimes.push(lastBarTime);barHeightByCategory.push(heightByCategory);if(lastBarTime>maxBarTime)
maxBarTime=lastBarTime;lastBarTime=0;heightByCategory={};lastBarIndex=i;}}
const paddingHeight=4*window.devicePixelRatio;const scale=(this._canvas.height-paddingHeight-this._minBarHeight)/maxBarTime;for(let i=0;i<barTimes.length;++i){for(const categoryName in barHeightByCategory[i])
barHeightByCategory[i][categoryName]*=(barTimes[i]*scale+this._minBarHeight)/barTimes[i];this._renderBar(i,barHeightByCategory[i]);}}
_renderBar(index,heightByCategory){const categories=LayerViewer.PaintProfilerView.categories();let currentHeight=0;const x=this._barPaddingWidth+index*this._outerBarWidth;for(const categoryName in categories){if(!heightByCategory[categoryName])
continue;currentHeight+=heightByCategory[categoryName];const y=this._canvas.height-currentHeight;this._context.fillStyle=categories[categoryName].color;this._context.fillRect(x,y,this._innerBarWidth,heightByCategory[categoryName]);}}
_onWindowChanged(){this.dispatchEventToListeners(LayerViewer.PaintProfilerView.Events.WindowChanged);this._updatePieChart();if(this._updateImageTimer)
return;this._updateImageTimer=setTimeout(this._updateImage.bind(this),100);}
_updatePieChart(){const window=this.selectionWindow();if(!this._profiles||!this._profiles.length||!window)
return;let totalTime=0;const timeByCategory={};for(let i=window.left;i<window.right;++i){const logEntry=this._log[i];const category=LayerViewer.PaintProfilerView._categoryForLogItem(logEntry);timeByCategory[category.color]=timeByCategory[category.color]||0;for(let j=0;j<this._profiles.length;++j){const time=this._profiles[j][logEntry.commandIndex];totalTime+=time;timeByCategory[category.color]+=time;}}
this._pieChart.setTotal(totalTime/this._profiles.length);for(const color in timeByCategory)
this._pieChart.addSlice(timeByCategory[color]/this._profiles.length,color);}
_formatPieChartTime(value){return Number.millisToString(value*1000,true);}
selectionWindow(){if(!this._log)
return null;const screenLeft=this._selectionWindow.windowLeft*this._canvas.width;const screenRight=this._selectionWindow.windowRight*this._canvas.width;const barLeft=Math.floor(screenLeft/this._outerBarWidth);const barRight=Math.floor((screenRight+this._innerBarWidth-this._barPaddingWidth/2)/this._outerBarWidth);const stepLeft=Number.constrain(barLeft*this._samplesPerBar,0,this._log.length-1);const stepRight=Number.constrain(barRight*this._samplesPerBar,0,this._log.length);return{left:stepLeft,right:stepRight};}
_updateImage(){delete this._updateImageTimer;let left;let right;const window=this.selectionWindow();if(this._profiles&&this._profiles.length&&window){left=this._log[window.left].commandIndex;right=this._log[window.right-1].commandIndex;}
const scale=this._pendingScale;this._snapshot.replay(scale,left,right).then(image=>{if(!image)
return;this._scale=scale;this._showImageCallback(image);});}
_reset(){if(this._snapshot)
this._snapshot.release();this._snapshot=null;this._profiles=null;this._selectionWindow.reset();this._selectionWindow.setEnabled(false);}};LayerViewer.PaintProfilerView.Events={WindowChanged:Symbol('WindowChanged')};LayerViewer.PaintProfilerCommandLogView=class extends UI.ThrottledWidget{constructor(){super();this.setMinimumSize(100,25);this.element.classList.add('overflow-auto');this._treeOutline=new UI.TreeOutlineInShadow();this.element.appendChild(this._treeOutline.element);this._log=[];}
setCommandLog(log){this._log=log;this._treeItemCache=new Map();this.updateWindow({left:0,right:this._log.length});}
_appendLogItem(logItem){let treeElement=this._treeItemCache.get(logItem);if(!treeElement){treeElement=new LayerViewer.LogTreeElement(this,logItem);this._treeItemCache.set(logItem,treeElement);}else if(treeElement.parent){return;}
this._treeOutline.appendChild(treeElement);}
updateWindow(selectionWindow){this._selectionWindow=selectionWindow;this.update();}
doUpdate(){if(!this._selectionWindow||!this._log.length){this._treeOutline.removeChildren();return Promise.resolve();}
const root=this._treeOutline.rootElement();for(;;){const child=root.firstChild();if(!child||child._logItem.commandIndex>=this._selectionWindow.left)
break;root.removeChildAtIndex(0);}
for(;;){const child=root.lastChild();if(!child||child._logItem.commandIndex<this._selectionWindow.right)
break;root.removeChildAtIndex(root.children().length-1);}
for(let i=this._selectionWindow.left,right=this._selectionWindow.right;i<right;++i)
this._appendLogItem(this._log[i]);return Promise.resolve();}};LayerViewer.LogTreeElement=class extends UI.TreeElement{constructor(ownerView,logItem){super('',!!logItem.params);this._logItem=logItem;this._ownerView=ownerView;this._filled=false;}
onattach(){this._update();}
onpopulate(){for(const param in this._logItem.params)
LayerViewer.LogPropertyTreeElement._appendLogPropertyItem(this,param,this._logItem.params[param]);}
_paramToString(param,name){if(typeof param!=='object')
return typeof param==='string'&&param.length>100?name:JSON.stringify(param);let str='';let keyCount=0;for(const key in param){if(++keyCount>4||typeof param[key]==='object'||(typeof param[key]==='string'&&param[key].length>100))
return name;if(str)
str+=', ';str+=param[key];}
return str;}
_paramsToString(params){let str='';for(const key in params){if(str)
str+=', ';str+=this._paramToString(params[key],key);}
return str;}
_update(){const title=createDocumentFragment();title.createTextChild(this._logItem.method+'('+this._paramsToString(this._logItem.params)+')');this.title=title;}};LayerViewer.LogPropertyTreeElement=class extends UI.TreeElement{constructor(property){super();this._property=property;}
static _appendLogPropertyItem(element,name,value){const treeElement=new LayerViewer.LogPropertyTreeElement({name:name,value:value});element.appendChild(treeElement);if(value&&typeof value==='object'){for(const property in value)
LayerViewer.LogPropertyTreeElement._appendLogPropertyItem(treeElement,property,value[property]);}}
onattach(){const title=createDocumentFragment();const nameElement=title.createChild('span','name');nameElement.textContent=this._property.name;const separatorElement=title.createChild('span','separator');separatorElement.textContent=': ';if(this._property.value===null||typeof this._property.value!=='object'){const valueElement=title.createChild('span','value');valueElement.textContent=JSON.stringify(this._property.value);valueElement.classList.add('cm-js-'+(this._property.value===null?'null':typeof this._property.value));}
this.title=title;}};LayerViewer.PaintProfilerCategory=class{constructor(name,title,color){this.name=name;this.title=title;this.color=color;}};;LayerViewer.TransformController=class extends Common.Object{constructor(element,disableRotate){super();this._shortcuts={};this.element=element;if(this.element.tabIndex<0)
this.element.tabIndex=0;this._registerShortcuts();UI.installDragHandle(element,this._onDragStart.bind(this),this._onDrag.bind(this),this._onDragEnd.bind(this),'move',null);element.addEventListener('keydown',this._onKeyDown.bind(this),false);element.addEventListener('keyup',this._onKeyUp.bind(this),false);element.addEventListener('mousewheel',this._onMouseWheel.bind(this),false);this._minScale=0;this._maxScale=Infinity;this._controlPanelToolbar=new UI.Toolbar('transform-control-panel');this._modeButtons={};if(!disableRotate){const panModeButton=new UI.ToolbarToggle(Common.UIString('Pan mode (X)'),'largeicon-pan');panModeButton.addEventListener(UI.ToolbarButton.Events.Click,this._setMode.bind(this,LayerViewer.TransformController.Modes.Pan));this._modeButtons[LayerViewer.TransformController.Modes.Pan]=panModeButton;this._controlPanelToolbar.appendToolbarItem(panModeButton);const rotateModeButton=new UI.ToolbarToggle(Common.UIString('Rotate mode (V)'),'largeicon-rotate');rotateModeButton.addEventListener(UI.ToolbarButton.Events.Click,this._setMode.bind(this,LayerViewer.TransformController.Modes.Rotate));this._modeButtons[LayerViewer.TransformController.Modes.Rotate]=rotateModeButton;this._controlPanelToolbar.appendToolbarItem(rotateModeButton);}
this._setMode(LayerViewer.TransformController.Modes.Pan);const resetButton=new UI.ToolbarButton(Common.UIString('Reset transform (0)'),'largeicon-center');resetButton.addEventListener(UI.ToolbarButton.Events.Click,this.resetAndNotify.bind(this,undefined));this._controlPanelToolbar.appendToolbarItem(resetButton);this._reset();}
toolbar(){return this._controlPanelToolbar;}
_onKeyDown(event){if(event.keyCode===UI.KeyboardShortcut.Keys.Shift.code){this._toggleMode();return;}
const shortcutKey=UI.KeyboardShortcut.makeKeyFromEventIgnoringModifiers(event);const handler=this._shortcuts[shortcutKey];if(handler&&handler(event))
event.consume();}
_onKeyUp(event){if(event.keyCode===UI.KeyboardShortcut.Keys.Shift.code)
this._toggleMode();}
_addShortcuts(keys,handler){for(let i=0;i<keys.length;++i)
this._shortcuts[keys[i].key]=handler;}
_registerShortcuts(){this._addShortcuts(UI.ShortcutsScreen.LayersPanelShortcuts.ResetView,this.resetAndNotify.bind(this));this._addShortcuts(UI.ShortcutsScreen.LayersPanelShortcuts.PanMode,this._setMode.bind(this,LayerViewer.TransformController.Modes.Pan));this._addShortcuts(UI.ShortcutsScreen.LayersPanelShortcuts.RotateMode,this._setMode.bind(this,LayerViewer.TransformController.Modes.Rotate));const zoomFactor=1.1;this._addShortcuts(UI.ShortcutsScreen.LayersPanelShortcuts.ZoomIn,this._onKeyboardZoom.bind(this,zoomFactor));this._addShortcuts(UI.ShortcutsScreen.LayersPanelShortcuts.ZoomOut,this._onKeyboardZoom.bind(this,1/zoomFactor));this._addShortcuts(UI.ShortcutsScreen.LayersPanelShortcuts.Up,this._onKeyboardPanOrRotate.bind(this,0,-1));this._addShortcuts(UI.ShortcutsScreen.LayersPanelShortcuts.Down,this._onKeyboardPanOrRotate.bind(this,0,1));this._addShortcuts(UI.ShortcutsScreen.LayersPanelShortcuts.Left,this._onKeyboardPanOrRotate.bind(this,-1,0));this._addShortcuts(UI.ShortcutsScreen.LayersPanelShortcuts.Right,this._onKeyboardPanOrRotate.bind(this,1,0));}
_postChangeEvent(){this.dispatchEventToListeners(LayerViewer.TransformController.Events.TransformChanged);}
_reset(){this._scale=1;this._offsetX=0;this._offsetY=0;this._rotateX=0;this._rotateY=0;}
_toggleMode(){this._setMode(this._mode===LayerViewer.TransformController.Modes.Pan?LayerViewer.TransformController.Modes.Rotate:LayerViewer.TransformController.Modes.Pan);}
_setMode(mode){if(this._mode===mode)
return;this._mode=mode;this._updateModeButtons();this.element.focus();}
_updateModeButtons(){for(const mode in this._modeButtons)
this._modeButtons[mode].setToggled(mode===this._mode);}
resetAndNotify(event){this._reset();this._postChangeEvent();if(event)
event.preventDefault();this.element.focus();}
setScaleConstraints(minScale,maxScale){this._minScale=minScale;this._maxScale=maxScale;this._scale=Number.constrain(this._scale,minScale,maxScale);}
clampOffsets(minX,maxX,minY,maxY){this._offsetX=Number.constrain(this._offsetX,minX,maxX);this._offsetY=Number.constrain(this._offsetY,minY,maxY);}
scale(){return this._scale;}
offsetX(){return this._offsetX;}
offsetY(){return this._offsetY;}
rotateX(){return this._rotateX;}
rotateY(){return this._rotateY;}
_onScale(scaleFactor,x,y){scaleFactor=Number.constrain(this._scale*scaleFactor,this._minScale,this._maxScale)/this._scale;this._scale*=scaleFactor;this._offsetX-=(x-this._offsetX)*(scaleFactor-1);this._offsetY-=(y-this._offsetY)*(scaleFactor-1);this._postChangeEvent();}
_onPan(offsetX,offsetY){this._offsetX+=offsetX;this._offsetY+=offsetY;this._postChangeEvent();}
_onRotate(rotateX,rotateY){this._rotateX=rotateX;this._rotateY=rotateY;this._postChangeEvent();}
_onKeyboardZoom(zoomFactor){this._onScale(zoomFactor,this.element.clientWidth/2,this.element.clientHeight/2);}
_onKeyboardPanOrRotate(xMultiplier,yMultiplier){const panStepInPixels=6;const rotateStepInDegrees=5;if(this._mode===LayerViewer.TransformController.Modes.Rotate){this._onRotate(this._rotateX+yMultiplier*rotateStepInDegrees,this._rotateY+xMultiplier*rotateStepInDegrees);}else{this._onPan(xMultiplier*panStepInPixels,yMultiplier*panStepInPixels);}}
_onMouseWheel(event){const zoomFactor=1.1;const mouseWheelZoomSpeed=1/120;const scaleFactor=Math.pow(zoomFactor,event.wheelDeltaY*mouseWheelZoomSpeed);this._onScale(scaleFactor,event.clientX-this.element.totalOffsetLeft(),event.clientY-this.element.totalOffsetTop());}
_onDrag(event){if(this._mode===LayerViewer.TransformController.Modes.Rotate){this._onRotate(this._oldRotateX+(this._originY-event.clientY)/this.element.clientHeight*180,this._oldRotateY-(this._originX-event.clientX)/this.element.clientWidth*180);}else{this._onPan(event.clientX-this._originX,event.clientY-this._originY);this._originX=event.clientX;this._originY=event.clientY;}}
_onDragStart(event){this.element.focus();this._originX=event.clientX;this._originY=event.clientY;this._oldRotateX=this._rotateX;this._oldRotateY=this._rotateY;return true;}
_onDragEnd(){delete this._originX;delete this._originY;delete this._oldRotateX;delete this._oldRotateY;}};LayerViewer.TransformController.Events={TransformChanged:Symbol('TransformChanged')};LayerViewer.TransformController.Modes={Pan:'Pan',Rotate:'Rotate',};;Runtime.cachedResources["layer_viewer/layers3DView.css"]="/*\n * Copyright 2016 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n.layers-3d-view {\n    overflow: hidden;\n    -webkit-user-select: none;\n}\n\ncanvas {\n    flex: 1 1;\n}\n\n/*# sourceURL=layer_viewer/layers3DView.css */";Runtime.cachedResources["layer_viewer/paintProfiler.css"]="/*\n * Copyright 2016 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n.paint-profiler-overview {\n    background-color: #eee;\n}\n\n.paint-profiler-canvas-container {\n    flex: auto;\n    position: relative;\n}\n\n.paint-profiler-pie-chart {\n    width: 60px !important;\n    height: 60px !important;\n    padding: 2px;\n    overflow: hidden;\n    font-size: 10px;\n}\n\n.paint-profiler-canvas-container canvas {\n    z-index: 200;\n    background-color: white;\n    opacity: 0.95;\n    height: 100%;\n    width: 100%;\n}\n\n.paint-profiler-canvas-container .overview-grid-dividers-background,\n.paint-profiler-canvas-container .overview-grid-window {\n    bottom: 0;\n    height: auto;\n}\n\n.paint-profiler-canvas-container .overview-grid-window-resizer {\n    z-index: 2000;\n}\n\n/*# sourceURL=layer_viewer/paintProfiler.css */";Runtime.cachedResources["layer_viewer/layerDetailsView.css"]="/*\n * Copyright 2016 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\ntable td {\n    padding-left: 8px;\n}\n\ntable td:first-child {\n    font-weight: bold;\n}\n\n.scroll-rect.active {\n    background-color: rgba(100, 100, 100, 0.2);\n}\n\nul {\n    list-style: none;\n    -webkit-padding-start: 0;\n    -webkit-margin-before: 0;\n    -webkit-margin-after: 0;\n}\n\na {\n    padding: 8px;\n    display: block;\n}\n\n/*# sourceURL=layer_viewer/layerDetailsView.css */";