Precise text wrapping using actual font measurements for optimal packing. Returns a list of tuples (line_text, is_paragraph_end) to track paragraph boundaries.
(text: str, max_width: int, font, font_size: int)
| 303 | |
| 304 | |
| 305 | def wrap_text_precise(text: str, max_width: int, font, font_size: int) -> List[Tuple[str, bool]]: |
| 306 | """ |
| 307 | Precise text wrapping using actual font measurements for optimal packing. |
| 308 | Returns a list of tuples (line_text, is_paragraph_end) to track paragraph boundaries. |
| 309 | """ |
| 310 | lines = [] |
| 311 | paragraphs = text.split('\n') |
| 312 | |
| 313 | for para_idx, paragraph in enumerate(paragraphs): |
| 314 | paragraph = paragraph.strip() |
| 315 | if not paragraph: |
| 316 | lines.append(("", True)) |
| 317 | continue |
| 318 | |
| 319 | words = paragraph.split() |
| 320 | current_line = "" |
| 321 | |
| 322 | for word in words: |
| 323 | test_line = current_line + (" " if current_line else "") + word |
| 324 | |
| 325 | # Use actual font measurement |
| 326 | try: |
| 327 | bbox = font.getbbox(test_line) |
| 328 | text_width = bbox[2] - bbox[0] |
| 329 | except: |
| 330 | # Fallback to character-based estimation |
| 331 | text_width = len(test_line) * font_size * 0.6 |
| 332 | |
| 333 | if text_width <= max_width: |
| 334 | current_line = test_line |
| 335 | else: |
| 336 | if current_line: |
| 337 | lines.append((current_line, False)) |
| 338 | current_line = word |
| 339 | |
| 340 | if current_line: |
| 341 | # Mark the last line of each paragraph |
| 342 | is_last_para = para_idx == len(paragraphs) - 1 |
| 343 | lines.append((current_line, not is_last_para)) |
| 344 | |
| 345 | return lines |
| 346 | |
| 347 | |
| 348 | # Cache for font metrics to avoid repeated calculations |
no outgoing calls
no test coverage detected