Implement font shadows for RichTextLabel
This commit is contained in:
parent
23fc8ca223
commit
1c6ea572ca
5 changed files with 65 additions and 19 deletions
|
@ -319,6 +319,14 @@
|
|||
</theme_item>
|
||||
<theme_item name="font_color_selected" type="Color">
|
||||
</theme_item>
|
||||
<theme_item name="font_color_shadow" type="Color">
|
||||
</theme_item>
|
||||
<theme_item name="shadow_as_outline" type="int">
|
||||
</theme_item>
|
||||
<theme_item name="shadow_offset_x" type="int">
|
||||
</theme_item>
|
||||
<theme_item name="shadow_offset_y" type="int">
|
||||
</theme_item>
|
||||
<theme_item name="italics_font" type="Font">
|
||||
</theme_item>
|
||||
<theme_item name="line_separation" type="int">
|
||||
|
|
|
@ -891,6 +891,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
|
|||
|
||||
//RichTextLabel
|
||||
theme->set_color("default_color", "RichTextLabel", font_color);
|
||||
theme->set_color("font_color_shadow", "RichTextLabel", Color(0, 0, 0, 0));
|
||||
theme->set_constant("shadow_offset_x", "RichTextLabel", 1 * EDSCALE);
|
||||
theme->set_constant("shadow_offset_y", "RichTextLabel", 1 * EDSCALE);
|
||||
theme->set_constant("shadow_as_outline", "RichTextLabel", 0 * EDSCALE);
|
||||
theme->set_stylebox("focus", "RichTextLabel", make_empty_stylebox());
|
||||
theme->set_stylebox("normal", "RichTextLabel", style_tree_bg);
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ Rect2 RichTextLabel::_get_text_rect() {
|
|||
Ref<StyleBox> style = get_stylebox("normal");
|
||||
return Rect2(style->get_offset(), get_size() - style->get_minimum_size());
|
||||
}
|
||||
int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &y, int p_width, int p_line, ProcessMode p_mode, const Ref<Font> &p_base_font, const Color &p_base_color, const Point2i &p_click_pos, Item **r_click_item, int *r_click_char, bool *r_outside, int p_char_count) {
|
||||
int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &y, int p_width, int p_line, ProcessMode p_mode, const Ref<Font> &p_base_font, const Color &p_base_color, const Color &p_font_color_shadow, bool p_shadow_as_outline, const Point2 &shadow_ofs, const Point2i &p_click_pos, Item **r_click_item, int *r_click_char, bool *r_outside, int p_char_count) {
|
||||
|
||||
RID ci;
|
||||
if (r_outside)
|
||||
|
@ -269,10 +269,12 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
|
|||
int descent = font->get_descent();
|
||||
|
||||
Color color;
|
||||
Color font_color_shadow;
|
||||
bool underline = false;
|
||||
|
||||
if (p_mode == PROCESS_DRAW) {
|
||||
color = _find_color(text, p_base_color);
|
||||
font_color_shadow = _find_color(text, p_font_color_shadow);
|
||||
underline = _find_underline(text);
|
||||
if (_find_meta(text, &meta)) {
|
||||
|
||||
|
@ -284,7 +286,6 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
|
|||
}
|
||||
|
||||
rchar = 0;
|
||||
|
||||
while (*c) {
|
||||
|
||||
int end = 0;
|
||||
|
@ -297,7 +298,6 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
|
|||
line_ascent = line < l.ascent_caches.size() ? l.ascent_caches[line] : 1;
|
||||
line_descent = line < l.descent_caches.size() ? l.descent_caches[line] : 1;
|
||||
}
|
||||
|
||||
while (c[end] != 0 && !(end && c[end - 1] == ' ' && c[end] != ' ')) {
|
||||
|
||||
int cw = font->get_char_size(c[end], c[end + 1]).width;
|
||||
|
@ -314,7 +314,6 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
|
|||
|
||||
end++;
|
||||
}
|
||||
|
||||
CHECK_HEIGHT(fh);
|
||||
ENSURE_WIDTH(w);
|
||||
|
||||
|
@ -376,17 +375,31 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
|
|||
if (c[i] == '\t')
|
||||
visible = false;
|
||||
|
||||
if (visible) {
|
||||
if (selected) {
|
||||
|
||||
cw = font->get_char_size(c[i], c[i + 1]).x;
|
||||
draw_rect(Rect2(p_ofs.x + pofs, p_ofs.y + y, cw, lh), selection_bg);
|
||||
if (visible)
|
||||
font->draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - line_descent), c[i], c[i + 1], override_selected_font_color ? selection_fg : color);
|
||||
}
|
||||
|
||||
if (p_font_color_shadow.a > 0) {
|
||||
float x_ofs_shadow = align_ofs + pofs;
|
||||
float y_ofs_shadow = y + lh - line_descent;
|
||||
float move = font->draw_char(ci, Point2(x_ofs_shadow, y_ofs_shadow) + shadow_ofs, c[i], c[i + 1], p_font_color_shadow);
|
||||
|
||||
if (p_shadow_as_outline) {
|
||||
font->draw_char(ci, Point2(x_ofs_shadow, y_ofs_shadow) + Vector2(-shadow_ofs.x, shadow_ofs.y), c[i], c[i + 1], p_font_color_shadow);
|
||||
font->draw_char(ci, Point2(x_ofs_shadow, y_ofs_shadow) + Vector2(shadow_ofs.x, -shadow_ofs.y), c[i], c[i + 1], p_font_color_shadow);
|
||||
font->draw_char(ci, Point2(x_ofs_shadow, y_ofs_shadow) + Vector2(-shadow_ofs.x, -shadow_ofs.y), c[i], c[i + 1], p_font_color_shadow);
|
||||
}
|
||||
x_ofs_shadow += move;
|
||||
}
|
||||
|
||||
if (selected) {
|
||||
font->draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - line_descent), c[i], c[i + 1], override_selected_font_color ? selection_fg : color);
|
||||
} else {
|
||||
if (visible)
|
||||
cw = font->draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - line_descent), c[i], c[i + 1], color);
|
||||
}
|
||||
}
|
||||
|
||||
p_char_count++;
|
||||
if (c[i] == '\t') {
|
||||
|
@ -464,6 +477,9 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
|
|||
int vseparation = get_constant("table_vseparation");
|
||||
Color ccolor = _find_color(table, p_base_color);
|
||||
Vector2 draw_ofs = Point2(wofs, y);
|
||||
Color font_color_shadow = get_color("font_color_shadow");
|
||||
bool use_outline = get_constant("shadow_as_outline");
|
||||
Point2 shadow_ofs(get_constant("shadow_offset_x"), get_constant("shadow_offset_y"));
|
||||
|
||||
if (p_mode == PROCESS_CACHE) {
|
||||
|
||||
|
@ -487,7 +503,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
|
|||
|
||||
for (int i = 0; i < frame->lines.size(); i++) {
|
||||
|
||||
_process_line(frame, Point2(), ly, available_width, i, PROCESS_CACHE, cfont, Color());
|
||||
_process_line(frame, Point2(), ly, available_width, i, PROCESS_CACHE, cfont, Color(), font_color_shadow, use_outline, shadow_ofs);
|
||||
table->columns[column].min_width = MAX(table->columns[column].min_width, frame->lines[i].minimum_width);
|
||||
table->columns[column].max_width = MAX(table->columns[column].max_width, frame->lines[i].maximum_width);
|
||||
}
|
||||
|
@ -560,7 +576,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
|
|||
for (int i = 0; i < frame->lines.size(); i++) {
|
||||
|
||||
int ly = 0;
|
||||
_process_line(frame, Point2(), ly, table->columns[column].width, i, PROCESS_CACHE, cfont, Color());
|
||||
_process_line(frame, Point2(), ly, table->columns[column].width, i, PROCESS_CACHE, cfont, Color(), font_color_shadow, use_outline, shadow_ofs);
|
||||
frame->lines[i].height_cache = ly; //actual height
|
||||
frame->lines[i].height_accum_cache = ly; //actual height
|
||||
}
|
||||
|
@ -593,9 +609,9 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
|
|||
|
||||
if (visible) {
|
||||
if (p_mode == PROCESS_DRAW) {
|
||||
nonblank_line_count += _process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_DRAW, cfont, ccolor);
|
||||
nonblank_line_count += _process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_DRAW, cfont, ccolor, font_color_shadow, use_outline, shadow_ofs);
|
||||
} else if (p_mode == PROCESS_POINTER) {
|
||||
_process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_POINTER, cfont, ccolor, p_click_pos, r_click_item, r_click_char, r_outside);
|
||||
_process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_POINTER, cfont, ccolor, font_color_shadow, use_outline, shadow_ofs, p_click_pos, r_click_item, r_click_char, r_outside);
|
||||
if (r_click_item && *r_click_item) {
|
||||
RETURN; // exit early
|
||||
}
|
||||
|
@ -767,12 +783,18 @@ void RichTextLabel::_notification(int p_what) {
|
|||
int y = (main->lines[from_line].height_accum_cache - main->lines[from_line].height_cache) - ofs;
|
||||
Ref<Font> base_font = get_font("normal_font");
|
||||
Color base_color = get_color("default_color");
|
||||
Color font_color_shadow = get_color("font_color_shadow");
|
||||
bool use_outline = get_constant("shadow_as_outline");
|
||||
Point2 shadow_ofs(get_constant("shadow_offset_x"), get_constant("shadow_offset_y"));
|
||||
|
||||
float x_ofs = 0;
|
||||
|
||||
visible_line_count = 0;
|
||||
while (y < size.height && from_line < main->lines.size()) {
|
||||
|
||||
visible_line_count += _process_line(main, text_rect.get_position(), y, text_rect.get_size().width - scroll_w, from_line, PROCESS_DRAW, base_font, base_color, Point2i(), NULL, NULL, NULL, total_chars);
|
||||
visible_line_count += _process_line(main, text_rect.get_position(), y, text_rect.get_size().width - scroll_w, from_line, PROCESS_DRAW, base_font, base_color, font_color_shadow, use_outline, shadow_ofs, Point2i(), NULL, NULL, NULL, total_chars);
|
||||
total_chars += main->lines[from_line].char_count;
|
||||
|
||||
from_line++;
|
||||
}
|
||||
}
|
||||
|
@ -787,6 +809,9 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item
|
|||
Size2 size = get_size();
|
||||
Rect2 text_rect = _get_text_rect();
|
||||
int ofs = vscroll->get_value();
|
||||
Color font_color_shadow = get_color("font_color_shadow");
|
||||
bool use_outline = get_constant("shadow_as_outline");
|
||||
Point2 shadow_ofs(get_constant("shadow_offset_x"), get_constant("shadow_offset_y"));
|
||||
|
||||
//todo, change to binary search
|
||||
int from_line = 0;
|
||||
|
@ -807,7 +832,7 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item
|
|||
|
||||
while (y < text_rect.get_size().height && from_line < p_frame->lines.size()) {
|
||||
|
||||
_process_line(p_frame, text_rect.get_position(), y, text_rect.get_size().width - scroll_w, from_line, PROCESS_POINTER, base_font, base_color, p_click, r_click_item, r_click_char, r_outside);
|
||||
_process_line(p_frame, text_rect.get_position(), y, text_rect.get_size().width - scroll_w, from_line, PROCESS_POINTER, base_font, base_color, font_color_shadow, use_outline, shadow_ofs, p_click, r_click_item, r_click_char, r_outside);
|
||||
if (r_click_item && *r_click_item)
|
||||
return;
|
||||
from_line++;
|
||||
|
@ -1182,13 +1207,16 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) {
|
|||
//validate invalid lines
|
||||
Size2 size = get_size();
|
||||
Rect2 text_rect = _get_text_rect();
|
||||
Color font_color_shadow = get_color("font_color_shadow");
|
||||
bool use_outline = get_constant("shadow_as_outline");
|
||||
Point2 shadow_ofs(get_constant("shadow_offset_x"), get_constant("shadow_offset_y"));
|
||||
|
||||
Ref<Font> base_font = get_font("normal_font");
|
||||
|
||||
for (int i = p_frame->first_invalid_line; i < p_frame->lines.size(); i++) {
|
||||
|
||||
int y = 0;
|
||||
_process_line(p_frame, text_rect.get_position(), y, text_rect.get_size().width - scroll_w, i, PROCESS_CACHE, base_font, Color());
|
||||
_process_line(p_frame, text_rect.get_position(), y, text_rect.get_size().width - scroll_w, i, PROCESS_CACHE, base_font, Color(), font_color_shadow, use_outline, shadow_ofs);
|
||||
p_frame->lines[i].height_cache = y;
|
||||
p_frame->lines[i].height_accum_cache = y;
|
||||
|
||||
|
|
|
@ -270,7 +270,7 @@ private:
|
|||
int visible_characters;
|
||||
float percent_visible;
|
||||
|
||||
int _process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &y, int p_width, int p_line, ProcessMode p_mode, const Ref<Font> &p_base_font, const Color &p_base_color, const Point2i &p_click_pos = Point2i(), Item **r_click_item = NULL, int *r_click_char = NULL, bool *r_outside = NULL, int p_char_count = 0);
|
||||
int _process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &y, int p_width, int p_line, ProcessMode p_mode, const Ref<Font> &p_base_font, const Color &p_base_color, const Color &p_font_color_shadow, bool p_shadow_as_outline, const Point2 &shadow_ofs, const Point2i &p_click_pos = Point2i(), Item **r_click_item = NULL, int *r_click_char = NULL, bool *r_outside = NULL, int p_char_count = 0);
|
||||
void _find_click(ItemFrame *p_frame, const Point2i &p_click, Item **r_click_item = NULL, int *r_click_char = NULL, bool *r_outside = NULL);
|
||||
|
||||
Ref<Font> _find_font(Item *p_item);
|
||||
|
|
|
@ -818,6 +818,12 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
|
|||
theme->set_color("font_color_selected", "RichTextLabel", font_color_selection);
|
||||
theme->set_color("selection_color", "RichTextLabel", Color(0.1, 0.1, 1, 0.8));
|
||||
|
||||
theme->set_color("font_color_shadow", "RichTextLabel", Color(0, 0, 0, 0));
|
||||
|
||||
theme->set_constant("shadow_offset_x", "RichTextLabel", 1 * scale);
|
||||
theme->set_constant("shadow_offset_y", "RichTextLabel", 1 * scale);
|
||||
theme->set_constant("shadow_as_outline", "RichTextLabel", 0 * scale);
|
||||
|
||||
theme->set_constant("line_separation", "RichTextLabel", 1 * scale);
|
||||
theme->set_constant("table_hseparation", "RichTextLabel", 3 * scale);
|
||||
theme->set_constant("table_vseparation", "RichTextLabel", 3 * scale);
|
||||
|
|
Loading…
Reference in a new issue