• 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 { SpApplication } from "../SpApplication.js";
17import { BaseStruct } from "./BaseStruct.js";
18import { Rect } from "../component/trace/timer-shaft/Rect.js";
19import { info } from "../../log/Log.js";
20
21const padding: number = 1;
22
23export class ChartStruct extends BaseStruct {
24    static hoverFuncStruct: ChartStruct | undefined;
25    static selectFuncStruct: ChartStruct | undefined;
26    static lastSelectFuncStruct: ChartStruct | undefined;
27    needShow = false;
28    depth: number = 0;
29    symbol: string = '';
30    size: number = 0;
31    count: number = 0;
32    dur: number = 0;
33    type: ChartMode = ChartMode.Call;
34    parent: ChartStruct | undefined;
35    children: Array<ChartStruct> = [];
36}
37
38export enum ChartMode {
39    Call,
40    Byte,
41    Count,
42    Duration,
43}
44
45export function setFuncFrame(node: ChartStruct, canvas_frame: Rect, total: number, mode: ChartMode) {
46    if (!node.frame) {
47        node.frame = new Rect(0, 0, 0, 0);
48    }
49    // filter depth is 0
50    if (node.parent) {
51        let idx = node.parent.children.indexOf(node);
52        if (idx == 0) {
53            node.frame!.x = node.parent.frame!.x;
54        } else {
55            // set x by left frame. left frame is parent.children[idx - 1]
56            node.frame.x = node.parent.children[idx - 1].frame!.x + node.parent.children[idx - 1].frame!.width
57        }
58        switch (mode) {
59            case ChartMode.Byte:
60                node.frame!.width = Math.floor(node.size / total * canvas_frame.width);
61                break;
62            case ChartMode.Count:
63                node.frame!.width = Math.floor(node.count / total * canvas_frame.width);
64                break;
65            case ChartMode.Duration:
66                node.frame!.width = Math.floor(node.dur / total * canvas_frame.width);
67                break;
68            default:
69                info('not match ChartMode');
70        }
71        node.frame!.y = node.parent.frame!.y + 20;
72        node.frame!.height = 20;
73    }
74}
75
76
77/**
78 * draw rect
79 * @param ctx CanvasRenderingContext2D
80 * @param data rect which is need draw
81 * @param percent function size or count / total size or count
82 */
83export function draw(ctx: CanvasRenderingContext2D, data: ChartStruct, percent: number) {
84    let spApplication = <SpApplication>document.getElementsByTagName("sp-application")[0]
85    if (data.frame) {
86        // draw rect
87        let miniHeight = 20;
88        if (isSelected(data)) {
89            ctx.fillStyle = `rgba(${82}, ${145}, ${255}, 0.9)`;
90        } else {
91            let color = getHeatColor(percent);
92            ctx.fillStyle = `rgba(${color.r}, ${color.g}, ${color.b}, 0.9)`;
93        }
94        ctx.fillRect(data.frame.x, data.frame.y, data.frame.width, miniHeight - padding * 2);
95        //draw border
96        if (isHover(data)) {
97            if (spApplication.dark) {
98                ctx.strokeStyle = "#fff";
99            } else {
100                ctx.strokeStyle = "#000";
101            }
102        } else {
103            if (spApplication.dark) {
104                ctx.strokeStyle = "#000";
105            } else {
106                ctx.strokeStyle = "#fff";
107            }
108        }
109        ctx.lineWidth = 0.4;
110        ctx.strokeRect(data.frame.x, data.frame.y, data.frame.width, miniHeight - padding * 2);
111
112        //draw symbol name
113        if (data.frame.width > 10) {
114            if (percent > 0.6 || isSelected(data)) {
115                ctx.fillStyle = "#fff";
116            } else {
117                ctx.fillStyle = "#000";
118            }
119            drawString(ctx, data.symbol || '', 5, data.frame);
120        }
121    }
122}
123
124/**
125 * get framechart color by percent
126 * @param widthPercentage proportion of function
127 * @returns rbg
128 */
129function getHeatColor(widthPercentage: number) {
130    return {
131        r: Math.floor(245 + 10 * (1 - widthPercentage)),
132        g: Math.floor(110 + 105 * (1 - widthPercentage)),
133        b: 100,
134    };
135}
136
137/**
138 * draw function string in rect
139 * @param ctx CanvasRenderingContext2D
140 * @param str function Name
141 * @param textPadding textPadding
142 * @param frame canvas area
143 * @returns is draw
144 */
145function drawString(ctx: CanvasRenderingContext2D, str: string, textPadding: number, frame: Rect): boolean {
146    let textMetrics = ctx.measureText(str);
147    let charWidth = Math.round(textMetrics.width / str.length)
148    if (textMetrics.width < frame.width - textPadding * 2) {
149        let x2 = Math.floor(frame.width / 2 - textMetrics.width / 2 + frame.x + textPadding)
150        ctx.fillText(str, x2, Math.floor(frame.y + frame.height / 2 + 2), frame.width - textPadding * 2)
151        return true;
152    }
153    if (frame.width - textPadding * 2 > charWidth * 4) {
154        let chatNum = (frame.width - textPadding * 2) / charWidth;
155        let x1 = frame.x + textPadding
156        ctx.fillText(str.substring(0, chatNum - 4) + '...', x1, Math.floor(frame.y + frame.height / 2 + 2), frame.width - textPadding * 2)
157        return true;
158    }
159    return false;
160}
161
162function isHover(data: ChartStruct): boolean {
163    return ChartStruct.hoverFuncStruct == data;
164}
165
166function isSelected(data: ChartStruct): boolean {
167    return ChartStruct.lastSelectFuncStruct == data;
168}
169