sampleTickRenderer.tsx 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. import {mat3} from 'gl-matrix';
  2. import {Flamegraph} from '../flamegraph';
  3. import {FlamegraphTheme} from '../flamegraph/flamegraphTheme';
  4. import {getContext, Rect} from '../gl/utils';
  5. function computeAbsoluteSampleTimestamps(startedAt: number, weights: readonly number[]) {
  6. const timeline = [startedAt + weights[0]];
  7. for (let i = 1; i < weights.length; i++) {
  8. timeline.push(timeline[i - 1] + weights[i]);
  9. }
  10. return timeline;
  11. }
  12. class SampleTickRenderer {
  13. canvas: HTMLCanvasElement;
  14. context: CanvasRenderingContext2D;
  15. theme: FlamegraphTheme;
  16. flamegraph: Flamegraph;
  17. intervals: number[];
  18. constructor(
  19. canvas: HTMLCanvasElement,
  20. flamegraph: Flamegraph,
  21. configSpace: Rect,
  22. theme: FlamegraphTheme
  23. ) {
  24. this.canvas = canvas;
  25. this.flamegraph = flamegraph;
  26. this.theme = theme;
  27. this.intervals = computeAbsoluteSampleTimestamps(
  28. configSpace.x,
  29. this.flamegraph.profile.weights
  30. );
  31. this.context = getContext(canvas, '2d');
  32. }
  33. draw(
  34. configViewToPhysicalSpace: mat3,
  35. configView: Rect,
  36. context: CanvasRenderingContext2D = this.context
  37. ): void {
  38. if (this.intervals.length === 0) {
  39. return;
  40. }
  41. const height =
  42. this.theme.SIZES.LABEL_FONT_SIZE * window.devicePixelRatio +
  43. this.theme.SIZES.LABEL_FONT_PADDING * window.devicePixelRatio * 2 -
  44. this.theme.SIZES.LABEL_FONT_PADDING;
  45. context.strokeStyle = `rgba(${this.theme.COLORS.SAMPLE_TICK_COLOR.join(',')})`;
  46. context.lineWidth = this.theme.SIZES.INTERNAL_SAMPLE_TICK_LINE_WIDTH;
  47. for (let i = 0; i < this.intervals.length; i++) {
  48. const interval = this.intervals[i];
  49. if (interval < configView.left) {
  50. continue;
  51. }
  52. if (interval > configView.right) {
  53. break;
  54. }
  55. // Compute the x position of our interval from config space to physical
  56. const physicalIntervalPosition = Math.round(
  57. interval * configViewToPhysicalSpace[0] + configViewToPhysicalSpace[6]
  58. );
  59. context.strokeRect(physicalIntervalPosition, 0, 0, height);
  60. }
  61. }
  62. }
  63. export {SampleTickRenderer};