summaryrefslogtreecommitdiffstats
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/3d/label_3d.cpp36
-rw-r--r--scene/3d/label_3d.h4
-rw-r--r--scene/gui/label.cpp62
-rw-r--r--scene/gui/label.h4
-rw-r--r--scene/gui/rich_text_label.cpp46
-rw-r--r--scene/gui/rich_text_label.h5
-rw-r--r--scene/main/canvas_item.cpp8
-rw-r--r--scene/resources/font.cpp12
-rw-r--r--scene/resources/primitive_meshes.cpp36
-rw-r--r--scene/resources/primitive_meshes.h4
-rw-r--r--scene/resources/text_paragraph.cpp38
-rw-r--r--scene/resources/text_paragraph.h2
12 files changed, 227 insertions, 30 deletions
diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp
index 5fc36abb76..198fb70ad7 100644
--- a/scene/3d/label_3d.cpp
+++ b/scene/3d/label_3d.cpp
@@ -88,6 +88,9 @@ void Label3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_autowrap_mode", "autowrap_mode"), &Label3D::set_autowrap_mode);
ClassDB::bind_method(D_METHOD("get_autowrap_mode"), &Label3D::get_autowrap_mode);
+ ClassDB::bind_method(D_METHOD("set_justification_flags", "justification_flags"), &Label3D::set_justification_flags);
+ ClassDB::bind_method(D_METHOD("get_justification_flags"), &Label3D::get_justification_flags);
+
ClassDB::bind_method(D_METHOD("set_width", "width"), &Label3D::set_width);
ClassDB::bind_method(D_METHOD("get_width"), &Label3D::get_width);
@@ -157,6 +160,7 @@ void Label3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing", PROPERTY_HINT_NONE, "suffix:px"), "set_line_spacing", "get_line_spacing");
ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "justification_flags", PROPERTY_HINT_FLAGS, "Kashida Justification:1,Word Justification:2,Justify Only After Last Tab:8,Skip Last Line:32,Skip Last Line With Visible Characters:64,Do Not Skip Single Line:128"), "set_justification_flags", "get_justification_flags");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width", PROPERTY_HINT_NONE, "suffix:px"), "set_width", "get_width");
ADD_GROUP("BiDi", "");
@@ -533,8 +537,24 @@ void Label3D::_shape() {
}
if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) {
- for (int i = 0; i < lines_rid.size() - 1; i++) {
- TS->shaped_text_fit_to_width(lines_rid[i], (width > 0) ? width : max_line_w, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA);
+ int jst_to_line = lines_rid.size();
+ if (lines_rid.size() == 1 && jst_flags.has_flag(TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE)) {
+ jst_to_line = lines_rid.size();
+ } else {
+ if (jst_flags.has_flag(TextServer::JUSTIFICATION_SKIP_LAST_LINE)) {
+ jst_to_line = lines_rid.size() - 1;
+ }
+ if (jst_flags.has_flag(TextServer::JUSTIFICATION_SKIP_LAST_LINE_WITH_VISIBLE_CHARS)) {
+ for (int i = lines_rid.size() - 1; i >= 0; i--) {
+ if (TS->shaped_text_has_visible_chars(lines_rid[i])) {
+ jst_to_line = i;
+ break;
+ }
+ }
+ }
+ }
+ for (int i = 0; i < jst_to_line; i++) {
+ TS->shaped_text_fit_to_width(lines_rid[i], (width > 0) ? width : max_line_w, jst_flags);
}
}
dirty_lines = false;
@@ -871,6 +891,18 @@ TextServer::AutowrapMode Label3D::get_autowrap_mode() const {
return autowrap_mode;
}
+void Label3D::set_justification_flags(BitField<TextServer::JustificationFlag> p_flags) {
+ if (jst_flags != p_flags) {
+ jst_flags = p_flags;
+ dirty_lines = true;
+ _queue_update();
+ }
+}
+
+BitField<TextServer::JustificationFlag> Label3D::get_justification_flags() const {
+ return jst_flags;
+}
+
void Label3D::set_width(float p_width) {
if (width != p_width) {
width = p_width;
diff --git a/scene/3d/label_3d.h b/scene/3d/label_3d.h
index 912f485354..332eaac18d 100644
--- a/scene/3d/label_3d.h
+++ b/scene/3d/label_3d.h
@@ -112,6 +112,7 @@ private:
bool uppercase = false;
TextServer::AutowrapMode autowrap_mode = TextServer::AUTOWRAP_OFF;
+ BitField<TextServer::JustificationFlag> jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE;
float width = 500.0;
int font_size = 32;
@@ -215,6 +216,9 @@ public:
void set_autowrap_mode(TextServer::AutowrapMode p_mode);
TextServer::AutowrapMode get_autowrap_mode() const;
+ void set_justification_flags(BitField<TextServer::JustificationFlag> p_flags);
+ BitField<TextServer::JustificationFlag> get_justification_flags() const;
+
void set_width(float p_width);
float get_width() const;
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index 59f7511894..a9f704e904 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -55,6 +55,20 @@ TextServer::AutowrapMode Label::get_autowrap_mode() const {
return autowrap_mode;
}
+void Label::set_justification_flags(BitField<TextServer::JustificationFlag> p_flags) {
+ if (jst_flags == p_flags) {
+ return;
+ }
+
+ jst_flags = p_flags;
+ lines_dirty = true;
+ queue_redraw();
+}
+
+BitField<TextServer::JustificationFlag> Label::get_justification_flags() const {
+ return jst_flags;
+}
+
void Label::set_uppercase(bool p_uppercase) {
if (uppercase == p_uppercase) {
return;
@@ -198,11 +212,27 @@ void Label::_shape() {
overrun_flags.set_flag(TextServer::OVERRUN_ENFORCE_ELLIPSIS);
}
if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) {
+ int jst_to_line = visible_lines;
+ if (lines_rid.size() == 1 && jst_flags.has_flag(TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE)) {
+ jst_to_line = lines_rid.size();
+ } else {
+ if (jst_flags.has_flag(TextServer::JUSTIFICATION_SKIP_LAST_LINE)) {
+ jst_to_line = visible_lines - 1;
+ }
+ if (jst_flags.has_flag(TextServer::JUSTIFICATION_SKIP_LAST_LINE_WITH_VISIBLE_CHARS)) {
+ for (int i = visible_lines - 1; i >= 0; i--) {
+ if (TS->shaped_text_has_visible_chars(lines_rid[i])) {
+ jst_to_line = i;
+ break;
+ }
+ }
+ }
+ }
for (int i = 0; i < lines_rid.size(); i++) {
- if (i < visible_lines - 1 || lines_rid.size() == 1) {
- TS->shaped_text_fit_to_width(lines_rid[i], width);
+ if (i < jst_to_line) {
+ TS->shaped_text_fit_to_width(lines_rid[i], width, jst_flags);
} else if (i == (visible_lines - 1)) {
- TS->shaped_text_overrun_trim_to_width(lines_rid[visible_lines - 1], width, overrun_flags);
+ TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags);
}
}
} else if (lines_hidden) {
@@ -210,12 +240,28 @@ void Label::_shape() {
}
} else {
// Autowrap disabled.
+ int jst_to_line = lines_rid.size();
+ if (lines_rid.size() == 1 && jst_flags.has_flag(TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE)) {
+ jst_to_line = lines_rid.size();
+ } else {
+ if (jst_flags.has_flag(TextServer::JUSTIFICATION_SKIP_LAST_LINE)) {
+ jst_to_line = lines_rid.size() - 1;
+ }
+ if (jst_flags.has_flag(TextServer::JUSTIFICATION_SKIP_LAST_LINE_WITH_VISIBLE_CHARS)) {
+ for (int i = lines_rid.size() - 1; i >= 0; i--) {
+ if (TS->shaped_text_has_visible_chars(lines_rid[i])) {
+ jst_to_line = i;
+ break;
+ }
+ }
+ }
+ }
for (int i = 0; i < lines_rid.size(); i++) {
- if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) {
- TS->shaped_text_fit_to_width(lines_rid[i], width);
+ if (i < jst_to_line && horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) {
+ TS->shaped_text_fit_to_width(lines_rid[i], width, jst_flags);
overrun_flags.set_flag(TextServer::OVERRUN_JUSTIFICATION_AWARE);
TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags);
- TS->shaped_text_fit_to_width(lines_rid[i], width, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS);
+ TS->shaped_text_fit_to_width(lines_rid[i], width, jst_flags | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS);
} else {
TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags);
}
@@ -936,6 +982,8 @@ void Label::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_language"), &Label::get_language);
ClassDB::bind_method(D_METHOD("set_autowrap_mode", "autowrap_mode"), &Label::set_autowrap_mode);
ClassDB::bind_method(D_METHOD("get_autowrap_mode"), &Label::get_autowrap_mode);
+ ClassDB::bind_method(D_METHOD("set_justification_flags", "justification_flags"), &Label::set_justification_flags);
+ ClassDB::bind_method(D_METHOD("get_justification_flags"), &Label::get_justification_flags);
ClassDB::bind_method(D_METHOD("set_clip_text", "enable"), &Label::set_clip_text);
ClassDB::bind_method(D_METHOD("is_clipping_text"), &Label::is_clipping_text);
ClassDB::bind_method(D_METHOD("set_text_overrun_behavior", "overrun_behavior"), &Label::set_text_overrun_behavior);
@@ -966,6 +1014,8 @@ void Label::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment");
ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_alignment", PROPERTY_HINT_ENUM, "Top,Center,Bottom,Fill"), "set_vertical_alignment", "get_vertical_alignment");
ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "justification_flags", PROPERTY_HINT_FLAGS, "Kashida Justification:1,Word Justification:2,Justify Only After Last Tab:8,Skip Last Line:32,Skip Last Line With Visible Characters:64,Do Not Skip Single Line:128"), "set_justification_flags", "get_justification_flags");
+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "is_clipping_text");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_overrun_behavior", PROPERTY_HINT_ENUM, "Trim Nothing,Trim Characters,Trim Words,Ellipsis,Word Ellipsis"), "set_text_overrun_behavior", "get_text_overrun_behavior");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase");
diff --git a/scene/gui/label.h b/scene/gui/label.h
index 2350525236..5102750bc3 100644
--- a/scene/gui/label.h
+++ b/scene/gui/label.h
@@ -43,6 +43,7 @@ private:
String text;
String xl_text;
TextServer::AutowrapMode autowrap_mode = TextServer::AUTOWRAP_OFF;
+ BitField<TextServer::JustificationFlag> jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE;
bool clip = false;
TextServer::OverrunBehavior overrun_behavior = TextServer::OVERRUN_NO_TRIMMING;
Size2 minsize;
@@ -122,6 +123,9 @@ public:
void set_autowrap_mode(TextServer::AutowrapMode p_mode);
TextServer::AutowrapMode get_autowrap_mode() const;
+ void set_justification_flags(BitField<TextServer::JustificationFlag> p_flags);
+ BitField<TextServer::JustificationFlag> get_justification_flags() const;
+
void set_uppercase(bool p_uppercase);
bool is_uppercase() const;
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 43c68a8eca..185db1b972 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -471,7 +471,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
// Clear cache.
l.text_buf->clear();
l.text_buf->set_break_flags(autowrap_flags);
- l.text_buf->set_justification_flags(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_TRIM_EDGE_SPACES);
+ l.text_buf->set_justification_flags(_find_jst_flags(l.from));
l.char_offset = *r_char_offset;
l.char_count = 0;
@@ -2453,6 +2453,21 @@ int RichTextLabel::_find_margin(Item *p_item, const Ref<Font> &p_base_font, int
return margin;
}
+BitField<TextServer::JustificationFlag> RichTextLabel::_find_jst_flags(Item *p_item) {
+ Item *item = p_item;
+
+ while (item) {
+ if (item->type == ITEM_PARAGRAPH) {
+ ItemParagraph *p = static_cast<ItemParagraph *>(item);
+ return p->jst_flags;
+ }
+
+ item = item->parent;
+ }
+
+ return default_jst_flags;
+}
+
HorizontalAlignment RichTextLabel::_find_alignment(Item *p_item) {
Item *item = p_item;
@@ -3297,7 +3312,7 @@ void RichTextLabel::push_strikethrough() {
_add_item(item, true);
}
-void RichTextLabel::push_paragraph(HorizontalAlignment p_alignment, Control::TextDirection p_direction, const String &p_language, TextServer::StructuredTextParser p_st_parser) {
+void RichTextLabel::push_paragraph(HorizontalAlignment p_alignment, Control::TextDirection p_direction, const String &p_language, TextServer::StructuredTextParser p_st_parser, BitField<TextServer::JustificationFlag> p_jst_flags) {
_stop_thread();
MutexLock data_lock(data_mutex);
@@ -3308,6 +3323,7 @@ void RichTextLabel::push_paragraph(HorizontalAlignment p_alignment, Control::Tex
item->direction = p_direction;
item->language = p_language;
item->st_parser = p_st_parser;
+ item->jst_flags = p_jst_flags;
_add_item(item, true, true);
}
@@ -4079,10 +4095,30 @@ void RichTextLabel::append_text(const String &p_bbcode) {
Control::TextDirection dir = Control::TEXT_DIRECTION_INHERITED;
String lang;
TextServer::StructuredTextParser st_parser_type = TextServer::STRUCTURED_TEXT_DEFAULT;
+ BitField<TextServer::JustificationFlag> jst_flags = default_jst_flags;
for (int i = 0; i < subtag.size(); i++) {
Vector<String> subtag_a = subtag[i].split("=");
if (subtag_a.size() == 2) {
- if (subtag_a[0] == "align") {
+ if (subtag_a[0] == "justification_flags" || subtag_a[0] == "jst") {
+ Vector<String> subtag_b = subtag_a[1].split(",");
+ for (const String &E : subtag_b) {
+ if (E == "kashida" || E == "k") {
+ jst_flags.set_flag(TextServer::JUSTIFICATION_KASHIDA);
+ } else if (E == "word" || E == "w") {
+ jst_flags.set_flag(TextServer::JUSTIFICATION_WORD_BOUND);
+ } else if (E == "trim" || E == "tr") {
+ jst_flags.set_flag(TextServer::JUSTIFICATION_TRIM_EDGE_SPACES);
+ } else if (E == "after_last_tab" || E == "lt") {
+ jst_flags.set_flag(TextServer::JUSTIFICATION_AFTER_LAST_TAB);
+ } else if (E == "skip_last" || E == "sl") {
+ jst_flags.set_flag(TextServer::JUSTIFICATION_SKIP_LAST_LINE);
+ } else if (E == "skip_last_with_chars" || E == "sv") {
+ jst_flags.set_flag(TextServer::JUSTIFICATION_SKIP_LAST_LINE_WITH_VISIBLE_CHARS);
+ } else if (E == "do_not_skip_singe" || E == "ns") {
+ jst_flags.set_flag(TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE);
+ }
+ }
+ } else if (subtag_a[0] == "align") {
if (subtag_a[1] == "l" || subtag_a[1] == "left") {
alignment = HORIZONTAL_ALIGNMENT_LEFT;
} else if (subtag_a[1] == "c" || subtag_a[1] == "center") {
@@ -4121,7 +4157,7 @@ void RichTextLabel::append_text(const String &p_bbcode) {
}
}
}
- push_paragraph(alignment, dir, lang, st_parser_type);
+ push_paragraph(alignment, dir, lang, st_parser_type, jst_flags);
pos = brk_end + 1;
tag_stack.push_front("p");
} else if (tag == "url") {
@@ -5370,7 +5406,7 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("push_color", "color"), &RichTextLabel::push_color);
ClassDB::bind_method(D_METHOD("push_outline_size", "outline_size"), &RichTextLabel::push_outline_size);
ClassDB::bind_method(D_METHOD("push_outline_color", "color"), &RichTextLabel::push_outline_color);
- ClassDB::bind_method(D_METHOD("push_paragraph", "alignment", "base_direction", "language", "st_parser"), &RichTextLabel::push_paragraph, DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(""), DEFVAL(TextServer::STRUCTURED_TEXT_DEFAULT));
+ ClassDB::bind_method(D_METHOD("push_paragraph", "alignment", "base_direction", "language", "st_parser", "justification_flags"), &RichTextLabel::push_paragraph, DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(""), DEFVAL(TextServer::STRUCTURED_TEXT_DEFAULT), DEFVAL(TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE));
ClassDB::bind_method(D_METHOD("push_indent", "level"), &RichTextLabel::push_indent);
ClassDB::bind_method(D_METHOD("push_list", "level", "type", "capitalize", "bullet"), &RichTextLabel::push_list, DEFVAL(String::utf8("•")));
ClassDB::bind_method(D_METHOD("push_meta", "data"), &RichTextLabel::push_meta);
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 567528652c..3e3413d47a 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -240,6 +240,7 @@ private:
String language;
Control::TextDirection direction = Control::TEXT_DIRECTION_AUTO;
TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
+ BitField<TextServer::JustificationFlag> jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE;
ItemParagraph() { type = ITEM_PARAGRAPH; }
};
@@ -405,6 +406,7 @@ private:
bool use_selected_font_color = false;
HorizontalAlignment default_alignment = HORIZONTAL_ALIGNMENT_LEFT;
+ BitField<TextServer::JustificationFlag> default_jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE;
ItemMeta *meta_hovering = nullptr;
Variant current_meta;
@@ -492,6 +494,7 @@ private:
int _find_list(Item *p_item, Vector<int> &r_index, Vector<ItemList *> &r_list);
int _find_margin(Item *p_item, const Ref<Font> &p_base_font, int p_base_font_size);
HorizontalAlignment _find_alignment(Item *p_item);
+ BitField<TextServer::JustificationFlag> _find_jst_flags(Item *p_item);
TextServer::Direction _find_direction(Item *p_item);
TextServer::StructuredTextParser _find_stt(Item *p_item);
String _find_language(Item *p_item);
@@ -593,7 +596,7 @@ public:
void push_outline_color(const Color &p_color);
void push_underline();
void push_strikethrough();
- void push_paragraph(HorizontalAlignment p_alignment, Control::TextDirection p_direction = Control::TEXT_DIRECTION_INHERITED, const String &p_language = "", TextServer::StructuredTextParser p_st_parser = TextServer::STRUCTURED_TEXT_DEFAULT);
+ void push_paragraph(HorizontalAlignment p_alignment, Control::TextDirection p_direction = Control::TEXT_DIRECTION_INHERITED, const String &p_language = "", TextServer::StructuredTextParser p_st_parser = TextServer::STRUCTURED_TEXT_DEFAULT, BitField<TextServer::JustificationFlag> p_jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE);
void push_indent(int p_level);
void push_list(int p_level, ListType p_list, bool p_capitalize, const String &p_bullet = String::utf8("•"));
void push_meta(const Variant &p_meta);
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index cb115a6d94..afadd96d9b 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -1031,10 +1031,10 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture"), &CanvasItem::draw_primitive, DEFVAL(Ref<Texture2D>()));
ClassDB::bind_method(D_METHOD("draw_polygon", "points", "colors", "uvs", "texture"), &CanvasItem::draw_polygon, DEFVAL(PackedVector2Array()), DEFVAL(Ref<Texture2D>()));
ClassDB::bind_method(D_METHOD("draw_colored_polygon", "points", "color", "uvs", "texture"), &CanvasItem::draw_colored_polygon, DEFVAL(PackedVector2Array()), DEFVAL(Ref<Texture2D>()));
- ClassDB::bind_method(D_METHOD("draw_string", "font", "pos", "text", "alignment", "width", "font_size", "modulate", "jst_flags", "direction", "orientation"), &CanvasItem::draw_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
- ClassDB::bind_method(D_METHOD("draw_multiline_string", "font", "pos", "text", "alignment", "width", "font_size", "max_lines", "modulate", "brk_flags", "jst_flags", "direction", "orientation"), &CanvasItem::draw_multiline_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
- ClassDB::bind_method(D_METHOD("draw_string_outline", "font", "pos", "text", "alignment", "width", "font_size", "size", "modulate", "jst_flags", "direction", "orientation"), &CanvasItem::draw_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
- ClassDB::bind_method(D_METHOD("draw_multiline_string_outline", "font", "pos", "text", "alignment", "width", "font_size", "max_lines", "size", "modulate", "brk_flags", "jst_flags", "direction", "orientation"), &CanvasItem::draw_multiline_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
+ ClassDB::bind_method(D_METHOD("draw_string", "font", "pos", "text", "alignment", "width", "font_size", "modulate", "justification_flags", "direction", "orientation"), &CanvasItem::draw_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
+ ClassDB::bind_method(D_METHOD("draw_multiline_string", "font", "pos", "text", "alignment", "width", "font_size", "max_lines", "modulate", "brk_flags", "justification_flags", "direction", "orientation"), &CanvasItem::draw_multiline_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
+ ClassDB::bind_method(D_METHOD("draw_string_outline", "font", "pos", "text", "alignment", "width", "font_size", "size", "modulate", "justification_flags", "direction", "orientation"), &CanvasItem::draw_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
+ ClassDB::bind_method(D_METHOD("draw_multiline_string_outline", "font", "pos", "text", "alignment", "width", "font_size", "max_lines", "size", "modulate", "brk_flags", "justification_flags", "direction", "orientation"), &CanvasItem::draw_multiline_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
ClassDB::bind_method(D_METHOD("draw_char", "font", "pos", "char", "font_size", "modulate"), &CanvasItem::draw_char, DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0)));
ClassDB::bind_method(D_METHOD("draw_char_outline", "font", "pos", "char", "font_size", "size", "modulate"), &CanvasItem::draw_char_outline, DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)));
ClassDB::bind_method(D_METHOD("draw_mesh", "mesh", "texture", "transform", "modulate"), &CanvasItem::draw_mesh, DEFVAL(Transform2D()), DEFVAL(Color(1, 1, 1, 1)));
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index c4b5834ad5..a9d8fc38a4 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -72,14 +72,14 @@ void Font::_bind_methods() {
// Drawing string.
ClassDB::bind_method(D_METHOD("set_cache_capacity", "single_line", "multi_line"), &Font::set_cache_capacity);
- ClassDB::bind_method(D_METHOD("get_string_size", "text", "alignment", "width", "font_size", "jst_flags", "direction", "orientation"), &Font::get_string_size, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
- ClassDB::bind_method(D_METHOD("get_multiline_string_size", "text", "alignment", "width", "font_size", "max_lines", "brk_flags", "jst_flags", "direction", "orientation"), &Font::get_multiline_string_size, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
+ ClassDB::bind_method(D_METHOD("get_string_size", "text", "alignment", "width", "font_size", "justification_flags", "direction", "orientation"), &Font::get_string_size, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
+ ClassDB::bind_method(D_METHOD("get_multiline_string_size", "text", "alignment", "width", "font_size", "max_lines", "brk_flags", "justification_flags", "direction", "orientation"), &Font::get_multiline_string_size, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
- ClassDB::bind_method(D_METHOD("draw_string", "canvas_item", "pos", "text", "alignment", "width", "font_size", "modulate", "jst_flags", "direction", "orientation"), &Font::draw_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
- ClassDB::bind_method(D_METHOD("draw_multiline_string", "canvas_item", "pos", "text", "alignment", "width", "font_size", "max_lines", "modulate", "brk_flags", "jst_flags", "direction", "orientation"), &Font::draw_multiline_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
+ ClassDB::bind_method(D_METHOD("draw_string", "canvas_item", "pos", "text", "alignment", "width", "font_size", "modulate", "justification_flags", "direction", "orientation"), &Font::draw_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
+ ClassDB::bind_method(D_METHOD("draw_multiline_string", "canvas_item", "pos", "text", "alignment", "width", "font_size", "max_lines", "modulate", "brk_flags", "justification_flags", "direction", "orientation"), &Font::draw_multiline_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
- ClassDB::bind_method(D_METHOD("draw_string_outline", "canvas_item", "pos", "text", "alignment", "width", "font_size", "size", "modulate", "jst_flags", "direction", "orientation"), &Font::draw_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
- ClassDB::bind_method(D_METHOD("draw_multiline_string_outline", "canvas_item", "pos", "text", "alignment", "width", "font_size", "max_lines", "size", "modulate", "brk_flags", "jst_flags", "direction", "orientation"), &Font::draw_multiline_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
+ ClassDB::bind_method(D_METHOD("draw_string_outline", "canvas_item", "pos", "text", "alignment", "width", "font_size", "size", "modulate", "justification_flags", "direction", "orientation"), &Font::draw_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
+ ClassDB::bind_method(D_METHOD("draw_multiline_string_outline", "canvas_item", "pos", "text", "alignment", "width", "font_size", "max_lines", "size", "modulate", "brk_flags", "justification_flags", "direction", "orientation"), &Font::draw_multiline_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
// Drawing char.
ClassDB::bind_method(D_METHOD("get_char_size", "char", "font_size"), &Font::get_char_size);
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index 8ed68626a8..6a4f7d082e 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -2967,8 +2967,24 @@ void TextMesh::_create_mesh_array(Array &p_arr) const {
}
if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) {
- for (int i = 0; i < lines_rid.size() - 1; i++) {
- TS->shaped_text_fit_to_width(lines_rid[i], (width > 0) ? width : max_line_w, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA);
+ int jst_to_line = lines_rid.size();
+ if (lines_rid.size() == 1 && jst_flags.has_flag(TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE)) {
+ jst_to_line = lines_rid.size();
+ } else {
+ if (jst_flags.has_flag(TextServer::JUSTIFICATION_SKIP_LAST_LINE)) {
+ jst_to_line = lines_rid.size() - 1;
+ }
+ if (jst_flags.has_flag(TextServer::JUSTIFICATION_SKIP_LAST_LINE_WITH_VISIBLE_CHARS)) {
+ for (int i = lines_rid.size() - 1; i >= 0; i--) {
+ if (TS->shaped_text_has_visible_chars(lines_rid[i])) {
+ jst_to_line = i;
+ break;
+ }
+ }
+ }
+ }
+ for (int i = 0; i < jst_to_line; i++) {
+ TS->shaped_text_fit_to_width(lines_rid[i], (width > 0) ? width : max_line_w, jst_flags);
}
}
dirty_lines = false;
@@ -3293,6 +3309,9 @@ void TextMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_autowrap_mode", "autowrap_mode"), &TextMesh::set_autowrap_mode);
ClassDB::bind_method(D_METHOD("get_autowrap_mode"), &TextMesh::get_autowrap_mode);
+ ClassDB::bind_method(D_METHOD("set_justification_flags", "justification_flags"), &TextMesh::set_justification_flags);
+ ClassDB::bind_method(D_METHOD("get_justification_flags"), &TextMesh::get_justification_flags);
+
ClassDB::bind_method(D_METHOD("set_depth", "depth"), &TextMesh::set_depth);
ClassDB::bind_method(D_METHOD("get_depth"), &TextMesh::get_depth);
@@ -3335,6 +3354,7 @@ void TextMesh::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing", PROPERTY_HINT_NONE, "suffix:px"), "set_line_spacing", "get_line_spacing");
ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "justification_flags", PROPERTY_HINT_FLAGS, "Kashida Justification:1,Word Justification:2,Justify Only After Last Tab:8,Skip Last Line:32,Skip Last Line With Visible Characters:64,Do Not Skip Single Line:128"), "set_justification_flags", "get_justification_flags");
ADD_GROUP("Mesh", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001,suffix:m"), "set_pixel_size", "get_pixel_size");
@@ -3512,6 +3532,18 @@ TextServer::AutowrapMode TextMesh::get_autowrap_mode() const {
return autowrap_mode;
}
+void TextMesh::set_justification_flags(BitField<TextServer::JustificationFlag> p_flags) {
+ if (jst_flags != p_flags) {
+ jst_flags = p_flags;
+ dirty_lines = true;
+ _request_update();
+ }
+}
+
+BitField<TextServer::JustificationFlag> TextMesh::get_justification_flags() const {
+ return jst_flags;
+}
+
void TextMesh::set_depth(real_t p_depth) {
if (depth != p_depth) {
depth = MAX(p_depth, 0.0);
diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h
index e62f26b17c..5b788b726e 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -591,6 +591,7 @@ private:
Ref<Font> font_override;
TextServer::AutowrapMode autowrap_mode = TextServer::AUTOWRAP_OFF;
+ BitField<TextServer::JustificationFlag> jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE;
float width = 500.0;
float line_spacing = 0.f;
Point2 lbl_offset;
@@ -649,6 +650,9 @@ public:
void set_autowrap_mode(TextServer::AutowrapMode p_mode);
TextServer::AutowrapMode get_autowrap_mode() const;
+ void set_justification_flags(BitField<TextServer::JustificationFlag> p_flags);
+ BitField<TextServer::JustificationFlag> get_justification_flags() const;
+
void set_text_direction(TextServer::Direction p_text_direction);
TextServer::Direction get_text_direction() const;
diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp
index 191b71f301..33f11371fe 100644
--- a/scene/resources/text_paragraph.cpp
+++ b/scene/resources/text_paragraph.cpp
@@ -82,7 +82,7 @@ void TextParagraph::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_justification_flags", "flags"), &TextParagraph::set_justification_flags);
ClassDB::bind_method(D_METHOD("get_justification_flags"), &TextParagraph::get_justification_flags);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "justification_flags", PROPERTY_HINT_FLAGS, "Kashida Justification,Word Justification,Trim Edge Spaces After Justification,Justify Only After Last Tab,Constrain Ellipsis"), "set_justification_flags", "get_justification_flags");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "justification_flags", PROPERTY_HINT_FLAGS, "Kashida Justification:1,Word Justification:2,Trim Edge Spaces After Justification:4,Justify Only After Last Tab:8,Constrain Ellipsis:16,Skip Last Line:32,Skip Last Line With Visible Characters:64,Do Not Skip Single Line:128"), "set_justification_flags", "get_justification_flags");
ClassDB::bind_method(D_METHOD("set_text_overrun_behavior", "overrun_behavior"), &TextParagraph::set_text_overrun_behavior);
ClassDB::bind_method(D_METHOD("get_text_overrun_behavior"), &TextParagraph::get_text_overrun_behavior);
@@ -232,9 +232,25 @@ void TextParagraph::_shape_lines() {
overrun_flags.set_flag(TextServer::OVERRUN_ENFORCE_ELLIPSIS);
}
if (alignment == HORIZONTAL_ALIGNMENT_FILL) {
+ int jst_to_line = visible_lines;
+ if (lines_rid.size() == 1 && jst_flags.has_flag(TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE)) {
+ jst_to_line = lines_rid.size();
+ } else {
+ if (jst_flags.has_flag(TextServer::JUSTIFICATION_SKIP_LAST_LINE)) {
+ jst_to_line = visible_lines - 1;
+ }
+ if (jst_flags.has_flag(TextServer::JUSTIFICATION_SKIP_LAST_LINE_WITH_VISIBLE_CHARS)) {
+ for (int i = visible_lines - 1; i >= 0; i--) {
+ if (TS->shaped_text_has_visible_chars(lines_rid[i])) {
+ jst_to_line = i;
+ break;
+ }
+ }
+ }
+ }
for (int i = 0; i < (int)lines_rid.size(); i++) {
float line_w = (i <= dropcap_lines) ? (width - h_offset) : width;
- if (i < visible_lines - 1 || (int)lines_rid.size() == 1) {
+ if (i < jst_to_line) {
TS->shaped_text_fit_to_width(lines_rid[i], line_w, jst_flags);
} else if (i == (visible_lines - 1)) {
TS->shaped_text_overrun_trim_to_width(lines_rid[visible_lines - 1], line_w, overrun_flags);
@@ -245,9 +261,25 @@ void TextParagraph::_shape_lines() {
}
} else {
// Autowrap disabled.
+ int jst_to_line = lines_rid.size();
+ if (lines_rid.size() == 1 && jst_flags.has_flag(TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE)) {
+ jst_to_line = lines_rid.size();
+ } else {
+ if (jst_flags.has_flag(TextServer::JUSTIFICATION_SKIP_LAST_LINE)) {
+ jst_to_line = lines_rid.size() - 1;
+ }
+ if (jst_flags.has_flag(TextServer::JUSTIFICATION_SKIP_LAST_LINE_WITH_VISIBLE_CHARS)) {
+ for (int i = lines_rid.size() - 1; i >= 0; i--) {
+ if (TS->shaped_text_has_visible_chars(lines_rid[i])) {
+ jst_to_line = i;
+ break;
+ }
+ }
+ }
+ }
for (int i = 0; i < (int)lines_rid.size(); i++) {
float line_w = (i <= dropcap_lines) ? (width - h_offset) : width;
- if (alignment == HORIZONTAL_ALIGNMENT_FILL) {
+ if (i < jst_to_line && alignment == HORIZONTAL_ALIGNMENT_FILL) {
TS->shaped_text_fit_to_width(lines_rid[i], line_w, jst_flags);
overrun_flags.set_flag(TextServer::OVERRUN_JUSTIFICATION_AWARE);
TS->shaped_text_overrun_trim_to_width(lines_rid[i], line_w, overrun_flags);
diff --git a/scene/resources/text_paragraph.h b/scene/resources/text_paragraph.h
index 5723dabeca..31fc95ac02 100644
--- a/scene/resources/text_paragraph.h
+++ b/scene/resources/text_paragraph.h
@@ -55,7 +55,7 @@ private:
int max_lines_visible = -1;
BitField<TextServer::LineBreakFlag> brk_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND;
- BitField<TextServer::JustificationFlag> jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA;
+ BitField<TextServer::JustificationFlag> jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE;
TextServer::OverrunBehavior overrun_behavior = TextServer::OVERRUN_NO_TRIMMING;
HorizontalAlignment alignment = HORIZONTAL_ALIGNMENT_LEFT;