@@ -257,57 +257,119 @@ String RichTextLabel::_get_prefix(Item *p_item, const Vector<int> &p_list_index,
257257 return prefix + " " ;
258258}
259259
260- void RichTextLabel::_update_line_font (ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size) {
261- ERR_FAIL_NULL (p_frame);
262- ERR_FAIL_COND (p_line < 0 || p_line >= (int )p_frame->lines .size ());
263-
264- Line &l = p_frame->lines [p_line];
265- MutexLock lock (l.text_buf ->get_mutex ());
266-
267- // Prefix.
260+ void RichTextLabel::_add_list_prefixes (ItemFrame *p_frame, int p_line, Line &r_l) {
268261 Vector<int > list_index;
269262 Vector<int > list_count;
270263 Vector<ItemList *> list_items;
271- _find_list (l.from , list_index, list_count, list_items);
272-
264+ _find_list (r_l.from , list_index, list_count, list_items);
273265 if (list_items.size () > 0 ) {
266+ ItemList *this_list = list_items[0 ];
274267 if (list_index[0 ] == 1 ) {
275268 // List level start, shape all prefixes for this level and compute max. prefix width.
276269 list_items[0 ]->max_width = 0 ;
277270 int index = 0 ;
278- for (int i = p_line; i < (int )p_frame->lines .size (); i++) {
279- Line &list_l = p_frame->lines [i];
280- if (_find_list_item (list_l .from ) == list_items[ 0 ] ) {
271+ for (int i = p_line; i < (int )p_frame->lines .size (); i++) { // For all the list rows in all lists in this frame.
272+ Line &list_row_line = p_frame->lines [i];
273+ if (_find_list_item (list_row_line .from ) == this_list ) { // Is a row inside this list.
281274 index++;
282-
283275 Ref<Font> font = theme_cache.normal_font ;
284276 int font_size = theme_cache.normal_font_size ;
285-
286- ItemFont *font_it = _find_font (list_l.from );
287- if (font_it) {
288- if (font_it->font .is_valid ()) {
289- font = font_it->font ;
277+ int list_row_char_ofs = list_row_line.from ->char_ofs ;
278+ int item_font_size = -1 ;
279+ ItemFont *found_font_item = nullptr ;
280+ Vector<Item *> formatting_items_info;
281+ ItemText *this_row_text_item = nullptr ;
282+ Item *it = _get_next_item (this_list);
283+ 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.
284+ if (it->type == ITEM_TEXT && it->char_ofs == list_row_char_ofs) {
285+ ItemText *text_item = static_cast <ItemText *>(it);
286+ this_row_text_item = text_item;
287+ // `parent` is the enclosing item tag, if any, which itself can be further enclosed by another tag and so on,
288+ // all of which will be applied to the text item. The `parent` is an interval predecessor, not a hierarchical parent.
289+ Item *parent = text_item->parent ;
290+ while (parent && parent != main) {
291+ // `formatting_items` is an Array of all ITEM types affecting glyph appearance, like ITEM_FONT, ITEM_COLOR, etc.
292+ if (formatting_items.has (parent->type )) {
293+ formatting_items_info.push_back (parent);
294+ }
295+ parent = parent->parent ;
296+ }
290297 }
291- if (font_it->font_size > 0 ) {
292- font_size = font_it->font_size ;
298+ it = _get_next_item (it);
299+ }
300+ if (this_row_text_item == nullptr ) { // If the row doesn't have any text yet.
301+ it = _get_next_item (this_list);
302+ // All format items at the same char location should be applied to the prefix.
303+ // This won't add any earlier tags.
304+ while (it && it->char_ofs <= list_row_char_ofs) {
305+ if (formatting_items.has (it->type ) && it->char_ofs == list_row_char_ofs) {
306+ formatting_items_info.push_back (it);
307+ }
308+ it = _get_next_item (it);
293309 }
294310 }
295- ItemFontSize *font_size_it = _find_font_size (list_l.from );
296- if (font_size_it && font_size_it->font_size > 0 ) {
297- font_size = font_size_it->font_size ;
311+ for (Item *format_item : formatting_items_info) {
312+ switch (format_item->type ) {
313+ case ITEM_FONT: {
314+ ItemFont *font_item = static_cast <ItemFont *>(format_item);
315+ if (font_item->def_font != RTL_CUSTOM_FONT) {
316+ font_item = _find_font (format_item); // Sets `def_font` based on font type.
317+ }
318+ if (font_item->font .is_valid ()) {
319+ if (font_item->def_font == RTL_BOLD_ITALICS_FONT) { // Always set bold italic.
320+ found_font_item = font_item;
321+ } else if (found_font_item == nullptr || found_font_item->def_font != RTL_BOLD_ITALICS_FONT) { // Don't overwrite BOLD_ITALIC with BOLD or ITALIC.
322+ found_font_item = font_item;
323+ }
324+ }
325+ if (found_font_item->font_size > 0 ) {
326+ font_size = found_font_item->font_size ;
327+ }
328+ } break ;
329+ case ITEM_FONT_SIZE: {
330+ ItemFontSize *font_size_item = static_cast <ItemFontSize *>(format_item);
331+ item_font_size = font_size_item->font_size ;
332+ } break ;
333+ case ITEM_COLOR: {
334+ ItemColor *color_item = static_cast <ItemColor *>(format_item);
335+ list_row_line.prefix_color = color_item->color ;
336+ } break ;
337+ case ITEM_OUTLINE_SIZE: {
338+ ItemOutlineSize *outline_size_item = static_cast <ItemOutlineSize *>(format_item);
339+ list_row_line.prefix_outline_size = outline_size_item->outline_size ;
340+ } break ;
341+ case ITEM_OUTLINE_COLOR: {
342+ ItemOutlineColor *outline_color_item = static_cast <ItemOutlineColor *>(format_item);
343+ list_row_line.prefix_outline_color = outline_color_item->color ;
344+ } break ;
345+ default : {
346+ } break ;
347+ }
298348 }
299-
349+ font = found_font_item != nullptr ? found_font_item->font : font;
350+ font_size = item_font_size != -1 ? item_font_size : font_size;
300351 list_index.write [0 ] = index;
301- String prefix = _get_prefix (list_l .from , list_index, list_items);
302- list_l .text_prefix .instantiate ();
303- list_l .text_prefix ->set_direction (_find_direction (list_l .from ));
304- list_l .text_prefix ->add_string (prefix, font, font_size);
305- list_items.write [0 ]->max_width = MAX (list_items[ 0 ] ->max_width , list_l .text_prefix ->get_size ().x );
352+ String prefix = _get_prefix (list_row_line .from , list_index, list_items);
353+ list_row_line .text_prefix .instantiate ();
354+ list_row_line .text_prefix ->set_direction (_find_direction (list_row_line .from ));
355+ list_row_line .text_prefix ->add_string (prefix, font, font_size);
356+ list_items.write [0 ]->max_width = MAX (this_list ->max_width , list_row_line .text_prefix ->get_size ().x );
306357 }
307358 }
308359 }
309- l .prefix_width = list_items[ 0 ] ->max_width ;
360+ r_l .prefix_width = this_list ->max_width ;
310361 }
362+ }
363+
364+ void RichTextLabel::_update_line_font (ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size) {
365+ ERR_FAIL_NULL (p_frame);
366+ ERR_FAIL_COND (p_line < 0 || p_line >= (int )p_frame->lines .size ());
367+
368+ Line &l = p_frame->lines [p_line];
369+ MutexLock lock (l.text_buf ->get_mutex ());
370+
371+ // List.
372+ _add_list_prefixes (p_frame, p_line, l);
311373
312374 RID t = l.text_buf ->get_rid ();
313375 int spans = TS->shaped_get_span_count (t);
@@ -458,50 +520,8 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
458520 l.char_offset = *r_char_offset;
459521 l.char_count = 0 ;
460522
461- // List prefix.
462- Vector<int > list_index;
463- Vector<int > list_count;
464- Vector<ItemList *> list_items;
465- _find_list (l.from , list_index, list_count, list_items);
466-
467- if (list_items.size () > 0 ) {
468- if (list_index[0 ] == 1 ) {
469- // List level start, shape all prefixes for this level and compute max. prefix width.
470- list_items[0 ]->max_width = 0 ;
471- int index = 0 ;
472- for (int i = p_line; i < (int )p_frame->lines .size (); i++) {
473- Line &list_l = p_frame->lines [i];
474- if (_find_list_item (list_l.from ) == list_items[0 ]) {
475- index++;
476-
477- Ref<Font> font = theme_cache.normal_font ;
478- int font_size = theme_cache.normal_font_size ;
479-
480- ItemFont *font_it = _find_font (list_l.from );
481- if (font_it) {
482- if (font_it->font .is_valid ()) {
483- font = font_it->font ;
484- }
485- if (font_it->font_size > 0 ) {
486- font_size = font_it->font_size ;
487- }
488- }
489- ItemFontSize *font_size_it = _find_font_size (list_l.from );
490- if (font_size_it && font_size_it->font_size > 0 ) {
491- font_size = font_size_it->font_size ;
492- }
493-
494- list_index.write [0 ] = index;
495- String prefix = _get_prefix (list_l.from , list_index, list_items);
496- list_l.text_prefix .instantiate ();
497- list_l.text_prefix ->set_direction (_find_direction (list_l.from ));
498- list_l.text_prefix ->add_string (prefix, font, font_size);
499- list_items.write [0 ]->max_width = MAX (list_items[0 ]->max_width , list_l.text_prefix ->get_size ().x );
500- }
501- }
502- }
503- l.prefix_width = list_items[0 ]->max_width ;
504- }
523+ // List.
524+ _add_list_prefixes (p_frame, p_line, l);
505525
506526 // Add indent.
507527 l.indent = _find_margin (l.from , p_base_font, p_base_font_size) + l.prefix_width ;
@@ -909,9 +929,9 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
909929
910930 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));
911931 if (l.text_prefix .is_valid () && line == 0 && !skip_prefix) {
912- Color font_color = _find_color (l.from , p_base_color);
913- int outline_size = _find_outline_size (l.from , p_outline_size);
914- Color font_outline_color = _find_outline_color (l.from , p_outline_color) ;
932+ Color font_color = l. prefix_color == Color ( 0 , 0 , 0 , 0 ) ? _find_color (l.from , p_base_color) : l. prefix_color ;
933+ int outline_size = l. prefix_outline_size == - 1 ? _find_outline_size (l.from , p_outline_size) : l. prefix_outline_size ;
934+ 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 ;
915935 Color font_shadow_color = p_font_shadow_color * Color (1 , 1 , 1 , font_color.a );
916936 if (rtl) {
917937 if (p_shadow_outline_size > 0 && font_shadow_color.a != 0.0 ) {
@@ -3866,13 +3886,13 @@ void RichTextLabel::add_text(const String &p_text) {
38663886 }
38673887
38683888 if (eol) {
3869- ItemNewline *item = memnew (ItemNewline);
3889+ ItemNewline *item = memnew (ItemNewline); // Sets item->type to ITEM_NEWLINE.
38703890 item->owner = get_instance_id ();
38713891 item->rid = items.make_rid (item);
38723892 item->line = current_frame->lines .size ();
38733893 _add_item (item, false );
38743894 current_frame->lines .resize (current_frame->lines .size () + 1 );
3875- if (item->type != ITEM_NEWLINE) {
3895+ if (item->type != ITEM_NEWLINE) { // item IS an ITEM_NEWLINE so this will never get called?
38763896 current_frame->lines [current_frame->lines .size () - 1 ].from = item;
38773897 }
38783898 _invalidate_current_line (current_frame);
0 commit comments