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