System/Libraries/Html/Renderer: Handle node->textAlign a bit better

Just a few QoL tweaks for now, until we properly handle CSS, layout,
and everything else.
This commit is contained in:
Alec Murphy 2025-04-14 10:53:05 -04:00
parent 72d626c0f1
commit 6532218883

View file

@ -1,4 +1,4 @@
#define RENDERER_DEFAULT_MAX_LINE_HEIGHT 8 #define RENDERER_DEFAULT_MAX_LINE_HEIGHT 17
class @html_lazyload_image class @html_lazyload_image
{ {
@ -37,6 +37,7 @@ class @html_renderer
I64 render_y; I64 render_y;
I64 indent; I64 indent;
I64 max_line_height; I64 max_line_height;
I64 calculated_page_height;
Context2D* link_pointer; Context2D* link_pointer;
U64 link_callback; U64 link_callback;
}; };
@ -651,6 +652,7 @@ U0 @render_node_text(@html_dom_node* node, HtmlRenderer* renderer)
return; return;
I64 i, j; I64 i, j;
node->textAlign = node->parentNode->textAlign;
// Convert all the code points to I32 // Convert all the code points to I32
I64 code_point_count = 0; I64 code_point_count = 0;
@ -846,7 +848,7 @@ U0 @render_node_list(@html_dom_node* node, HtmlRenderer* renderer)
} }
// Insert a block widget for the element's closing tag // Insert a block widget for the element's closing tag
if (node->display_block) { if (node->display_block || !StrICmp(node->tagName, "br")) {
block_widget = Gui.CreateWidget(renderer->win, WIDGET_TYPE_CONTEXT2D, block_widget = Gui.CreateWidget(renderer->win, WIDGET_TYPE_CONTEXT2D,
U64_MAX, U64_MAX, 0, 0); U64_MAX, U64_MAX, 0, 0);
block_widget->data = node; block_widget->data = node;
@ -871,52 +873,86 @@ U0 @reflow_node_list(HtmlRenderer* renderer)
return; return;
if (!renderer->widgets_base) if (!renderer->widgets_base)
return; return;
I64 prev_render_y = renderer->render_y;
renderer->render_x = 0; renderer->render_x = 0;
renderer->render_y = renderer->background_widget->y; renderer->render_y = 0;
if (renderer->vertical_scroll_widget && prev_render_y && renderer->vertical_scroll_widget->scroll) {
renderer->render_y -= (renderer->vertical_scroll_widget->scroll * (prev_render_y / renderer->vertical_scroll_widget->height));
}
renderer->max_line_height = RENDERER_DEFAULT_MAX_LINE_HEIGHT; renderer->max_line_height = RENDERER_DEFAULT_MAX_LINE_HEIGHT;
I64 cumulative_widgets_width; VerticalScrollBarWidget* vscroll = renderer->vertical_scroll_widget;
@window_widgets_list* cumulative_list_item;
@window_widgets_list* widget_list_item = renderer->widgets_base->next; I64 origin_y = renderer->background_widget->y;
Widget* widget; I64 offset_y = origin_y;
I64 line_break_max = 0;
I64 minimum_vscroll_value = 0;
if (vscroll && vscroll->max && vscroll->value) {
minimum_vscroll_value = ToI64((vscroll->max * 1.0) / (vscroll->height * 1.0) * (16 * 1.0));
offset_y -= vscroll->value - minimum_vscroll_value;
}
@html_dom_node* node; @html_dom_node* node;
@html_dom_node* cumulative_node;
I64 cumulative_widgets_width;
@window_widgets_list* widget_list_item = renderer->widgets_base->next;
@window_widgets_list* cumulative_list_item;
Widget* widget;
while (widget_list_item) { while (widget_list_item) {
widget = widget_list_item->widget; widget = widget_list_item->widget;
node = widget->data; node = widget->data;
if (node) { if (node) {
if (node->display_block && renderer->render_x) {
if (!StrICmp(node->tagName, "br")) {
renderer->render_x = 0;
renderer->render_y += renderer->max_line_height;
renderer->max_line_height = RENDERER_DEFAULT_MAX_LINE_HEIGHT;
goto reflow_next_list_item;
}
if (node->display_block) {
if (renderer->render_x) {
renderer->render_x = 0; renderer->render_x = 0;
renderer->render_y += renderer->max_line_height; renderer->render_y += renderer->max_line_height;
renderer->max_line_height = RENDERER_DEFAULT_MAX_LINE_HEIGHT; renderer->max_line_height = RENDERER_DEFAULT_MAX_LINE_HEIGHT;
} }
goto reflow_next_list_item;
}
if (!renderer->render_x && node->textAlign) { if (!renderer->render_x && node->textAlign) {
// Begin calculating x offset for text alignment
cumulative_widgets_width = widget->width;
cumulative_list_item = widget_list_item->next; cumulative_list_item = widget_list_item->next;
cumulative_widgets_width = 0; while (cumulative_list_item && cumulative_list_item->widget && cumulative_list_item->widget->data) {
while (cumulative_list_item && cumulative_list_item->widget && !cumulative_list_item->widget->data(@html_dom_node*)->display_block) { cumulative_node = cumulative_list_item->widget->data;
if (cumulative_node->display_block || !StrICmp(cumulative_node->tagName, "br")) {
cumulative_list_item = NULL;
} else {
cumulative_widgets_width += cumulative_list_item->widget->width; cumulative_widgets_width += cumulative_list_item->widget->width;
cumulative_list_item = cumulative_list_item->next; cumulative_list_item = cumulative_list_item->next;
} }
}
switch (node->textAlign) { switch (node->textAlign) {
case CSS_TEXT_ALIGN_CENTER: case CSS_TEXT_ALIGN_CENTER:
renderer->render_x = (renderer->win->width / 2) - (cumulative_widgets_width / 2); renderer->render_x = (renderer->win->width / 2) - (cumulative_widgets_width / 2);
break; break;
case CSS_TEXT_ALIGN_RIGHT: case CSS_TEXT_ALIGN_RIGHT:
renderer->render_x = renderer->win->width - cumulative_widgets_width; renderer->render_x = -8 + renderer->win->width - cumulative_widgets_width;
break; break;
default: default:
"ERROR: Invalid node->textAlign value: %d\n", node->textAlign;
PressAKey;
break; break;
} }
} }
line_break_max = 8;
if (!node->textAlign) {
line_break_max += widget->width + 16;
}
widget->x = renderer->render_x; widget->x = renderer->render_x;
widget->y = renderer->render_y; widget->y = renderer->render_y + offset_y;
if (@self_or_ancestor_matches_tag_name(node, "a")) { if (@self_or_ancestor_matches_tag_name(node, "a")) {
widget->pointer = renderer->link_pointer; widget->pointer = renderer->link_pointer;
Gui.Widget.SetCallback(widget, "clicked", renderer->link_callback); Gui.Widget.SetCallback(widget, "clicked", renderer->link_callback);
@ -925,15 +961,24 @@ U0 @reflow_node_list(HtmlRenderer* renderer)
renderer->render_x += widget->width; renderer->render_x += widget->width;
renderer->max_line_height = Max(renderer->max_line_height, widget->height); renderer->max_line_height = Max(renderer->max_line_height, widget->height);
if (renderer->render_x > renderer->win->width - widget->width) { if (renderer->render_x > renderer->win->width - line_break_max) {
renderer->render_x = 0; renderer->render_x = 0;
renderer->render_y += renderer->max_line_height; renderer->render_y += renderer->max_line_height;
renderer->max_line_height = RENDERER_DEFAULT_MAX_LINE_HEIGHT; renderer->max_line_height = RENDERER_DEFAULT_MAX_LINE_HEIGHT;
} }
} }
reflow_next_list_item:
widget_list_item = widget_list_item->next; widget_list_item = widget_list_item->next;
} }
if (renderer->render_x) {
renderer->render_x = 0;
renderer->render_y += renderer->max_line_height;
renderer->max_line_height = RENDERER_DEFAULT_MAX_LINE_HEIGHT;
}
renderer->calculated_page_height = renderer->render_y - origin_y;
} }
U0 @process_css_rules_from_external_stylesheet(HtmlRenderer* renderer, U8* str) U0 @process_css_rules_from_external_stylesheet(HtmlRenderer* renderer, U8* str)