xref: /aosp_15_r20/development/tools/winscope/src/parsers/view_capture/computations/rects_computation.ts (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
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      .setIsActiveDisplay(false)
80      .setDepth(depth * RectVcFactory.DEPTH_MAGNIFICATION)
81      .setOpacity(nodeAlpha)
82      .setIsSpy(false)
83      .build();
84
85    return rect;
86  }
87}
88export const rectsFactory = new RectVcFactory();
89
90export class RectsComputation {
91  private readonly rectsFactory = new RectVcFactory();
92  private root: HierarchyTreeNode | undefined;
93
94  setRoot(value: HierarchyTreeNode): this {
95    this.root = value;
96    return this;
97  }
98
99  executeInPlace(): void {
100    if (!this.root) {
101      throw new Error('root not set in VC rects computation');
102    }
103
104    this.addRects(this.root, 0, 0, 1, 1, 0);
105  }
106
107  private addRects(
108    node: HierarchyTreeNode,
109    leftShift: number,
110    topShift: number,
111    scaleX: number,
112    scaleY: number,
113    depth: number,
114  ) {
115    const newScaleX =
116      scaleX * assertDefined(node.getEagerPropertyByName('scaleX')).getValue();
117    const newScaleY =
118      scaleY * assertDefined(node.getEagerPropertyByName('scaleY')).getValue();
119
120    const rect = this.rectsFactory.makeNodeRect(
121      node,
122      leftShift,
123      topShift,
124      scaleX,
125      scaleY,
126      newScaleX,
127      newScaleY,
128      depth,
129    );
130    node.setRects([rect]);
131
132    node.getAllChildren().forEach((child) => {
133      this.addRects(
134        child,
135        rect.x -
136          assertDefined(node.getEagerPropertyByName('scrollX')).getValue(),
137        rect.y -
138          assertDefined(node.getEagerPropertyByName('scrollY')).getValue(),
139        newScaleX,
140        newScaleY,
141        depth + 1,
142      );
143    });
144  }
145}
146