github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/packages/pyroscope-flamegraph/src/fitMode/fitMode.ts (about)

     1  export const TailMode = 'TAIL';
     2  export const HeadMode = 'HEAD';
     3  
     4  export type FitModes = typeof TailMode | typeof HeadMode;
     5  
     6  const margin = 3;
     7  
     8  /**
     9   * Returns a text and margin left used to write text into a canvas rectangle
    10   *
    11   * @param {FitModes} mode -
    12   * @param {number} charSize - Size in pixels of an individual character. Assumes it's a monospace font.
    13   * @param {number} rectWidth - Width in pixels of the rectangle
    14   * @param {string} fullText - The text that will be first tried.
    15   * @param {string} shortText - The text that willbe used when fullText can't fit. It's normally a substring of the original text.
    16   */
    17  
    18  interface fitToCanvasRectProps {
    19    mode: FitModes;
    20  
    21    /** charSize - Size in pixels of an individual character. Assumes it's a monospace font. */
    22    charSize: number;
    23  
    24    /** Width in pixels of the rectangle */
    25    rectWidth: number;
    26  
    27    /** The text that will be first tried to fit */
    28    fullText: string;
    29  
    30    /** The text that willbe used when fullText can't fit. It's normally a substring of the original text. */
    31    shortText: string;
    32  }
    33  
    34  export function fitToCanvasRect({
    35    mode,
    36    charSize,
    37    rectWidth,
    38    fullText,
    39    shortText,
    40  }: fitToCanvasRectProps) {
    41    switch (mode) {
    42      case TailMode:
    43        // Case 1:
    44        // content fits rectangle width
    45        // | rectangle |
    46        // | text |
    47        if (charSize * fullText.length <= rectWidth) {
    48          // assume it's a monospaced font
    49          return {
    50            mode,
    51            text: fullText,
    52            marginLeft: margin,
    53          };
    54        }
    55  
    56        // assume it's a monospaced font
    57        // if not the case, use
    58        // ctx.measureText(shortName).width
    59        const shortTextWidth = charSize * shortText.length;
    60  
    61        // Case 2:
    62        // short text fits rectangle width
    63        // | rectangle |
    64        // | long_text_text |
    65        // | shorttext |
    66        if (shortTextWidth <= rectWidth) {
    67          // assume it's a monospaced font
    68          return {
    69            mode,
    70            text: shortText,
    71            marginLeft: margin,
    72          };
    73        }
    74  
    75        // Case 3:
    76        // short text is bigger than rectangle width
    77        // add a negative margin left
    78        // so that the 'tail' of the string is visible
    79        //     | rectangle |
    80        // | my_short_text |
    81        return {
    82          mode,
    83          text: shortText,
    84          marginLeft: -(shortTextWidth - rectWidth + margin),
    85        };
    86  
    87      // Case 3:
    88      // Normal
    89      case HeadMode:
    90      default:
    91        return {
    92          mode,
    93          text: fullText,
    94          marginLeft: margin,
    95        };
    96    }
    97  }
    98  
    99  /**
   100   * Returns an inline style in React format
   101   * used to fit the content into a table cell
   102   * or an empty object if not applicable.
   103   * @param {FitModes} mode - The mode
   104   */
   105  export function fitIntoTableCell(mode: FitModes): React.CSSProperties {
   106    switch (mode) {
   107      case TailMode:
   108        return {
   109          // prints from right to left
   110          direction: 'rtl',
   111          overflow: 'hidden',
   112          textOverflow: 'ellipsis',
   113        };
   114  
   115      case HeadMode:
   116      default:
   117        return {
   118          overflow: 'hidden',
   119          textOverflow: 'ellipsis',
   120        };
   121    }
   122  }