dragonpilot - 基於 openpilot 的開源駕駛輔助系統
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 lines
2.7 KiB

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