import pyray as rl from openpilot.system.ui.lib.text_measure import measure_text_cached def _break_long_word(font: rl.Font, word: str, font_size: int, max_width: int) -> list[str]: if not word: return [] parts = [] remaining = word while remaining: if measure_text_cached(font, remaining, font_size).x <= max_width: parts.append(remaining) break # Binary search for the longest substring that fits left, right = 1, len(remaining) best_fit = 1 while left <= right: mid = (left + right) // 2 substring = remaining[:mid] width = measure_text_cached(font, substring, font_size).x if width <= max_width: best_fit = mid left = mid + 1 else: right = mid - 1 # Add the part that fits parts.append(remaining[:best_fit]) remaining = remaining[best_fit:] return parts def wrap_text(font: rl.Font, text: str, font_size: int, max_width: int) -> list[str]: if not text or max_width <= 0: return [] # Split text by newlines first to preserve explicit line breaks paragraphs = text.split('\n') all_lines: list[str] = [] for paragraph in paragraphs: # Handle empty paragraphs (preserve empty lines) if not paragraph.strip(): all_lines.append("") continue # Process each paragraph separately words = paragraph.split() if not words: all_lines.append("") continue lines: list[str] = [] current_line: list[str] = [] current_width = 0 space_width = int(measure_text_cached(font, " ", font_size).x) for word in words: word_width = int(measure_text_cached(font, word, font_size).x) # Check if word alone exceeds max width (need to break the word) if word_width > max_width: # Finish current line if it has content if current_line: lines.append(" ".join(current_line)) current_line = [] current_width = 0 # Break the long word into parts lines.extend(_break_long_word(font, word, font_size, max_width)) continue # Calculate width if we add this word needed_width = current_width if current_line: # Need space before word needed_width += space_width needed_width += word_width # Check if word fits on current line if needed_width <= max_width: current_line.append(word) current_width = needed_width else: # Start new line with this word if current_line: lines.append(" ".join(current_line)) current_line = [word] current_width = word_width # Add remaining words if current_line: lines.append(" ".join(current_line)) # Add all lines from this paragraph all_lines.extend(lines) return all_lines