@@ -266,57 +266,119 @@ String RichTextLabel::_get_prefix(Item *p_item, const Vector<int> &p_list_index,
266266 return prefix + " " ;
267267}
268268
269- void RichTextLabel::_update_line_font (ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size) {
270- ERR_FAIL_NULL (p_frame);
271- ERR_FAIL_COND (p_line < 0 || p_line >= (int )p_frame->lines .size ());
272-
273- Line &l = p_frame->lines [p_line];
274- MutexLock lock (l.text_buf ->get_mutex ());
275-
276- // Prefix.
269+ void RichTextLabel::_add_list_prefixes (ItemFrame *p_frame, int p_line, Line &r_l) {
277270 Vector<int > list_index;
278271 Vector<int > list_count;
279272 Vector<ItemList *> list_items;
280- _find_list (l.from , list_index, list_count, list_items);
281-
273+ _find_list (r_l.from , list_index, list_count, list_items);
282274 if (list_items.size () > 0 ) {
275+ ItemList *this_list = list_items[0 ];
283276 if (list_index[0 ] == 1 ) {
284277 // List level start, shape all prefixes for this level and compute max. prefix width.
285278 list_items[0 ]->max_width = 0 ;
286279 int index = 0 ;
287- for (int i = p_line; i < (int )p_frame->lines .size (); i++) {
288- Line &list_l = p_frame->lines [i];
289- if (_find_list_item (list_l .from ) == list_items[ 0 ] ) {
280+ for (int i = p_line; i < (int )p_frame->lines .size (); i++) { // For all the list rows in all lists in this frame.
281+ Line &list_row_line = p_frame->lines [i];
282+ if (_find_list_item (list_row_line .from ) == this_list ) { // Is a row inside this list.
290283 index++;
291-
292284 Ref<Font> font = theme_cache.normal_font ;
293285 int font_size = theme_cache.normal_font_size ;
294-
295- ItemFont *font_it = _find_font (list_l.from );
296- if (font_it) {
297- if (font_it->font .is_valid ()) {
298- font = font_it->font ;
286+ int list_row_char_ofs = list_row_line.from ->char_ofs ;
287+ int item_font_size = -1 ;
288+ ItemFont *found_font_item = nullptr ;
289+ Vector<Item *> formatting_items_info;
290+ ItemText *this_row_text_item = nullptr ;
291+ Item *it = _get_next_item (this_list);
292+ while (it && (this_row_text_item != nullptr || it->char_ofs <= list_row_char_ofs)) { // Find the ItemText for this list row. There is only one per row or none.
293+ if (it->type == ITEM_TEXT && it->char_ofs == list_row_char_ofs) {
294+ ItemText *text_item = static_cast <ItemText *>(it);
295+ this_row_text_item = text_item;
296+ // `parent` is the enclosing item tag, if any, which itself can be further enclosed by another tag and so on,
297+ // all of which will be applied to the text item. The `parent` is an interval predecessor, not a hierarchical parent.
298+ Item *parent = text_item->parent ;
299+ while (parent && parent != main) {
300+ // `formatting_items` is an Array of all ITEM types affecting glyph appearance, like ITEM_FONT, ITEM_COLOR, etc.
301+ if (formatting_items.has (parent->type )) {
302+ formatting_items_info.push_back (parent);
303+ }
304+ parent = parent->parent ;
305+ }
299306 }
300- if (font_it->font_size > 0 ) {
301- font_size = font_it->font_size ;
307+ it = _get_next_item (it);
308+ }
309+ if (this_row_text_item == nullptr ) { // If the row doesn't have any text yet.
310+ it = _get_next_item (this_list);
311+ // All format items at the same char location should be applied to the prefix.
312+ // This won't add any earlier tags.
313+ while (it && it->char_ofs <= list_row_char_ofs) {
314+ if (formatting_items.has (it->type ) && it->char_ofs == list_row_char_ofs) {
315+ formatting_items_info.push_back (it);
316+ }
317+ it = _get_next_item (it);
302318 }
303319 }
304- ItemFontSize *font_size_it = _find_font_size (list_l.from );
305- if (font_size_it && font_size_it->font_size > 0 ) {
306- font_size = font_size_it->font_size ;
320+ for (Item *format_item : formatting_items_info) {
321+ switch (format_item->type ) {
322+ case ITEM_FONT: {
323+ ItemFont *font_item = static_cast <ItemFont *>(format_item);
324+ if (font_item->def_font != RTL_CUSTOM_FONT) {
325+ font_item = _find_font (format_item); // Sets `def_font` based on font type.
326+ }
327+ if (font_item->font .is_valid ()) {
328+ if (font_item->def_font == RTL_BOLD_ITALICS_FONT) { // Always set bold italic.
329+ found_font_item = font_item;
330+ } else if (found_font_item == nullptr || found_font_item->def_font != RTL_BOLD_ITALICS_FONT) { // Don't overwrite BOLD_ITALIC with BOLD or ITALIC.
331+ found_font_item = font_item;
332+ }
333+ }
334+ if (found_font_item->font_size > 0 ) {
335+ font_size = found_font_item->font_size ;
336+ }
337+ } break ;
338+ case ITEM_FONT_SIZE: {
339+ ItemFontSize *font_size_item = static_cast <ItemFontSize *>(format_item);
340+ item_font_size = font_size_item->font_size ;
341+ } break ;
342+ case ITEM_COLOR: {
343+ ItemColor *color_item = static_cast <ItemColor *>(format_item);
344+ list_row_line.prefix_color = color_item->color ;
345+ } break ;
346+ case ITEM_OUTLINE_SIZE: {
347+ ItemOutlineSize *outline_size_item = static_cast <ItemOutlineSize *>(format_item);
348+ list_row_line.prefix_outline_size = outline_size_item->outline_size ;
349+ } break ;
350+ case ITEM_OUTLINE_COLOR: {
351+ ItemOutlineColor *outline_color_item = static_cast <ItemOutlineColor *>(format_item);
352+ list_row_line.prefix_outline_color = outline_color_item->color ;
353+ } break ;
354+ default : {
355+ } break ;
356+ }
307357 }
308-
358+ font = found_font_item != nullptr ? found_font_item->font : font;
359+ font_size = item_font_size != -1 ? item_font_size : font_size;
309360 list_index.write [0 ] = index;
310- String prefix = _get_prefix (list_l .from , list_index, list_items);
311- list_l .text_prefix .instantiate ();
312- list_l .text_prefix ->set_direction (_find_direction (list_l .from ));
313- list_l .text_prefix ->add_string (prefix, font, font_size);
314- list_items.write [0 ]->max_width = MAX (list_items[ 0 ] ->max_width , list_l .text_prefix ->get_size ().x );
361+ String prefix = _get_prefix (list_row_line .from , list_index, list_items);
362+ list_row_line .text_prefix .instantiate ();
363+ list_row_line .text_prefix ->set_direction (_find_direction (list_row_line .from ));
364+ list_row_line .text_prefix ->add_string (prefix, font, font_size);
365+ list_items.write [0 ]->max_width = MAX (this_list ->max_width , list_row_line .text_prefix ->get_size ().x );
315366 }
316367 }
317368 }
318- l .prefix_width = list_items[ 0 ] ->max_width ;
369+ r_l .prefix_width = this_list ->max_width ;
319370 }
371+ }
372+
373+ void RichTextLabel::_update_line_font (ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size) {
374+ ERR_FAIL_NULL (p_frame);
375+ ERR_FAIL_COND (p_line < 0 || p_line >= (int )p_frame->lines .size ());
376+
377+ Line &l = p_frame->lines [p_line];
378+ MutexLock lock (l.text_buf ->get_mutex ());
379+
380+ // List.
381+ _add_list_prefixes (p_frame, p_line, l);
320382
321383 RID t = l.text_buf ->get_rid ();
322384 int spans = TS->shaped_get_span_count (t);
@@ -471,50 +533,8 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
471533 l.char_offset = *r_char_offset;
472534 l.char_count = 0 ;
473535
474- // List prefix.
475- Vector<int > list_index;
476- Vector<int > list_count;
477- Vector<ItemList *> list_items;
478- _find_list (l.from , list_index, list_count, list_items);
479-
480- if (list_items.size () > 0 ) {
481- if (list_index[0 ] == 1 ) {
482- // List level start, shape all prefixes for this level and compute max. prefix width.
483- list_items[0 ]->max_width = 0 ;
484- int index = 0 ;
485- for (int i = p_line; i < (int )p_frame->lines .size (); i++) {
486- Line &list_l = p_frame->lines [i];
487- if (_find_list_item (list_l.from ) == list_items[0 ]) {
488- index++;
489-
490- Ref<Font> font = theme_cache.normal_font ;
491- int font_size = theme_cache.normal_font_size ;
492-
493- ItemFont *font_it = _find_font (list_l.from );
494- if (font_it) {
495- if (font_it->font .is_valid ()) {
496- font = font_it->font ;
497- }
498- if (font_it->font_size > 0 ) {
499- font_size = font_it->font_size ;
500- }
501- }
502- ItemFontSize *font_size_it = _find_font_size (list_l.from );
503- if (font_size_it && font_size_it->font_size > 0 ) {
504- font_size = font_size_it->font_size ;
505- }
506-
507- list_index.write [0 ] = index;
508- String prefix = _get_prefix (list_l.from , list_index, list_items);
509- list_l.text_prefix .instantiate ();
510- list_l.text_prefix ->set_direction (_find_direction (list_l.from ));
511- list_l.text_prefix ->add_string (prefix, font, font_size);
512- list_items.write [0 ]->max_width = MAX (list_items[0 ]->max_width , list_l.text_prefix ->get_size ().x );
513- }
514- }
515- }
516- l.prefix_width = list_items[0 ]->max_width ;
517- }
536+ // List.
537+ _add_list_prefixes (p_frame, p_line, l);
518538
519539 // Add indent.
520540 l.indent = _find_margin (l.from , p_base_font, p_base_font_size) + l.prefix_width ;
@@ -934,9 +954,9 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
934954
935955 bool skip_prefix = (trim_chars && l.char_offset > visible_characters) || (trim_glyphs_ltr && (r_processed_glyphs >= visible_glyphs)) || (trim_glyphs_rtl && (r_processed_glyphs < total_glyphs - visible_glyphs));
936956 if (l.text_prefix .is_valid () && line == 0 && !skip_prefix) {
937- Color font_color = _find_color (l.from , p_base_color);
938- int outline_size = _find_outline_size (l.from , p_outline_size);
939- Color font_outline_color = _find_outline_color (l.from , p_outline_color) ;
957+ Color font_color = l. prefix_color == Color ( 0 , 0 , 0 , 0 ) ? _find_color (l.from , p_base_color) : l. prefix_color ;
958+ int outline_size = l. prefix_outline_size == - 1 ? _find_outline_size (l.from , p_outline_size) : l. prefix_outline_size ;
959+ Color font_outline_color = l. prefix_outline_color == Color ( 0 , 0 , 0 , 0 ) ? _find_outline_color (l.from , p_base_color) : l. prefix_outline_color ;
940960 Color font_shadow_color = p_font_shadow_color * Color (1 , 1 , 1 , font_color.a );
941961 if (rtl) {
942962 if (p_shadow_outline_size > 0 && font_shadow_color.a != 0.0 ) {
@@ -3951,13 +3971,13 @@ void RichTextLabel::add_text(const String &p_text) {
39513971 }
39523972
39533973 if (eol) {
3954- ItemNewline *item = memnew (ItemNewline);
3974+ ItemNewline *item = memnew (ItemNewline); // Sets item->type to ITEM_NEWLINE.
39553975 item->owner = get_instance_id ();
39563976 item->rid = items.make_rid (item);
39573977 item->line = current_frame->lines .size ();
39583978 _add_item (item, false );
39593979 current_frame->lines .resize (current_frame->lines .size () + 1 );
3960- if (item->type != ITEM_NEWLINE) {
3980+ if (item->type != ITEM_NEWLINE) { // item IS an ITEM_NEWLINE so this will never get called?
39613981 current_frame->lines [current_frame->lines .size () - 1 ].from = item;
39623982 }
39633983 _invalidate_current_line (current_frame);
0 commit comments