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 { ColorUtils } from '../../component/trace/base/ColorUtils'; 17import { TraceRow } from '../../component/trace/base/TraceRow'; 18import { BaseStruct, isFrameContainPoint, ns2x, Render, RequestMessage, drawString } from './ProcedureWorkerCommon'; 19import {SpSystemTrace} from "../../component/SpSystemTrace"; 20 21export class SoRender extends Render { 22 renderMainThread( 23 req: { 24 useCache: boolean; 25 context: CanvasRenderingContext2D; 26 type: string; 27 }, 28 row: TraceRow<SoStruct> 29 ): void { 30 let soList = row.dataList; 31 let soFilter = row.dataListCache; 32 soDataFilter( 33 soList, 34 soFilter, 35 TraceRow.range!.startNS, 36 TraceRow.range!.endNS, 37 TraceRow.range!.totalNS, 38 row.frame, 39 req.useCache || !TraceRow.range!.refresh 40 ); 41 req.context.beginPath(); 42 let soFind = false; 43 for (let so of soFilter) { 44 SoStruct.draw(req.context, so); 45 if (row.isHover) { 46 if (so.dur === 0 || so.dur === null || so.dur === undefined) { 47 if ( 48 so.frame && 49 row.hoverX >= so.frame.x - 5 && 50 row.hoverX <= so.frame.x + 5 && 51 row.hoverY >= so.frame.y && 52 row.hoverY <= so.frame.y + so.frame.height 53 ) { 54 SoStruct.hoverSoStruct = so; 55 soFind = true; 56 } 57 } else { 58 if (so.frame && isFrameContainPoint(so.frame, row.hoverX, row.hoverY)) { 59 SoStruct.hoverSoStruct = so; 60 soFind = true; 61 } 62 } 63 } 64 } 65 if (!soFind && row.isHover) SoStruct.hoverSoStruct = undefined; 66 req.context.closePath(); 67 } 68 69 render(req: RequestMessage, list: Array<any>, filter: Array<any>): void {} 70} 71 72export function soDataFilter( 73 soList: Array<SoStruct>, 74 soFilter: Array<SoStruct>, 75 startNS: number, 76 endNS: number, 77 totalNS: number, 78 frame: any, 79 use: boolean 80): void { 81 if (use && soFilter.length > 0) { 82 for (let i = 0, len = soFilter.length; i < len; i++) { 83 if ((soFilter[i].startTs || 0) + (soFilter[i].dur || 0) >= startNS && (soFilter[i].startTs || 0) <= endNS) { 84 SoStruct.setSoFrame(soFilter[i], 0, startNS, endNS, totalNS, frame); 85 } else { 86 soFilter[i].frame = undefined; 87 } 88 } 89 return; 90 } 91 soFilter.length = 0; 92 if (soList) { 93 let groups = soList 94 .filter((it) => (it.startTs ?? 0) + (it.dur ?? 0) >= startNS && (it.startTs ?? 0) <= endNS) 95 .map((it) => { 96 SoStruct.setSoFrame(it, 0, startNS, endNS, totalNS, frame); 97 return it; 98 }) 99 .reduce((pre: any, current, index, arr) => { 100 if (current.frame) { 101 (pre[`${current.frame.x}-${current.depth}`] = pre[`${current.frame.x}-${current.depth}`] || []).push(current); 102 } 103 return pre; 104 }, {}); 105 Reflect.ownKeys(groups).map((kv) => { 106 let arr = groups[kv].sort((a: any, b: any) => b.dur - a.dur); 107 soFilter.push(arr[0]); 108 }); 109 } 110} 111export function SoStructOnClick(clickRowType: string, sp: SpSystemTrace, scrollToFuncHandler: any) { 112 return new Promise((resolve, reject)=>{ 113 if (clickRowType === TraceRow.ROW_TYPE_STATIC_INIT && SoStruct.hoverSoStruct) { 114 SoStruct.selectSoStruct = SoStruct.hoverSoStruct; 115 sp.traceSheetEL?.displayStaticInitData(SoStruct.selectSoStruct, scrollToFuncHandler); 116 sp.timerShaftEL?.modifyFlagList(undefined); 117 reject(); 118 }else{ 119 resolve(null); 120 } 121 }) 122} 123export class SoStruct extends BaseStruct { 124 static hoverSoStruct: SoStruct | undefined; 125 static selectSoStruct: SoStruct | undefined; 126 textMetricsWidth: number | undefined; 127 depth: number | undefined; 128 dur: number | undefined; 129 soName: string | undefined; 130 process: string | undefined; 131 startTs: number | undefined; 132 tid: number | undefined; 133 pid: number | undefined; 134 itid: number | undefined; 135 id: number | undefined; 136 137 static setSoFrame(soNode: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any): void { 138 let x1: number; 139 let x2: number; 140 if ((soNode.startTs || 0) > startNS && (soNode.startTs || 0) < endNS) { 141 x1 = ns2x(soNode.startTs || 0, startNS, endNS, totalNS, frame); 142 } else { 143 x1 = 0; 144 } 145 if ((soNode.startTs || 0) + (soNode.dur || 0) > startNS && (soNode.startTs || 0) + (soNode.dur || 0) < endNS) { 146 x2 = ns2x((soNode.startTs || 0) + (soNode.dur || 0), startNS, endNS, totalNS, frame); 147 } else { 148 x2 = frame.width; 149 } 150 if (!soNode.frame) { 151 soNode.frame = {}; 152 } 153 let getV: number = x2 - x1 < 1 ? 1 : x2 - x1; 154 soNode.frame.x = Math.floor(x1); 155 soNode.frame.y = soNode.depth * 20; 156 soNode.frame.width = Math.ceil(getV); 157 soNode.frame.height = 20; 158 } 159 160 static draw(ctx: CanvasRenderingContext2D, data: SoStruct): void { 161 if (data.frame) { 162 if (data.dur === undefined || data.dur === null) { 163 } else { 164 ctx.globalAlpha = 1; 165 ctx.fillStyle = ColorUtils.FUNC_COLOR[ColorUtils.hashFunc(data.soName || '', 0, ColorUtils.FUNC_COLOR.length)]; 166 let textColor = ColorUtils.FUNC_COLOR[ColorUtils.hashFunc(data.soName || '', 0, ColorUtils.FUNC_COLOR.length)]; 167 let miniHeight = 20; 168 if (SoStruct.hoverSoStruct && data.soName === SoStruct.hoverSoStruct.soName) { 169 ctx.globalAlpha = 0.7; 170 } 171 ctx.fillRect(data.frame.x, data.frame.y, data.frame.width, miniHeight - padding * 2); 172 if (data.frame.width > 10) { 173 ctx.strokeStyle = '#fff'; 174 ctx.lineWidth = 1; 175 ctx.strokeRect(data.frame.x, data.frame.y, data.frame.width, miniHeight - padding * 2); 176 ctx.fillStyle = ColorUtils.funcTextColor(textColor); 177 drawString(ctx, `${data.soName || ''}`, 5, data.frame, data); 178 } 179 if (data === SoStruct.selectSoStruct) { 180 ctx.strokeStyle = '#000'; 181 ctx.lineWidth = 2; 182 ctx.strokeRect(data.frame.x, data.frame.y + 1, data.frame.width, miniHeight - padding * 2 - 2); 183 } 184 } 185 } 186 } 187} 188 189const padding = 1; 190