cache expensive height calc

pull/36257/head
Shane Smiskol 4 days ago
parent aaeb4a59d7
commit d38a9ca97a
  1. 24
      system/ui/widgets/html_render.py

@ -53,7 +53,10 @@ class HtmlRenderer(Widget):
text_size: dict | None = None, text_color: rl.Color = rl.WHITE): text_size: dict | None = None, text_color: rl.Color = rl.WHITE):
super().__init__() super().__init__()
self._text_color = text_color self._text_color = text_color
self.elements: list[HtmlElement] = []
self._total_height = 0.0
self._height_needs_recompute = True
self._prev_content_width = -1
self._normal_font = gui_app.font(FontWeight.NORMAL) self._normal_font = gui_app.font(FontWeight.NORMAL)
self._bold_font = gui_app.font(FontWeight.BOLD) self._bold_font = gui_app.font(FontWeight.BOLD)
self._indent_level = 0 self._indent_level = 0
@ -73,6 +76,7 @@ class HtmlRenderer(Widget):
ElementType.BR: {"size": 0, "weight": FontWeight.NORMAL, "margin_top": 0, "margin_bottom": 12}, ElementType.BR: {"size": 0, "weight": FontWeight.NORMAL, "margin_top": 0, "margin_bottom": 12},
} }
self.elements: list[HtmlElement] = []
if file_path is not None: if file_path is not None:
self.parse_html_file(file_path) self.parse_html_file(file_path)
elif text is not None: elif text is not None:
@ -87,6 +91,7 @@ class HtmlRenderer(Widget):
def parse_html_content(self, html_content: str) -> None: def parse_html_content(self, html_content: str) -> None:
self.elements.clear() self.elements.clear()
self._height_needs_recompute = True
# Remove HTML comments # Remove HTML comments
html_content = re.sub(r'<!--.*?-->', '', html_content, flags=re.DOTALL) html_content = re.sub(r'<!--.*?-->', '', html_content, flags=re.DOTALL)
@ -190,27 +195,32 @@ class HtmlRenderer(Widget):
return current_y - rect.y return current_y - rect.y
def get_total_height(self, content_width: int) -> float: def get_total_height(self, content_width: int) -> float:
total_height = 0.0 if not self._height_needs_recompute and self._prev_content_width == content_width:
return self.total_height
self.total_height = 0.0
padding = 20 padding = 20
usable_width = content_width - (padding * 2) usable_width = content_width - (padding * 2)
for element in self.elements: for element in self.elements:
if element.type == ElementType.BR: if element.type == ElementType.BR:
total_height += element.margin_bottom self.total_height += element.margin_bottom
continue continue
total_height += element.margin_top self.total_height += element.margin_top
if element.content: if element.content:
font = self._get_font(element.font_weight) font = self._get_font(element.font_weight)
wrapped_lines = wrap_text(font, element.content, element.font_size, int(usable_width)) wrapped_lines = wrap_text(font, element.content, element.font_size, int(usable_width))
for _ in wrapped_lines: for _ in wrapped_lines:
total_height += element.font_size * element.line_height self.total_height += element.font_size * element.line_height
total_height += element.margin_bottom self.total_height += element.margin_bottom
return total_height self._prev_content_width = content_width
self._height_needs_recompute = False
return self.total_height
def _get_font(self, weight: FontWeight): def _get_font(self, weight: FontWeight):
if weight == FontWeight.BOLD: if weight == FontWeight.BOLD:

Loading…
Cancel
Save