1/* 2 * Copyright (C) 2024 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, drawString, Rect } from './ProcedureWorkerCommon'; 17import { TraceRow } from '../../component/trace/base/TraceRow'; 18import { SpSystemTrace } from '../../component/SpSystemTrace'; 19import { SpApplication } from '../../SpApplication'; 20 21export class SnapShotRender { 22 renderMainThread( 23 req: { 24 snapShotContext: CanvasRenderingContext2D; 25 useCache: boolean; 26 type: string; 27 translateY: number; 28 }, 29 snapShotRow: TraceRow<SnapShotStruct>, 30 trace: SpSystemTrace 31 ): void { 32 let list = snapShotRow.dataList; 33 let filter = snapShotRow.dataListCache; 34 dataFilterHandler(list, filter, { 35 startKey: 'startTime', 36 durKey: 'dur', 37 startNS: TraceRow.range?.startNS ?? 0, 38 endNS: TraceRow.range?.endNS ?? 0, 39 totalNS: TraceRow.range?.totalNS ?? 0, 40 frame: snapShotRow.frame, 41 paddingTop: 5, 42 useCache: req.useCache || !(TraceRow.range?.refresh ?? false), 43 }); 44 req.snapShotContext.globalAlpha = 0.6; 45 let find = false; 46 let offset = 3; 47 for (let re of filter) { 48 snapShotRow.isHover = SnapShotStruct.isClear && SnapShotStruct.hoverSnapShotStruct === undefined ? false : snapShotRow.isHover; 49 SnapShotStruct.draw(req.snapShotContext, re, snapShotRow.translateY, snapShotRow.isHover); 50 if (snapShotRow.isHover) { 51 if ( 52 re.frame && 53 snapShotRow.hoverX >= re.frame.x - offset && 54 snapShotRow.hoverX <= re.frame.x + re.frame.width + offset 55 ) { 56 SnapShotStruct.hoverSnapShotStruct = re; 57 find = true; 58 } 59 } 60 } 61 if (!find && snapShotRow.isHover) { 62 SnapShotStruct.hoverSnapShotStruct = undefined; 63 } 64 } 65} 66 67export function SnapShotOnClick( 68 rowType: string, 69 sp: SpSystemTrace, 70 entry?: SnapShotStruct, 71): Promise<unknown> { 72 return new Promise((resolve, reject) => { 73 if (rowType === TraceRow.ROW_TYPE_SNAPSHOT && (SnapShotStruct.hoverSnapShotStruct || entry)) { 74 SnapShotStruct.selectSnapShotStruct = entry || SnapShotStruct.hoverSnapShotStruct; 75 SpApplication.displaySnapShot(SnapShotStruct.selectSnapShotStruct); 76 reject(new Error()); 77 } else { 78 resolve(null); 79 } 80 }); 81} 82 83export class SnapShotStruct extends BaseStruct { 84 static hoverSnapShotStruct: SnapShotStruct | undefined; 85 static selectSnapShotStruct: SnapShotStruct | undefined; 86 static maxVal: number | undefined = 0; 87 static index = 0; 88 static maxDepth: number = 0; 89 static imageCache: { [img: string]: Promise<HTMLImageElement> } = {}; 90 static isClear: boolean; 91 92 value: number | undefined = 20; 93 startTime: number | undefined; 94 dur: number | undefined; 95 img: string = ''; 96 97 static async draw( 98 ctx: CanvasRenderingContext2D, 99 data: SnapShotStruct, 100 translateY: number, 101 isHover: boolean 102 ): Promise<void> { 103 if (data.frame && data.img) { 104 const imagePromise = SnapShotStruct.getImageFromCache(data.img); 105 try { 106 const image = await imagePromise; 107 ctx.drawImage( 108 image, 109 data.frame.x, 110 data.frame.y + translateY, 111 data.frame.width, 112 data.frame.height 113 ); 114 if (data.startTime === SnapShotStruct.selectSnapShotStruct?.startTime) { 115 ctx.strokeStyle = 'red'; 116 ctx.lineWidth = 1; 117 ctx.strokeRect(data.frame.x, data.frame.y + translateY + 1, data.frame.width - 2, data.frame.height - 2); 118 } 119 if (isHover && SnapShotStruct.hoverSnapShotStruct && data.startTime === SnapShotStruct.hoverSnapShotStruct?.startTime) { 120 ctx.strokeStyle = '#000'; 121 ctx.lineWidth = 1; 122 ctx.strokeRect(data.frame.x, data.frame.y + translateY + 1, data.frame.width - 2, data.frame.height - 2); 123 } 124 } catch (error) { 125 console.error('Error loading image:', error); 126 } 127 } 128 } 129 private static async getImageFromCache(img: string): Promise<HTMLImageElement> { 130 if (!SnapShotStruct.imageCache[img]) { 131 SnapShotStruct.imageCache[img] = new Promise((resolve, reject) => { 132 const image = new Image(); 133 image.onload = (): void => resolve(image); 134 image.onerror = (error): void => reject(new Error(`Failed to load image: ${img},${error}`)); 135 image.src = img; 136 }); 137 } 138 return SnapShotStruct.imageCache[img]; 139 } 140}