( text: string, context: CanvasRenderingContext2D, fullRect: Rect, drawableRect: Rect, config?: TextConfig, )
| 69 | }; |
| 70 | |
| 71 | export function drawText( |
| 72 | text: string, |
| 73 | context: CanvasRenderingContext2D, |
| 74 | fullRect: Rect, |
| 75 | drawableRect: Rect, |
| 76 | config?: TextConfig, |
| 77 | ): void { |
| 78 | const { |
| 79 | fillStyle = COLORS.TEXT_COLOR, |
| 80 | fontSize = FONT_SIZE, |
| 81 | textAlign = 'left', |
| 82 | } = config || {}; |
| 83 | |
| 84 | if (fullRect.size.width > TEXT_PADDING * 2) { |
| 85 | context.textAlign = textAlign; |
| 86 | context.textBaseline = 'middle'; |
| 87 | context.font = `${fontSize}px sans-serif`; |
| 88 | |
| 89 | const {x, y} = fullRect.origin; |
| 90 | |
| 91 | const trimmedName = trimText( |
| 92 | context, |
| 93 | text, |
| 94 | fullRect.size.width - TEXT_PADDING * 2 + (x < 0 ? x : 0), |
| 95 | ); |
| 96 | |
| 97 | if (trimmedName !== null) { |
| 98 | context.fillStyle = fillStyle; |
| 99 | |
| 100 | // Prevent text from visibly overflowing its container when clipped. |
| 101 | const textOverflowsViewableArea = !rectEqualToRect( |
| 102 | drawableRect, |
| 103 | fullRect, |
| 104 | ); |
| 105 | if (textOverflowsViewableArea) { |
| 106 | context.save(); |
| 107 | context.beginPath(); |
| 108 | context.rect( |
| 109 | drawableRect.origin.x, |
| 110 | drawableRect.origin.y, |
| 111 | drawableRect.size.width, |
| 112 | drawableRect.size.height, |
| 113 | ); |
| 114 | context.closePath(); |
| 115 | context.clip(); |
| 116 | } |
| 117 | |
| 118 | let textX; |
| 119 | if (textAlign === 'center') { |
| 120 | textX = x + fullRect.size.width / 2 + TEXT_PADDING - (x < 0 ? x : 0); |
| 121 | } else { |
| 122 | textX = x + TEXT_PADDING - (x < 0 ? x : 0); |
| 123 | } |
| 124 | |
| 125 | const textY = y + fullRect.size.height / 2; |
| 126 | |
| 127 | context.fillText(trimmedName, textX, textY); |
| 128 |
no test coverage detected