diff --git a/selfdrive/ui/onroad/alert_renderer.py b/selfdrive/ui/onroad/alert_renderer.py index 37276b11a4..7b0128271e 100644 --- a/selfdrive/ui/onroad/alert_renderer.py +++ b/selfdrive/ui/onroad/alert_renderer.py @@ -5,6 +5,7 @@ from cereal import messaging, log from openpilot.system.hardware import TICI from openpilot.system.ui.lib.application import gui_app, FontWeight, DEFAULT_FPS from openpilot.system.ui.lib.label import gui_text_box +from openpilot.system.ui.lib.text_measure import measure_text_cached from openpilot.selfdrive.ui.ui_state import ui_state @@ -64,7 +65,6 @@ class AlertRenderer: def __init__(self): self.font_regular: rl.Font = gui_app.font(FontWeight.NORMAL) self.font_bold: rl.Font = gui_app.font(FontWeight.BOLD) - self.font_metrics_cache: dict[tuple[str, int, str], rl.Vector2] = {} def get_alert(self, sm: messaging.SubMaster) -> Alert | None: """Generate the current alert based on selfdrive state.""" @@ -152,14 +152,8 @@ class AlertRenderer: text_rect.y = rect.y + rect.height // 2 gui_text_box(text_rect, alert.text2, ALERT_FONT_BIG, alignment=align_ment) - def _measure_text(self, font: rl.Font, text: str, font_size: int, font_type: str) -> rl.Vector2: - key = (text, font_size, font_type) - if key not in self.font_metrics_cache: - self.font_metrics_cache[key] = rl.measure_text_ex(font, text, font_size, 0) - return self.font_metrics_cache[key] - def _draw_centered(self, text, rect, font, font_size, center_y=True, color=rl.WHITE) -> None: - text_size = self._measure_text(font, text, font_size, 'bold' if font == self.font_bold else 'regular') + text_size = measure_text_cached(font, text, font_size) x = rect.x + (rect.width - text_size.x) / 2 y = rect.y + ((rect.height - text_size.y) / 2 if center_y else 0) rl.draw_text_ex(font, text, rl.Vector2(x, y), font_size, 0, color) diff --git a/selfdrive/ui/onroad/hud_renderer.py b/selfdrive/ui/onroad/hud_renderer.py index ed0b7cc974..0e893acfe9 100644 --- a/selfdrive/ui/onroad/hud_renderer.py +++ b/selfdrive/ui/onroad/hud_renderer.py @@ -3,6 +3,7 @@ from dataclasses import dataclass from cereal.messaging import SubMaster from openpilot.selfdrive.ui.ui_state import ui_state, UIStatus from openpilot.system.ui.lib.application import gui_app, FontWeight +from openpilot.system.ui.lib.text_measure import measure_text_cached from openpilot.common.conversions import Conversions as CV # Constants @@ -61,7 +62,6 @@ class HudRenderer: self.set_speed: float = SET_SPEED_NA self.speed: float = 0.0 self.v_ego_cluster_seen: bool = False - self.font_metrics_cache: dict[[str, int, str], rl.Vector2] = {} self._wheel_texture: rl.Texture = gui_app.texture('icons/chffr_wheel.png', UI_CONFIG.wheel_icon_size, UI_CONFIG.wheel_icon_size) self._font_semi_bold: rl.Font = gui_app.font(FontWeight.SEMI_BOLD) self._font_bold: rl.Font = gui_app.font(FontWeight.BOLD) @@ -134,7 +134,7 @@ class HudRenderer: max_color = COLORS.override max_text = "MAX" - max_text_width = self._measure_text(max_text, self._font_semi_bold, FONT_SIZES.max_speed, 'semi_bold').x + max_text_width = measure_text_cached(self._font_semi_bold, max_text, FONT_SIZES.max_speed).x rl.draw_text_ex( self._font_semi_bold, max_text, @@ -145,7 +145,7 @@ class HudRenderer: ) set_speed_text = CRUISE_DISABLED_CHAR if not self.is_cruise_set else str(round(self.set_speed)) - speed_text_width = self._measure_text(set_speed_text, self._font_bold, FONT_SIZES.set_speed, 'bold').x + speed_text_width = measure_text_cached(self._font_bold, set_speed_text, FONT_SIZES.set_speed).x rl.draw_text_ex( self._font_bold, set_speed_text, @@ -158,12 +158,12 @@ class HudRenderer: def _draw_current_speed(self, rect: rl.Rectangle) -> None: """Draw the current vehicle speed and unit.""" speed_text = str(round(self.speed)) - speed_text_size = self._measure_text(speed_text, self._font_bold, FONT_SIZES.current_speed, 'bold') + speed_text_size = measure_text_cached(self._font_bold, speed_text, FONT_SIZES.current_speed) speed_pos = rl.Vector2(rect.x + rect.width / 2 - speed_text_size.x / 2, 180 - speed_text_size.y / 2) rl.draw_text_ex(self._font_bold, speed_text, speed_pos, FONT_SIZES.current_speed, 0, COLORS.white) unit_text = "km/h" if ui_state.is_metric else "mph" - unit_text_size = self._measure_text(unit_text, self._font_medium, FONT_SIZES.speed_unit, 'medium') + unit_text_size = measure_text_cached(self._font_medium, unit_text, FONT_SIZES.speed_unit) unit_pos = rl.Vector2(rect.x + rect.width / 2 - unit_text_size.x / 2, 290 - unit_text_size.y / 2) rl.draw_text_ex(self._font_medium, unit_text, unit_pos, FONT_SIZES.speed_unit, 0, COLORS.white_translucent) @@ -176,10 +176,3 @@ class HudRenderer: opacity = 0.7 if ui_state.status == UIStatus.DISENGAGED else 1.0 img_pos = rl.Vector2(center_x - self._wheel_texture.width / 2, center_y - self._wheel_texture.height / 2) rl.draw_texture_v(self._wheel_texture, img_pos, rl.Color(255, 255, 255, int(255 * opacity))) - - def _measure_text(self, text: str, font: rl.Font, font_size: int, font_type: str) -> rl.Vector2: - """Measure text dimensions with caching.""" - key = (text, font_size, font_type) - if key not in self.font_metrics_cache: - self.font_metrics_cache[key] = rl.measure_text_ex(font, text, font_size, 0) - return self.font_metrics_cache[key] diff --git a/system/ui/lib/text_measure.py b/system/ui/lib/text_measure.py new file mode 100644 index 0000000000..9cdd566409 --- /dev/null +++ b/system/ui/lib/text_measure.py @@ -0,0 +1,13 @@ +import pyray as rl + +_cache: dict[int, rl.Vector2] = {} + + +def measure_text_cached(font: rl.Font, text: str, font_size: int, spacing: int = 0) -> rl.Vector2: + key = hash((font.texture.id, text, font_size, spacing)) + if key in _cache: + return _cache[key] + + result = rl.measure_text_ex(font, text, font_size, spacing) + _cache[key] = result + return result