• 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 { TraceRow } from '../../component/trace/base/TraceRow';
17import {
18  BaseStruct,
19  computeUnitWidth,
20  drawLoadingFrame,
21  isSurroundingPoint,
22  ns2x,
23  Rect,
24  Render,
25} from './ProcedureWorkerCommon';
26import { type AnimationRanges } from '../../bean/FrameComponentBean';
27import { ColorUtils } from '../../component/trace/base/ColorUtils';
28import {SpSystemTrace} from "../../component/SpSystemTrace";
29
30export class FrameSpacingRender extends Render {
31  renderMainThread(
32    req: {
33      useCache: boolean;
34      context: CanvasRenderingContext2D;
35      type: string;
36      frameRate: number;
37      animationRanges: AnimationRanges[];
38    },
39    row: TraceRow<FrameSpacingStruct>
40  ): void {
41    let frameSpacingList = row.dataList;
42    let frameSpacingFilter = row.dataListCache;
43    this.frameSpacing(
44      frameSpacingList,
45      frameSpacingFilter,
46      TraceRow.range!.startNS,
47      TraceRow.range!.endNS,
48      TraceRow.range!.totalNS,
49      row,
50      req.animationRanges,
51      req.useCache || !TraceRow.range!.refresh
52    );
53    drawLoadingFrame(req.context, row.dataListCache, row);
54    this.render(req, frameSpacingList, row);
55  }
56
57  private render(
58    req: {
59      useCache: boolean;
60      context: CanvasRenderingContext2D;
61      type: string;
62      frameRate: number;
63      animationRanges: AnimationRanges[];
64    },
65    frameSpacingFilter: Array<FrameSpacingStruct>,
66    row: TraceRow<FrameSpacingStruct>
67  ): void {
68    if (req.animationRanges.length > 0 && req.animationRanges[0] && frameSpacingFilter.length > 0) {
69      let minValue = 0;
70      let maxValue = 0;
71      let smallTickStandard = {
72        firstLine: 0,
73        secondLine: 0,
74        thirdLine: 0,
75      };
76      if (req.frameRate) {
77        // @ts-ignore
78        smallTickStandard = smallTick[req.frameRate];
79        [minValue, maxValue] = this.maxMinData(
80          smallTickStandard.firstLine,
81          smallTickStandard.thirdLine,
82          frameSpacingFilter
83        );
84      } else {
85        minValue = Math.min.apply(
86          Math,
87          frameSpacingFilter.map((filterData) => {
88            return filterData.frameSpacingResult!;
89          })
90        );
91        maxValue = Math.max.apply(
92          Math,
93          frameSpacingFilter.map((filterData) => {
94            return filterData.frameSpacingResult!;
95          })
96        );
97      }
98      let selectUnitWidth: number = 0;
99      this.drawTraceRow(frameSpacingFilter, selectUnitWidth, req, row, minValue, maxValue, smallTickStandard);
100      let findStructList = frameSpacingFilter.filter(
101        (filter) => row.isHover && isSurroundingPoint(row.hoverX, filter.frame!, selectUnitWidth / multiple)
102      );
103      this.setHoverStruct(findStructList, row);
104    }
105  }
106  private drawTraceRow(
107    frameSpacingFilter: Array<FrameSpacingStruct>,
108    selectUnitWidth: number,
109    req: any,
110    row: TraceRow<FrameSpacingStruct>,
111    minValue: number,
112    maxValue: number,
113    smallTickStandard: any
114  ) {
115    let preFrameSpacing: FrameSpacingStruct = frameSpacingFilter[0];
116    let isDraw = false;
117    for (let index: number = 0; index < frameSpacingFilter.length; index++) {
118      let currentStruct = frameSpacingFilter[index];
119      selectUnitWidth = computeUnitWidth(
120        preFrameSpacing.currentTs,
121        currentStruct.currentTs,
122        row.frame.width,
123        selectUnitWidth
124      );
125      FrameSpacingStruct.refreshHoverStruct(preFrameSpacing, currentStruct, row, minValue, maxValue);
126      if (currentStruct.groupId === 0) {
127        if (currentStruct.currentTs > TraceRow.range!.startNS && currentStruct.currentTs < TraceRow.range!.endNS) {
128          isDraw = true;
129          this.drawPoint(req.context, currentStruct, row, minValue, maxValue);
130        }
131      } else if (
132        currentStruct.groupId !== invalidGroupId &&
133        index > 0 &&
134        currentStruct.groupId === preFrameSpacing!.groupId
135      ) {
136        isDraw = true;
137        FrameSpacingStruct.draw(req.context, preFrameSpacing, currentStruct, row, minValue, maxValue);
138      }
139      FrameSpacingStruct.drawSelect(currentStruct, req.context, row);
140      preFrameSpacing = currentStruct;
141    }
142    if (req.frameRate) {
143      if (isDraw) {
144        this.drawDashedLines(Object.values(smallTickStandard), req, row, minValue, maxValue);
145      }
146    }
147  }
148  private setHoverStruct(findStructList: Array<FrameSpacingStruct>, row: TraceRow<FrameSpacingStruct>) {
149    let find = false;
150    if (findStructList.length > 0) {
151      find = true;
152      let hoverIndex: number = 0;
153      if (findStructList.length > unitIndex) {
154        hoverIndex = Math.ceil(findStructList.length / multiple);
155      }
156      FrameSpacingStruct.hoverFrameSpacingStruct = findStructList[hoverIndex];
157    }
158    if (!find && row.isHover) {
159      FrameSpacingStruct.hoverFrameSpacingStruct = undefined;
160    }
161  }
162
163  private drawPoint(
164    ctx: CanvasRenderingContext2D,
165    currentStruct: FrameSpacingStruct,
166    row: TraceRow<FrameSpacingStruct>,
167    minValue: number,
168    maxValue: number
169  ): void {
170    let currentPointY =
171      row.frame.height -
172      Math.floor(
173        ((currentStruct.frameSpacingResult! - minValue) * (row.frame.height - padding * multiple)) /
174          (maxValue - minValue)
175      ) -
176      padding;
177    ctx.beginPath();
178    ctx.lineWidth = 1;
179    ctx.globalAlpha = 1;
180    ctx.arc(currentStruct.frame!.x, currentPointY, multiple, 0, multiple * Math.PI);
181    ctx.strokeStyle = ColorUtils.ANIMATION_COLOR[2];
182    ctx.fillStyle = ColorUtils.ANIMATION_COLOR[2];
183    ctx.stroke();
184    ctx.fill();
185    ctx.closePath();
186  }
187
188  private drawDashedLines(
189    dashedLines: number[],
190    req: { useCache: boolean; context: CanvasRenderingContext2D; type: string; frameRate: number },
191    row: TraceRow<FrameSpacingStruct>,
192    minVale: number,
193    maxValue: number
194  ): void {
195    for (let i = 0; i < dashedLines.length; i++) {
196      FrameSpacingStruct.drawParallelLine(req.context, row.frame, dashedLines, i, minVale, maxValue);
197    }
198  }
199
200  private frameSpacing(
201    frameSpacingList: Array<FrameSpacingStruct>,
202    frameSpacingFilter: Array<FrameSpacingStruct>,
203    startNS: number,
204    endNS: number,
205    totalNS: number,
206    row: TraceRow<FrameSpacingStruct>,
207    animationRanges: AnimationRanges[],
208    use: boolean
209  ): void {
210    let frame: Rect = row.frame;
211    let modelName: string | undefined | null = row.getAttribute('model-name');
212    if ((use || !TraceRow.range!.refresh) && frameSpacingFilter.length > 0) {
213      frameSpacingList.length = 0;
214      let groupIdList: number[] = [];
215      for (let index = 0; index < frameSpacingFilter.length; index++) {
216        let item = frameSpacingFilter[index];
217        if (modelName === item.nameId) {
218          item.groupId = invalidGroupId;
219          for (let rangeIndex = 0; rangeIndex < animationRanges.length; rangeIndex++) {
220            let currentRange = animationRanges[rangeIndex];
221            if (item.currentTs >= currentRange.start && item.currentTs <= currentRange.end) {
222              item.groupId = currentRange.start;
223              break;
224            }
225          }
226          if (
227            item.currentTs < startNS &&
228            index + unitIndex < frameSpacingFilter.length &&
229            frameSpacingFilter[index + unitIndex].currentTs >= startNS &&
230            item.groupId !== invalidGroupId
231          ) {
232            this.refreshFrame(frameSpacingList, item, startNS, endNS, totalNS, frame, groupIdList);
233          }
234          if (item.currentTs >= startNS && item.currentTs <= endNS && item.groupId !== invalidGroupId) {
235            this.refreshFrame(frameSpacingList, item, startNS, endNS, totalNS, frame, groupIdList);
236          }
237          if (item.currentTs > endNS && item.groupId !== invalidGroupId) {
238            this.refreshFrame(frameSpacingList, item, startNS, endNS, totalNS, frame, groupIdList);
239            break;
240          }
241        }
242      }
243      this.grouping(groupIdList, frameSpacingList);
244      return;
245    }
246  }
247
248  private grouping(groupIdList: number[], frameSpacingFilter: Array<FrameSpacingStruct>): void {
249    let simpleGroup = groupIdList.filter((groupId) => {
250      return groupId !== invalidGroupId && groupIdList.indexOf(groupId) === groupIdList.lastIndexOf(groupId);
251    });
252    frameSpacingFilter.forEach((frameSpacing) => {
253      if (simpleGroup.indexOf(frameSpacing.groupId!) > invalidGroupId) {
254        frameSpacing.groupId = 0;
255        frameSpacing.frameSpacingResult = 0;
256        frameSpacing.preFrameWidth = 0;
257        frameSpacing.preFrameHeight = 0;
258        frameSpacing.preTs = 0;
259        frameSpacing.preX = 0;
260        frameSpacing.preY = 0;
261      }
262    });
263  }
264
265  private refreshFrame(
266    frameSpacingFilter: Array<FrameSpacingStruct>,
267    item: FrameSpacingStruct,
268    startNS: number,
269    endNS: number,
270    totalNS: number,
271    frame: Rect,
272    groupIdList: number[]
273  ): void {
274    frameSpacingFilter.push(item);
275    FrameSpacingStruct.setFrameSpacingFrame(item, startNS, endNS, totalNS, frame);
276    groupIdList.push(item.groupId!);
277  }
278
279  private maxMinData(tickStandardMin: number, tickStandardMax: number, filter: FrameSpacingStruct[]): [number, number] {
280    let min = Math.min.apply(
281      Math,
282      filter.map((filterData) => {
283        return filterData.frameSpacingResult!;
284      })
285    );
286    let max = Math.max.apply(
287      Math,
288      filter.map((filterData) => {
289        return filterData.frameSpacingResult!;
290      })
291    );
292    if (max < tickStandardMax) {
293      max = tickStandardMax + padding;
294    }
295    if (min > tickStandardMin) {
296      min = tickStandardMin;
297    }
298    return [min, max];
299  }
300}
301export function FrameSpacingStructOnClick(clickRowType: string, sp: SpSystemTrace) {
302  return new Promise((resolve,reject) => {
303    if (clickRowType === TraceRow.ROW_TYPE_FRAME_SPACING && FrameSpacingStruct.hoverFrameSpacingStruct) {
304      FrameSpacingStruct.selectFrameSpacingStruct = FrameSpacingStruct.hoverFrameSpacingStruct;
305      sp.traceSheetEL?.displayFrameSpacingData(FrameSpacingStruct.selectFrameSpacingStruct);
306      sp.timerShaftEL?.modifyFlagList(undefined);
307      reject();
308    }else{
309      resolve(null);
310    }
311  });
312}
313export class FrameSpacingStruct extends BaseStruct {
314  static hoverFrameSpacingStruct: FrameSpacingStruct | undefined;
315  static selectFrameSpacingStruct: FrameSpacingStruct | undefined;
316  physicalWidth: number | undefined;
317  physicalHeight: number | undefined;
318  preTs: number | undefined;
319  currentTs: number = 0;
320  frameSpacingResult: number | undefined;
321  id: number = 0;
322  groupId: number | undefined;
323  currentFrameWidth: number | undefined;
324  preFrameWidth: number | undefined;
325  currentFrameHeight: number | undefined;
326  preFrameHeight: number | undefined;
327  x: number | undefined;
328  y: number | undefined;
329  preX: number | undefined;
330  preY: number | undefined;
331  nameId: string | undefined;
332
333  static setFrameSpacingFrame(
334    frameSpacingNode: FrameSpacingStruct,
335    startNS: number,
336    endNS: number,
337    totalNS: number,
338    row: Rect
339  ): void {
340    let pointX = ns2x(frameSpacingNode.currentTs || 0, startNS, endNS, totalNS, row);
341    if (!frameSpacingNode.frame) {
342      frameSpacingNode.frame = new Rect(0, 0, 0, 0);
343    }
344    frameSpacingNode.frame.x = Math.floor(pointX);
345  }
346
347  static isSelect(currSpacingStruct: FrameSpacingStruct): boolean | 0 | undefined {
348    return (
349      TraceRow.rangeSelectObject &&
350      TraceRow.rangeSelectObject.startNS &&
351      TraceRow.rangeSelectObject.endNS &&
352      currSpacingStruct.currentTs >= TraceRow.rangeSelectObject.startNS &&
353      currSpacingStruct.currentTs <= TraceRow.rangeSelectObject.endNS
354    );
355  }
356
357  static refreshHoverStruct(
358    preFrameSpacing: FrameSpacingStruct,
359    frameSpacing: FrameSpacingStruct,
360    row: TraceRow<FrameSpacingStruct>,
361    minValue: number,
362    maxValue: number
363  ): void {
364    if (frameSpacing.frame) {
365      frameSpacing.frame.y =
366        row.frame.height -
367        Math.floor(
368          ((frameSpacing.frameSpacingResult! - minValue) * (row.frame.height - padding * multiple)) /
369            (maxValue - minValue)
370        ) -
371        padding;
372    }
373  }
374
375  static draw(
376    ctx: CanvasRenderingContext2D,
377    preFrameSpacing: FrameSpacingStruct,
378    currentStruct: FrameSpacingStruct,
379    rowFrame: TraceRow<FrameSpacingStruct>,
380    minValue: number,
381    maxValue: number
382  ): void {
383    if (currentStruct.frame && preFrameSpacing.frame) {
384      this.drawPolyline(ctx, preFrameSpacing, currentStruct, rowFrame, minValue, maxValue);
385    }
386  }
387
388  static drawSelect(
389    currentStruct: FrameSpacingStruct,
390    ctx: CanvasRenderingContext2D,
391    rowFrame: TraceRow<FrameSpacingStruct>
392  ): void {
393    if (
394      currentStruct.frame &&
395      currentStruct.currentTs > TraceRow.range!.startNS &&
396      currentStruct.currentTs < TraceRow.range!.endNS
397    ) {
398      if (
399        (currentStruct === FrameSpacingStruct.hoverFrameSpacingStruct && rowFrame.isHover) ||
400        currentStruct === FrameSpacingStruct.selectFrameSpacingStruct
401      ) {
402        ctx.lineWidth = 3;
403        ctx.beginPath();
404        ctx.arc(currentStruct.frame.x, currentStruct.frame.y, selectRadius, 0, multiple * Math.PI);
405        ctx.strokeStyle = ColorUtils.ANIMATION_COLOR[7];
406        ctx.lineWidth = 2;
407        ctx.globalAlpha = 1;
408        ctx.fillStyle = ColorUtils.ANIMATION_COLOR[9];
409        ctx.stroke();
410        ctx.fill();
411        ctx.closePath();
412      }
413    }
414    if (rowFrame.getAttribute('check-type') === '2' && FrameSpacingStruct.isSelect(currentStruct)) {
415      ctx.beginPath();
416      ctx.lineWidth = 3;
417      ctx.arc(currentStruct.frame!.x, currentStruct.frame!.y, selectRadius, 0, multiple * Math.PI);
418      ctx.strokeStyle = ColorUtils.ANIMATION_COLOR[7];
419      ctx.fillStyle = ColorUtils.ANIMATION_COLOR[9];
420      ctx.lineWidth = 2;
421      ctx.globalAlpha = 1;
422      ctx.stroke();
423      ctx.fill();
424      ctx.closePath();
425    }
426  }
427
428  static drawParallelLine(
429    ctx: CanvasRenderingContext2D,
430    rowFrame: Rect,
431    dashedLines: number[],
432    index: number,
433    minValue: number,
434    maxValue: number
435  ): void {
436    let pointY =
437      rowFrame.height -
438      Math.floor(((dashedLines[index] - minValue) * (rowFrame.height - padding * multiple)) / (maxValue - minValue)) -
439      padding;
440    let lineDash = 10;
441    let textPadding = 4;
442    ctx.beginPath();
443    ctx.lineWidth = 2;
444    ctx.setLineDash([lineDash]);
445    ctx.strokeStyle = ColorUtils.ANIMATION_COLOR[6];
446    ctx.fillStyle = ColorUtils.ANIMATION_COLOR[6];
447    ctx.moveTo(0, pointY);
448    ctx.lineTo(rowFrame.width, pointY);
449    ctx.stroke();
450    ctx.strokeStyle = ColorUtils.ANIMATION_COLOR[3];
451    ctx.fillStyle = ColorUtils.ANIMATION_COLOR[3];
452    if (index === 0) {
453      ctx.fillText(dashedLines[index].toString(), 0, pointY + multiple * textPadding);
454    } else if (index === unitIndex) {
455      ctx.fillText(dashedLines[index].toString(), 0, pointY + textPadding);
456    } else {
457      ctx.fillText(dashedLines[index].toString(), 0, pointY - textPadding);
458    }
459    ctx.closePath();
460  }
461
462  static drawPolyline(
463    ctx: CanvasRenderingContext2D,
464    preFrameSpacing: FrameSpacingStruct,
465    currentStruct: FrameSpacingStruct,
466    rowFrame: TraceRow<FrameSpacingStruct>,
467    minValue: number,
468    maxValue: number
469  ): void {
470    ctx.beginPath();
471    let prePointY =
472      rowFrame.frame.height -
473      Math.floor(
474        ((preFrameSpacing.frameSpacingResult! - minValue) * (rowFrame.frame.height - padding * multiple)) /
475          (maxValue - minValue)
476      ) -
477      padding;
478    let currentPointY =
479      rowFrame.frame.height -
480      Math.floor(
481        ((currentStruct.frameSpacingResult! - minValue) * (rowFrame.frame.height - padding * multiple)) /
482          (maxValue - minValue)
483      ) -
484      padding;
485    if (preFrameSpacing.frame && currentStruct.frame) {
486      ctx.strokeStyle = ColorUtils.ANIMATION_COLOR[2];
487      ctx.fillStyle = ColorUtils.ANIMATION_COLOR[2];
488      ctx.lineWidth = 2;
489      ctx.setLineDash([0]);
490      ctx.moveTo(preFrameSpacing.frame.x, prePointY);
491      ctx.lineTo(currentStruct.frame.x, currentPointY);
492      ctx.stroke();
493      ctx.closePath();
494      FrameSpacingStruct.drawSelect(preFrameSpacing, ctx, rowFrame);
495    }
496  }
497}
498
499const padding = 3;
500const invalidGroupId: number = -1;
501const multiple: number = 2;
502const unitIndex: number = 1;
503const selectRadius: number = 3;
504
505const smallTick = {
506  60: {
507    firstLine: 11.4,
508    secondLine: 13,
509    thirdLine: 14.6,
510  },
511  90: {
512    firstLine: 13.7,
513    secondLine: 19.4,
514    thirdLine: 25,
515  },
516  120: {
517    firstLine: 13.7,
518    secondLine: 19.4,
519    thirdLine: 25,
520  },
521};
522