1/* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17import {assertDefined} from 'common/assert_utils'; 18import {TraceRect} from 'trace/trace_rect'; 19import {TraceRectBuilder} from 'trace/trace_rect_builder'; 20import {HierarchyTreeNode} from 'trace/tree_node/hierarchy_tree_node'; 21 22class RectVcFactory { 23 private static DEPTH_MAGNIFICATION = 4; 24 25 makeNodeRect( 26 node: HierarchyTreeNode, 27 leftShift: number, 28 topShift: number, 29 scaleX: number, 30 scaleY: number, 31 newScaleX: number, 32 newScaleY: number, 33 depth: number, 34 ): TraceRect { 35 const nodeLeft = assertDefined( 36 node.getEagerPropertyByName('left'), 37 ).getValue(); 38 const nodeTranslationX = assertDefined( 39 node.getEagerPropertyByName('translationX'), 40 ).getValue(); 41 const nodeWidth = assertDefined( 42 node.getEagerPropertyByName('width'), 43 ).getValue(); 44 45 const nodeTop = assertDefined( 46 node.getEagerPropertyByName('top'), 47 ).getValue(); 48 const nodeTranslationY = assertDefined( 49 node.getEagerPropertyByName('translationY'), 50 ).getValue(); 51 const nodeHeight = assertDefined( 52 node.getEagerPropertyByName('height'), 53 ).getValue(); 54 55 const nodeAlpha = node.getEagerPropertyByName('alpha')?.getValue() ?? 0; 56 57 const rectLeft = 58 leftShift + 59 (nodeLeft + nodeTranslationX) * scaleX + 60 (nodeWidth * (scaleX - newScaleX)) / 2; 61 const rectTop = 62 topShift + 63 (nodeTop + nodeTranslationY) * scaleY + 64 (nodeHeight * (scaleY - newScaleY)) / 2; 65 66 const rect = new TraceRectBuilder() 67 .setX(rectLeft) 68 .setY(rectTop) 69 .setWidth(nodeWidth * newScaleX) 70 .setHeight(nodeHeight * newScaleY) 71 .setId(node.id) 72 .setName(node.name) 73 .setCornerRadius(0) 74 .setGroupId(0) 75 .setIsVisible( 76 node.getEagerPropertyByName('isComputedVisible')?.getValue() ?? false, 77 ) 78 .setIsDisplay(false) 79 .setIsVirtual(false) 80 .setDepth(depth * RectVcFactory.DEPTH_MAGNIFICATION) 81 .setOpacity(nodeAlpha) 82 .build(); 83 84 return rect; 85 } 86} 87export const rectsFactory = new RectVcFactory(); 88 89export class RectsComputation { 90 private readonly rectsFactory = new RectVcFactory(); 91 private root: HierarchyTreeNode | undefined; 92 93 setRoot(value: HierarchyTreeNode): this { 94 this.root = value; 95 return this; 96 } 97 98 executeInPlace(): void { 99 if (!this.root) { 100 throw Error('root not set'); 101 } 102 103 this.addRects(this.root, 0, 0, 1, 1, 0); 104 } 105 106 private addRects( 107 node: HierarchyTreeNode, 108 leftShift: number, 109 topShift: number, 110 scaleX: number, 111 scaleY: number, 112 depth: number, 113 ) { 114 const newScaleX = 115 scaleX * assertDefined(node.getEagerPropertyByName('scaleX')).getValue(); 116 const newScaleY = 117 scaleY * assertDefined(node.getEagerPropertyByName('scaleY')).getValue(); 118 119 const rect = this.rectsFactory.makeNodeRect( 120 node, 121 leftShift, 122 topShift, 123 scaleX, 124 scaleY, 125 newScaleX, 126 newScaleY, 127 depth, 128 ); 129 node.setRects([rect]); 130 131 node.getAllChildren().forEach((child) => { 132 this.addRects( 133 child, 134 rect.x - 135 assertDefined(node.getEagerPropertyByName('scrollX')).getValue(), 136 rect.y - 137 assertDefined(node.getEagerPropertyByName('scrollY')).getValue(), 138 newScaleX, 139 newScaleY, 140 depth + 1, 141 ); 142 }); 143 } 144} 145