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 {CpuStruct, WakeupBean} from "./ProcedureWorkerCPU.js"; 17 18export abstract class Render { 19 abstract render(req: RequestMessage, list: Array<any>, filter: Array<any>): void; 20} 21 22export abstract class PerfRender { 23 abstract render(req: RequestMessage, list: Array<any>, filter: Array<any>, dataList2: Array<any>): void; 24} 25 26export class RequestMessage { 27 type: string | undefined | null 28 lazyRefresh: boolean | undefined; 29 intervalPerf: any; 30 canvas: any; 31 context: any; 32 params: any; 33 online: any; 34 buf: any; 35 isRangeSelect: any; 36 isHover: any; 37 xs: any; 38 frame: any; 39 flagMoveInfo: any; 40 flagSelectedInfo: any; 41 hoverX: any; 42 hoverY: any; 43 startNS: any; 44 endNS: any; 45 totalNS: any; 46 slicesTime: { startTime: number | null, endTime: number | null, color: string | null } | undefined; 47 range: any; 48 scale: any; 49 chartColor:any; 50 canvasWidth: any; 51 canvasHeight: any; 52 useCache: any; 53 lineColor: any; 54 wakeupBean: WakeupBean | undefined | null; 55 id: any; 56 postMessage: { (message: any, targetOrigin: string, transfer?: Transferable[]): void; (message: any, options?: WindowPostMessageOptions): void } | undefined; 57} 58 59export function ns2s(ns: number): string { 60 let second1 = 1_000_000_000; // 1 second 61 let millisecond1 = 1_000_000; // 1 millisecond 62 let microsecond1 = 1_000; // 1 microsecond 63 let nanosecond1 = 1000.0; 64 let res; 65 if (ns >= second1) { 66 res = (ns / 1000 / 1000 / 1000).toFixed(1) + " s"; 67 } else if (ns >= millisecond1) { 68 res = (ns / 1000 / 1000).toFixed(1) + " ms"; 69 } else if (ns >= microsecond1) { 70 res = (ns / 1000).toFixed(1) + " μs"; 71 } else if (ns > 0) { 72 res = ns.toFixed(1) + " ns"; 73 } else { 74 res = ns.toFixed(1) + " s"; 75 } 76 return res; 77} 78 79export function ns2x(ns: number, startNS: number, endNS: number, duration: number, rect: any) { 80 // @ts-ignore 81 if (endNS == 0) { 82 endNS = duration; 83 } 84 let xSize: number = (ns - startNS) * rect.width / (endNS - startNS); 85 if (xSize < 0) { 86 xSize = 0; 87 } else if (xSize > rect.width) { 88 xSize = rect.width; 89 } 90 return xSize; 91} 92 93export class Rect { 94 x: number = 0 95 y: number = 0 96 width: number = 0 97 height: number = 0 98 99 constructor(x: number, y: number, width: number, height: number) { 100 this.x = x; 101 this.y = y; 102 this.width = width; 103 this.height = height; 104 } 105 106 static contains(rect: Rect, x: number, y: number): boolean { 107 return rect.x <= x && x <= rect.x + rect.width && rect.y <= y && y <= rect.y + rect.height; 108 } 109 110 static containsWithPadding(rect: Rect, x: number, y: number, paddingLeftRight: number, paddingTopBottom: number): boolean { 111 return rect.x + paddingLeftRight <= x 112 && x <= rect.x + rect.width - paddingLeftRight 113 && rect.y + paddingTopBottom <= y 114 && y <= rect.y + rect.height - paddingTopBottom; 115 } 116 117 static containsWithMargin(rect: Rect, x: number, y: number, t: number, r: number, b: number, l: number): boolean { 118 return rect.x - l <= x 119 && x <= rect.x + rect.width + r 120 && rect.y - t <= y 121 && y <= rect.y + rect.height + b; 122 } 123 124 static intersect(r1: Rect, rect: Rect): boolean { 125 let maxX = r1.x + r1.width >= rect.x + rect.width ? r1.x + r1.width : rect.x + rect.width; 126 let maxY = r1.y + r1.height >= rect.y + rect.height ? r1.y + r1.height : rect.y + rect.height; 127 let minX = r1.x <= rect.x ? r1.x : rect.x; 128 let minY = r1.y <= rect.y ? r1.y : rect.y; 129 if (maxX - minX <= rect.width + r1.width && maxY - minY <= r1.height + rect.height) { 130 return true; 131 } else { 132 return false; 133 } 134 } 135 136 contains(x: number, y: number): boolean { 137 return this.x <= x && x <= this.x + this.width && this.y <= y && y <= this.y + this.height; 138 } 139 140 containsWithPadding(x: number, y: number, paddingLeftRight: number, paddingTopBottom: number): boolean { 141 return this.x + paddingLeftRight <= x 142 && x <= this.x + this.width - paddingLeftRight 143 && this.y + paddingTopBottom <= y 144 && y <= this.y + this.height - paddingTopBottom; 145 } 146 147 containsWithMargin(x: number, y: number, t: number, r: number, b: number, l: number): boolean { 148 return this.x - l <= x 149 && x <= this.x + this.width + r 150 && this.y - t <= y 151 && y <= this.y + this.height + b; 152 } 153 154 /** 155 * 判断是否相交 156 * @param rect 157 */ 158 intersect(rect: Rect): boolean { 159 let maxX = this.x + this.width >= rect.x + rect.width ? this.x + this.width : rect.x + rect.width; 160 let maxY = this.y + this.height >= rect.y + rect.height ? this.y + this.height : rect.y + rect.height; 161 let minX = this.x <= rect.x ? this.x : rect.x; 162 let minY = this.y <= rect.y ? this.y : rect.y; 163 if (maxX - minX <= rect.width + this.width && maxY - minY <= this.height + rect.height) { 164 return true; 165 } else { 166 return false; 167 } 168 } 169} 170 171export class Point { 172 x: number = 0 173 y: number = 0 174 175 constructor(x: number, y: number) { 176 this.x = x; 177 this.y = y; 178 } 179} 180 181export class BaseStruct { 182 frame: Rect | undefined 183 isHover: boolean = false; 184} 185 186export function drawLines(ctx: CanvasRenderingContext2D, xs: Array<any>, height: number, lineColor: string) { 187 if (ctx) { 188 ctx.lineWidth = 1; 189 ctx.strokeStyle = lineColor || "#dadada"; 190 xs?.forEach(it => { 191 ctx.moveTo(Math.floor(it), 0) 192 ctx.lineTo(Math.floor(it), height) 193 }) 194 ctx.stroke(); 195 } 196} 197 198export function drawFlagLine(ctx: any, hoverFlag: any, selectFlag: any, startNS: number, endNS: number, totalNS: number, frame: any, slicesTime: { startTime: number | null, endTime: number | null, color: string | null } | undefined) { 199 if (ctx) { 200 if (hoverFlag) { 201 ctx.beginPath(); 202 ctx.lineWidth = 2; 203 ctx.strokeStyle = hoverFlag?.color || "#dadada"; 204 ctx.moveTo(Math.floor(hoverFlag.x), 0) 205 ctx.lineTo(Math.floor(hoverFlag.x), frame.height) 206 ctx.stroke(); 207 ctx.closePath(); 208 } 209 if (selectFlag) { 210 ctx.beginPath(); 211 ctx.lineWidth = 2; 212 ctx.strokeStyle = selectFlag?.color || "#dadada"; 213 selectFlag.x = ns2x(selectFlag.time, startNS, endNS, totalNS, frame); 214 ctx.moveTo(Math.floor(selectFlag.x), 0) 215 ctx.lineTo(Math.floor(selectFlag.x), frame.height) 216 ctx.stroke(); 217 ctx.closePath(); 218 } 219 if (slicesTime && slicesTime.startTime && slicesTime.endTime) { 220 ctx.beginPath(); 221 ctx.lineWidth = 1; 222 ctx.strokeStyle = slicesTime.color || "#dadada"; 223 let x1 = ns2x(slicesTime.startTime, startNS, endNS, totalNS, frame); 224 let x2 = ns2x(slicesTime.endTime, startNS, endNS, totalNS, frame); 225 ctx.moveTo(Math.floor(x1), 0) 226 ctx.lineTo(Math.floor(x1), frame.height) 227 ctx.moveTo(Math.floor(x2), 0) 228 ctx.lineTo(Math.floor(x2), frame.height) 229 ctx.stroke(); 230 ctx.closePath(); 231 } 232 } 233} 234 235export function drawSelection(context: any, params: any) { 236 if (params.isRangeSelect && params.rangeSelectObject) { 237 params.rangeSelectObject!.startX = Math.floor(ns2x(params.rangeSelectObject!.startNS!, params.startNS, params.endNS, params.totalNS, params.frame)); 238 params.rangeSelectObject!.endX = Math.floor(ns2x(params.rangeSelectObject!.endNS!, params.startNS, params.endNS, params.totalNS, params.frame)); 239 if (context) { 240 context.globalAlpha = 0.5 241 context.fillStyle = "#666666" 242 context.fillRect(params.rangeSelectObject!.startX!, params.frame.y, params.rangeSelectObject!.endX! - params.rangeSelectObject!.startX!, params.frame.height) 243 context.globalAlpha = 1 244 } 245 } 246} 247 248export function drawWakeUp(context: CanvasRenderingContext2D | any, wake: WakeupBean | undefined | null, startNS: number, endNS: number, totalNS: number, frame: Rect, selectCpuStruct: CpuStruct | undefined = undefined, currentCpu: number | undefined = undefined) { 249 if (wake) { 250 let x1 = Math.floor(ns2x((wake.wakeupTime || 0), startNS, endNS, totalNS, frame)); 251 context.beginPath(); 252 context.lineWidth = 2; 253 context.fillStyle = "#000000"; 254 if (x1 > 0 && x1 < frame.x + frame.width) { 255 context.moveTo(x1, frame.y); 256 context.lineTo(x1, frame.y + frame.height); 257 if (currentCpu == wake.cpu) { 258 let centerY = Math.floor(frame.y + frame.height / 2); 259 context.moveTo(x1, centerY - 6); 260 context.lineTo(x1 + 4, centerY); 261 context.lineTo(x1, centerY + 6); 262 context.lineTo(x1 - 4, centerY); 263 context.lineTo(x1, centerY - 6); 264 context.fill(); 265 } 266 } 267 if (selectCpuStruct) { 268 let x2 = Math.floor(ns2x((selectCpuStruct.startTime || 0), startNS, endNS, totalNS, frame)); 269 let y = frame.y + frame.height - 10; 270 context.moveTo(x1, y); 271 context.lineTo(x2, y); 272 273 let s = ns2s((selectCpuStruct.startTime || 0) - (wake.wakeupTime || 0)); 274 let distance = x2 - x1; 275 if (distance > 12) { 276 context.moveTo(x1, y); 277 context.lineTo(x1 + 6, y - 3); 278 context.moveTo(x1, y); 279 context.lineTo(x1 + 6, y + 3); 280 context.moveTo(x2, y); 281 context.lineTo(x2 - 6, y - 3); 282 context.moveTo(x2, y); 283 context.lineTo(x2 - 6, y + 3); 284 let measure = context.measureText(s); 285 let tHeight = measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent 286 let xStart = x1 + Math.floor(distance / 2 - measure.width / 2); 287 if (distance > measure.width + 4) { 288 context.fillStyle = "#ffffff" 289 context.fillRect(xStart - 2, y - 4 - tHeight, measure.width + 4, tHeight + 4); 290 context.font = "10px solid"; 291 context.fillStyle = "#000000"; 292 context.textBaseline = "bottom"; 293 context.fillText(s, xStart, y - 2); 294 } 295 296 } 297 } 298 context.strokeStyle = "#000000"; 299 context.stroke(); 300 context.closePath(); 301 } 302} 303 304export function drawLoading(ctx: CanvasRenderingContext2D, startNS: number, endNS: number, totalNS: number, frame: any, left: number, right: number) { 305} 306