• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { BaseStruct, dataFilterHandler, drawLoadingFrame, isFrameContainPoint, Render } from './ProcedureWorkerCommon';
17import { TraceRow } from '../../component/trace/base/TraceRow';
18import { ColorUtils } from '../../component/trace/base/ColorUtils';
19import { SpSystemTrace } from '../../component/SpSystemTrace';
20
21export class XpowerRender extends Render {
22  renderMainThread(
23    xpowerReq: {
24      context: CanvasRenderingContext2D;
25      useCache: boolean;
26      type: string;
27      maxValue: number;
28      minValue: number;
29      index: number;
30      maxName: string;
31    },
32    row: TraceRow<XpowerStruct>
33  ): void {
34    XpowerStruct.index = xpowerReq.index;
35    let xpowerList = row.dataList;
36    let xpowerFilter = row.dataListCache;
37    dataFilterHandler(xpowerList, xpowerFilter, {
38      startKey: 'startNS',
39      durKey: 'dur',
40      startNS: TraceRow.range?.startNS ?? 0,
41      endNS: TraceRow.range?.endNS ?? 0,
42      totalNS: TraceRow.range?.totalNS ?? 0,
43      frame: row.frame,
44      paddingTop: 5,
45      useCache: xpowerReq.useCache || !(TraceRow.range?.refresh ?? false),
46    });
47    drawLoadingFrame(xpowerReq.context, xpowerFilter, row);
48    xpowerReq.context.beginPath();
49    let find = false;
50    for (let re of xpowerFilter) {
51      XpowerStruct.draw(xpowerReq.context, re, xpowerReq.maxValue, xpowerReq.minValue);
52      if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) {
53        XpowerStruct.hoverXpowerStruct = re;
54        find = true;
55      }
56    }
57    if (!find && row.isHover) {
58      XpowerStruct.hoverXpowerStruct = undefined;
59    }
60    xpowerReq.context.closePath();
61    let s = xpowerReq.maxName;
62    let textMetrics = xpowerReq.context.measureText(s);
63    xpowerReq.context.globalAlpha = 0.8;
64    xpowerReq.context.fillStyle = '#f0f0f0';
65    xpowerReq.context.fillRect(0, 5, textMetrics.width + 8, 18);
66    xpowerReq.context.globalAlpha = 1;
67    xpowerReq.context.fillStyle = '#333';
68    xpowerReq.context.textBaseline = 'middle';
69    xpowerReq.context.fillText(s, 4, 5 + 9);
70  }
71}
72export function XpowerStructOnClick(clickRowType: string, sp: SpSystemTrace, entry?: XpowerStruct): Promise<unknown> {
73  return new Promise((resolve, reject) => {
74    if (clickRowType === TraceRow.ROW_TYPE_XPOWER_SYSTEM && (XpowerStruct.hoverXpowerStruct || entry)) {
75      XpowerStruct.selectXpowerStruct = entry || XpowerStruct.hoverXpowerStruct;
76      sp.traceSheetEL?.displayXpowerData(XpowerStruct.selectXpowerStruct!);
77      sp.timerShaftEL?.modifyFlagList(undefined);
78      reject(new Error());
79    } else {
80      resolve(null);
81    }
82  });
83}
84export class XpowerStruct extends BaseStruct {
85  static maxValue: number = 0;
86  static maxName: string = '';
87  static hoverXpowerStruct: XpowerStruct | undefined;
88  static selectXpowerStruct: XpowerStruct | undefined;
89  static index = 0;
90  filterId: number | undefined;
91  value: number | undefined;
92  startNS: number | undefined;
93  dur: number | undefined; //自补充,数据库没有返回
94  delta: number | undefined; //自补充,数据库没有返回
95
96  static draw(xpowerContext: CanvasRenderingContext2D, data: XpowerStruct, maxValue: number, minValue: number): void {
97    if (data.frame) {
98      let width = data.frame.width || 0;
99      xpowerContext.fillStyle = ColorUtils.colorForTid(XpowerStruct.index);
100      xpowerContext.strokeStyle = ColorUtils.colorForTid(XpowerStruct.index);
101      if ((data.value || 0) < 0) {
102        //数据为负数时显示不同颜色
103        xpowerContext.fillStyle = ColorUtils.colorForTid(XpowerStruct.index + 6);
104        xpowerContext.strokeStyle = ColorUtils.colorForTid(XpowerStruct.index + 6);
105      }
106      let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / maxValue);
107      if (drawHeight === 0) {
108        drawHeight = 1;
109      }
110      let minHeight: number = 0;
111      let maxHeight: number = 0;
112      let sumHeight: number = 0;
113      let cutHeight: number = 0;
114      if (minValue < 0) {
115        // 数据包含负数时
116        minHeight = Math.floor(((minValue || 0) * (data.frame.height || 0) * 1.0) / maxValue);
117        maxHeight = Math.floor(((maxValue || 0) * (data.frame.height || 0) * 1.0) / maxValue);
118        sumHeight = Math.abs(minHeight) + Math.abs(maxHeight);
119        let num = this.cal(Math.abs(minHeight), Math.abs(maxHeight));
120        drawHeight = Math.floor(drawHeight / num); //根据比例缩小绘制高度避免超出泳道
121
122        cutHeight = Math.abs(Math.floor(((minValue || 0) * (data.frame.height || 0) * 1.0) / maxValue) / num) + 1;
123        if (maxValue < 0) {
124          // 全部数据都是负数时
125          drawHeight = -drawHeight;
126          cutHeight = 30;
127        }
128      }
129      if (XpowerStruct.isHover(data)) {
130        xpowerContext.lineWidth = 1;
131        xpowerContext.globalAlpha = 0.6;
132        xpowerContext.fillRect(
133          data.frame.x,
134          data.frame.y + data.frame.height - drawHeight - cutHeight,
135          width,
136          drawHeight
137        );
138        xpowerContext.beginPath();
139        xpowerContext.arc(
140          data.frame.x,
141          data.frame.y + data.frame.height - drawHeight - cutHeight,
142          3,
143          0,
144          2 * Math.PI,
145          true
146        );
147        xpowerContext.fill();
148        xpowerContext.globalAlpha = 1.0;
149        xpowerContext.stroke();
150        xpowerContext.beginPath();
151        xpowerContext.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight - cutHeight);
152        xpowerContext.lineWidth = 3;
153        xpowerContext.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight - cutHeight);
154        xpowerContext.stroke();
155      } else {
156        xpowerContext.lineWidth = 1;
157        xpowerContext.globalAlpha = 1.0;
158        xpowerContext.strokeRect(
159          data.frame.x,
160          data.frame.y + data.frame.height - drawHeight - cutHeight,
161          width,
162          drawHeight
163        );
164        xpowerContext.globalAlpha = 0.6;
165        xpowerContext.fillRect(
166          data.frame.x,
167          data.frame.y + data.frame.height - drawHeight - cutHeight,
168          width,
169          drawHeight
170        );
171      }
172    }
173    xpowerContext.globalAlpha = 1.0;
174    xpowerContext.lineWidth = 1;
175  }
176
177  static cal(minHeight: number, maxHeight: number): number {
178    let multiplier = 1; // 初始倍数为1
179    let newSum: number;
180    do {
181      newSum = minHeight / multiplier + maxHeight / multiplier;
182      multiplier += 2; // 每次循环,倍数增加2
183    } while (newSum > 30 && multiplier <= (minHeight + maxHeight) * 2); // 确保不会除以0或过大数导致无限循环
184
185    // 检查是否找到了合适的倍数使得newSum <= 30
186    if (newSum <= 30) {
187      // 如果最后一次循环使multiplier超出了实际需要的值,需要调整回正确的倍数
188      multiplier -= 2;
189      while (minHeight / (multiplier + 2) + maxHeight / (multiplier + 2) > 30) {
190        multiplier += 2;
191      }
192      return multiplier;
193    } else {
194      // 如果没有找到合适的倍数,返回2
195      return 2;
196    }
197  }
198
199  static isHover(xpower: XpowerStruct): boolean {
200    return xpower === XpowerStruct.hoverXpowerStruct || xpower === XpowerStruct.selectXpowerStruct;
201  }
202}
203