Skip to content

Commit

Permalink
Fix text shadow outline draw batching.
Browse files Browse the repository at this point in the history
  • Loading branch information
bruvzg committed Mar 2, 2025
1 parent 15ff450 commit 23b98d3
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 25 deletions.
38 changes: 24 additions & 14 deletions scene/gui/label.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,14 +392,15 @@ inline void draw_glyph(const Glyph &p_gl, const RID &p_canvas, const Color &p_fo
}
}

inline void draw_glyph_shadow(const Glyph &p_gl, const RID &p_canvas, const Color &p_font_shadow_color, int p_shadow_outline_size, const Vector2 &p_ofs, const Vector2 &shadow_ofs) {
inline void draw_glyph_shadow(const Glyph &p_gl, const RID &p_canvas, const Color &p_font_shadow_color, const Vector2 &p_ofs, const Vector2 &shadow_ofs) {
if (p_gl.font_rid != RID()) {
if (p_font_shadow_color.a > 0) {
TS->font_draw_glyph(p_gl.font_rid, p_canvas, p_gl.font_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off) + shadow_ofs, p_gl.index, p_font_shadow_color);
}
if (p_font_shadow_color.a > 0 && p_shadow_outline_size > 0) {
TS->font_draw_glyph_outline(p_gl.font_rid, p_canvas, p_gl.font_size, p_shadow_outline_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off) + shadow_ofs, p_gl.index, p_font_shadow_color);
}
TS->font_draw_glyph(p_gl.font_rid, p_canvas, p_gl.font_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off) + shadow_ofs, p_gl.index, p_font_shadow_color);
}
}

inline void draw_glyph_shadow_outline(const Glyph &p_gl, const RID &p_canvas, const Color &p_font_shadow_color, int p_shadow_outline_size, const Vector2 &p_ofs, const Vector2 &shadow_ofs) {
if (p_gl.font_rid != RID()) {
TS->font_draw_glyph_outline(p_gl.font_rid, p_canvas, p_gl.font_size, p_shadow_outline_size, p_ofs + Vector2(p_gl.x_off, p_gl.y_off) + shadow_ofs, p_gl.index, p_font_shadow_color);
}
}

