( context: CanvasRenderingContext2D, text: string, width: number, )
| 28 | } |
| 29 | |
| 30 | export function trimText( |
| 31 | context: CanvasRenderingContext2D, |
| 32 | text: string, |
| 33 | width: number, |
| 34 | ): string | null { |
| 35 | const maxIndex = text.length - 1; |
| 36 | |
| 37 | let startIndex = 0; |
| 38 | let stopIndex = maxIndex; |
| 39 | |
| 40 | let longestValidIndex = 0; |
| 41 | let longestValidText = null; |
| 42 | |
| 43 | // Trimming long text could be really slow if we decrease only 1 character at a time. |
| 44 | // Trimming with more of a binary search approach is faster in the worst cases. |
| 45 | while (startIndex <= stopIndex) { |
| 46 | const currentIndex = Math.floor((startIndex + stopIndex) / 2); |
| 47 | const trimmedText = |
| 48 | currentIndex === maxIndex ? text : text.slice(0, currentIndex) + '…'; |
| 49 | |
| 50 | if (getTextWidth(context, trimmedText) <= width) { |
| 51 | if (longestValidIndex < currentIndex) { |
| 52 | longestValidIndex = currentIndex; |
| 53 | longestValidText = trimmedText; |
| 54 | } |
| 55 | |
| 56 | startIndex = currentIndex + 1; |
| 57 | } else { |
| 58 | stopIndex = currentIndex - 1; |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | return longestValidText; |
| 63 | } |
| 64 | |
| 65 | type TextConfig = { |
| 66 | fillStyle?: string, |
no test coverage detected