Expand Down Expand Up @@ -768,7 +769,10 @@ void Label::_notification(int p_what) {

// Draw shadow, outline and text. Note: Do not merge this into the single loop iteration, to prevent overlaps.
int processed_glyphs_step = 0;
for (int step = DRAW_STEP_SHADOW; step < DRAW_STEP_MAX; step++) {
for (int step = DRAW_STEP_SHADOW_OUTLINE; step < DRAW_STEP_MAX; step++) {
if (step == DRAW_STEP_SHADOW_OUTLINE && (font_shadow_color.a == 0 || shadow_outline_size <= 0)) {
continue;
}
if (step == DRAW_STEP_SHADOW && (font_shadow_color.a == 0)) {
continue;
}
Expand All @@ -784,8 +788,10 @@ void Label::_notification(int p_what) {
for (int j = 0; j < ellipsis_glyphs[gl_idx].repeat; j++) {
bool skip = (trim_chars && ellipsis_glyphs[gl_idx].end + para.start > visible_chars) || (trim_glyphs_ltr && (processed_glyphs_step >= visible_glyphs)) || (trim_glyphs_rtl && (processed_glyphs_step < total_glyphs - visible_glyphs));
if (!skip) {
if (step == DRAW_STEP_SHADOW) {
draw_glyph_shadow(ellipsis_glyphs[gl_idx], ci, font_shadow_color, shadow_outline_size, offset_step, shadow_ofs);
if (step == DRAW_STEP_SHADOW_OUTLINE) {
draw_glyph_shadow_outline(ellipsis_glyphs[gl_idx], ci, font_shadow_color, shadow_outline_size, offset_step, shadow_ofs);
} else if (step == DRAW_STEP_SHADOW) {
draw_glyph_shadow(ellipsis_glyphs[gl_idx], ci, font_shadow_color, offset_step, shadow_ofs);
} else if (step == DRAW_STEP_OUTLINE) {
draw_glyph_outline(ellipsis_glyphs[gl_idx], ci, font_outline_color, outline_size, offset_step);
} else if (step == DRAW_STEP_TEXT) {
Expand Down Expand Up @@ -814,8 +820,10 @@ void Label::_notification(int p_what) {
for (int k = 0; k < glyphs[j].repeat; k++) {
bool skip = (trim_chars && glyphs[j].end + para.start > visible_chars) || (trim_glyphs_ltr && (processed_glyphs_step >= visible_glyphs)) || (trim_glyphs_rtl && (processed_glyphs_step < total_glyphs - visible_glyphs));
if (!skip) {
if (step == DRAW_STEP_SHADOW) {
draw_glyph_shadow(glyphs[j], ci, font_shadow_color, shadow_outline_size, offset_step, shadow_ofs);
if (step == DRAW_STEP_SHADOW_OUTLINE) {
draw_glyph_shadow_outline(glyphs[j], ci, font_shadow_color, shadow_outline_size, offset_step, shadow_ofs);
} else if (step == DRAW_STEP_SHADOW) {
draw_glyph_shadow(glyphs[j], ci, font_shadow_color, offset_step, shadow_ofs);
} else if (step == DRAW_STEP_OUTLINE) {
draw_glyph_outline(glyphs[j], ci, font_outline_color, outline_size, offset_step);
} else if (step == DRAW_STEP_TEXT) {
Expand All @@ -832,8 +840,10 @@ void Label::_notification(int p_what) {
for (int j = 0; j < ellipsis_glyphs[gl_idx].repeat; j++) {
bool skip = (trim_chars && ellipsis_glyphs[gl_idx].end + para.start > visible_chars) || (trim_glyphs_ltr && (processed_glyphs_step >= visible_glyphs)) || (trim_glyphs_rtl && (processed_glyphs_step < total_glyphs - visible_glyphs));
if (!skip) {
if (step == DRAW_STEP_SHADOW) {
draw_glyph_shadow(ellipsis_glyphs[gl_idx], ci, font_shadow_color, shadow_outline_size, offset_step, shadow_ofs);
if (step == DRAW_STEP_SHADOW_OUTLINE) {
draw_glyph_shadow_outline(ellipsis_glyphs[gl_idx], ci, font_shadow_color, shadow_outline_size, offset_step, shadow_ofs);
} else if (step == DRAW_STEP_SHADOW) {
draw_glyph_shadow(ellipsis_glyphs[gl_idx], ci, font_shadow_color, offset_step, shadow_ofs);
} else if (step == DRAW_STEP_OUTLINE) {
draw_glyph_outline(ellipsis_glyphs[gl_idx], ci, font_outline_color, outline_size, offset_step);
} else if (step == DRAW_STEP_TEXT) {
Expand Down
1 change: 1 addition & 0 deletions scene/gui/label.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class Label : public Control {

private:
enum LabelDrawStep {
DRAW_STEP_SHADOW_OUTLINE,
DRAW_STEP_SHADOW,
DRAW_STEP_OUTLINE,
DRAW_STEP_TEXT,
Expand Down
23 changes: 12 additions & 11 deletions scene/gui/rich_text_label.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1051,15 +1051,17 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
}
}

Color font_color = (step == DRAW_STEP_SHADOW || step == DRAW_STEP_OUTLINE || step == DRAW_STEP_TEXT) ? _find_color(it, p_base_color) : Color();
Color font_color = (step == DRAW_STEP_SHADOW_OUTLINE || step == DRAW_STEP_SHADOW || step == DRAW_STEP_OUTLINE || step == DRAW_STEP_TEXT) ? _find_color(it, p_base_color) : Color();
int outline_size = (step == DRAW_STEP_OUTLINE) ? _find_outline_size(it, p_outline_size) : 0;
Color font_outline_color = (step == DRAW_STEP_OUTLINE) ? _find_outline_color(it, p_outline_color) : Color();
Color font_shadow_color = p_font_shadow_color;
bool txt_visible = false;
if (step == DRAW_STEP_OUTLINE) {
txt_visible = (font_outline_color.a != 0 && outline_size > 0);
} else if (step == DRAW_STEP_SHADOW) {
txt_visible = (font_shadow_color.a != 0);
if (step == DRAW_STEP_OUTLINE && (outline_size <= 0 || font_outline_color.a == 0)) {
continue;
} else if (step == DRAW_STEP_SHADOW_OUTLINE && (font_shadow_color.a == 0 || p_shadow_outline_size <= 0)) {
continue;
} else if (step == DRAW_STEP_SHADOW && (font_shadow_color.a == 0)) {
continue;
} else if (step == DRAW_STEP_TEXT) {
txt_visible = (font_color.a != 0);
bool has_ul = _find_underline(it);
Expand Down Expand Up @@ -1146,7 +1148,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
draw_line(st_start + Vector2(0, y_off), p_ofs + Vector2(off_step.x, off_step.y + y_off), st_color, underline_width);
}
}
if (step == DRAW_STEP_SHADOW || step == DRAW_STEP_OUTLINE || step == DRAW_STEP_TEXT) {
if (step == DRAW_STEP_SHADOW_OUTLINE || step == DRAW_STEP_SHADOW || step == DRAW_STEP_OUTLINE || step == DRAW_STEP_TEXT) {
ItemFade *fade = nullptr;
Item *fade_item = it;
while (fade_item) {
Expand Down Expand Up @@ -1209,7 +1211,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
charfx->range = Vector2i(l.char_offset + glyphs[i].start, l.char_offset + glyphs[i].end);
charfx->relative_index = l.char_offset + glyphs[i].start - item_fx->char_ofs;
charfx->visibility = txt_visible;
charfx->outline = (step == DRAW_STEP_SHADOW) || (step == DRAW_STEP_OUTLINE);
charfx->outline = (step == DRAW_STEP_SHADOW_OUTLINE) || (step == DRAW_STEP_SHADOW) || (step == DRAW_STEP_OUTLINE);
charfx->font = frid;
charfx->glyph_index = gl;
charfx->glyph_flags = gl_fl;
Expand Down Expand Up @@ -1284,7 +1286,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
char_reverse_xform.set_origin(-char_off);
Transform2D char_final_xform = char_xform * char_reverse_xform;
draw_set_transform_matrix(char_final_xform);
} else if (step == DRAW_STEP_SHADOW) {
} else if (step == DRAW_STEP_SHADOW_OUTLINE || step == DRAW_STEP_SHADOW) {
font_color = font_shadow_color * Color(1, 1, 1, font_color.a);

char_reverse_xform.set_origin(-char_off - p_shadow_ofs);
Expand All @@ -1311,11 +1313,10 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
} else if (((glyphs[i].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) && ((glyphs[i].flags & TextServer::GRAPHEME_IS_EMBEDDED_OBJECT) != TextServer::GRAPHEME_IS_EMBEDDED_OBJECT)) {
TS->draw_hex_code_box(ci, glyphs[i].font_size, fx_offset + char_off, gl, font_color);
}
} else if (step == DRAW_STEP_SHADOW_OUTLINE && frid != RID()) {
TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, p_shadow_outline_size, fx_offset + char_off + p_shadow_ofs, gl, font_color);
} else if (step == DRAW_STEP_SHADOW && frid != RID()) {
TS->font_draw_glyph(frid, ci, glyphs[i].font_size, fx_offset + char_off + p_shadow_ofs, gl, font_color);
if (p_shadow_outline_size > 0) {
TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, p_shadow_outline_size, fx_offset + char_off + p_shadow_ofs, gl, font_color);
}
} else if (step == DRAW_STEP_OUTLINE && frid != RID() && outline_size > 0) {
TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, outline_size, fx_offset + char_off, gl, font_color);
}
Expand Down
1 change: 1 addition & 0 deletions scene/gui/rich_text_label.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class RichTextLabel : public Control {

enum RTLDrawStep {
DRAW_STEP_BACKGROUND,
DRAW_STEP_SHADOW_OUTLINE,
DRAW_STEP_SHADOW,
DRAW_STEP_OUTLINE,
DRAW_STEP_TEXT,
Expand Down

0 comments on commit 23b98d3

Please sign in to comment.