[Text Server] Add support for user defined punctuation list, used for word breaking.

This commit is contained in:
bruvzg 2021-03-06 11:52:16 +02:00
parent 928c002f22
commit daa613333e
13 changed files with 165 additions and 12 deletions

View File

@ -278,6 +278,9 @@
<member name="align" type="int" setter="set_align" getter="get_align" enum="HAlign" default="0"> <member name="align" type="int" setter="set_align" getter="get_align" enum="HAlign" default="0">
Paragraph horizontal alignment. Paragraph horizontal alignment.
</member> </member>
<member name="custom_punctuation" type="String" setter="set_custom_punctuation" getter="get_custom_punctuation" default="&quot;&quot;">
Custom punctuation character list, used for word breaking. If set to empty string, server defaults are used.
</member>
<member name="direction" type="int" setter="set_direction" getter="get_direction" enum="TextServer.Direction" default="0"> <member name="direction" type="int" setter="set_direction" getter="get_direction" enum="TextServer.Direction" default="0">
Text writing direction. Text writing direction.
</member> </member>

View File

@ -911,6 +911,13 @@
Returns shapes of the carets corresponding to the character offset [code]position[/code] in the text. Returned caret shape is 1 pixel wide rectangle. Returns shapes of the carets corresponding to the character offset [code]position[/code] in the text. Returned caret shape is 1 pixel wide rectangle.
</description> </description>
</method> </method>
<method name="shaped_text_get_custom_punctuation" qualifiers="const">
<return type="String" />
<argument index="0" name="shaped" type="RID" />
<description>
Returns custom punctuation character list, used for word breaking. If set to empty string, server defaults are used.
</description>
</method>
<method name="shaped_text_get_descent" qualifiers="const"> <method name="shaped_text_get_descent" qualifiers="const">
<return type="float" /> <return type="float" />
<argument index="0" name="shaped" type="RID" /> <argument index="0" name="shaped" type="RID" />
@ -1161,6 +1168,14 @@
Override ranges should cover full source text without overlaps. BiDi algorithm will be used on each range separately. Override ranges should cover full source text without overlaps. BiDi algorithm will be used on each range separately.
</description> </description>
</method> </method>
<method name="shaped_text_set_custom_punctuation">
<return type="void" />
<argument index="0" name="shaped" type="RID" />
<argument index="1" name="punct" type="String" />
<description>
Sets custom punctuation character list, used for word breaking. If set to empty string, server defaults are used.
</description>
</method>
<method name="shaped_text_set_direction"> <method name="shaped_text_set_direction">
<return type="void" /> <return type="void" />
<argument index="0" name="shaped" type="RID" /> <argument index="0" name="shaped" type="RID" />

View File

@ -918,6 +918,13 @@
Returns shapes of the carets corresponding to the character offset [code]position[/code] in the text. Returned caret shape is 1 pixel wide rectangle. Returns shapes of the carets corresponding to the character offset [code]position[/code] in the text. Returned caret shape is 1 pixel wide rectangle.
</description> </description>
</method> </method>
<method name="_shaped_text_get_custom_punctuation" qualifiers="virtual const">
<return type="String" />
<argument index="0" name="shaped" type="RID" />
<description>
Returns custom punctuation character list, used for word breaking. If set to empty string, server defaults are used.
</description>
</method>
<method name="_shaped_text_get_descent" qualifiers="virtual const"> <method name="_shaped_text_get_descent" qualifiers="virtual const">
<return type="float" /> <return type="float" />
<argument index="0" name="shaped" type="RID" /> <argument index="0" name="shaped" type="RID" />
@ -1170,6 +1177,14 @@
Override ranges should cover full source text without overlaps. BiDi algorithm will be used on each range separately. Override ranges should cover full source text without overlaps. BiDi algorithm will be used on each range separately.
</description> </description>
</method> </method>
<method name="_shaped_text_set_custom_punctuation" qualifiers="virtual">
<return type="void" />
<argument index="0" name="shaped" type="RID" />
<argument index="1" name="punct" type="String" />
<description>
Sets custom punctuation character list, used for word breaking. If set to empty string, server defaults are used.
</description>
</method>
<method name="_shaped_text_set_direction" qualifiers="virtual"> <method name="_shaped_text_set_direction" qualifiers="virtual">
<return type="void" /> <return type="void" />
<argument index="0" name="shaped" type="RID" /> <argument index="0" name="shaped" type="RID" />

View File

@ -2928,6 +2928,27 @@ TextServer::Direction TextServerAdvanced::shaped_text_get_direction(RID p_shaped
return sd->direction; return sd->direction;
} }
void TextServerAdvanced::shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) {
_THREAD_SAFE_METHOD_
ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND(!sd);
if (sd->custom_punct != p_punct) {
if (sd->parent != RID()) {
full_copy(sd);
}
sd->custom_punct = p_punct;
invalidate(sd);
}
}
String TextServerAdvanced::shaped_text_get_custom_punctuation(RID p_shaped) const {
_THREAD_SAFE_METHOD_
const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, String());
return sd->custom_punct;
}
void TextServerAdvanced::shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) { void TextServerAdvanced::shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) {
ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND(!sd); ERR_FAIL_COND(!sd);
@ -3227,6 +3248,7 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng
new_sd->orientation = sd->orientation; new_sd->orientation = sd->orientation;
new_sd->direction = sd->direction; new_sd->direction = sd->direction;
new_sd->custom_punct = sd->custom_punct;
new_sd->para_direction = sd->para_direction; new_sd->para_direction = sd->para_direction;
new_sd->line_breaks_valid = sd->line_breaks_valid; new_sd->line_breaks_valid = sd->line_breaks_valid;
new_sd->justification_ops_valid = sd->justification_ops_valid; new_sd->justification_ops_valid = sd->justification_ops_valid;
@ -3807,6 +3829,9 @@ bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) {
const char32_t *ch = sd->text.ptr(); const char32_t *ch = sd->text.ptr();
Glyph *sd_glyphs = sd->glyphs.ptrw(); Glyph *sd_glyphs = sd->glyphs.ptrw();
int c_punct_size = sd->custom_punct.length();
const char32_t *c_punct = sd->custom_punct.ptr();
for (i = 0; i < sd_size; i++) { for (i = 0; i < sd_size; i++) {
if (sd_glyphs[i].count > 0) { if (sd_glyphs[i].count > 0) {
char32_t c = ch[sd_glyphs[i].start - sd->start]; char32_t c = ch[sd_glyphs[i].start - sd->start];
@ -3819,12 +3844,21 @@ bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) {
if (is_whitespace(c)) { if (is_whitespace(c)) {
sd_glyphs[i].flags |= GRAPHEME_IS_SPACE; sd_glyphs[i].flags |= GRAPHEME_IS_SPACE;
} }
if (c_punct_size == 0) {
if (u_ispunct(c) && c != 0x005F) {
sd_glyphs[i].flags |= GRAPHEME_IS_PUNCTUATION;
}
} else {
for (int j = 0; j < c_punct_size; j++) {
if (c_punct[j] == c) {
sd_glyphs[i].flags |= GRAPHEME_IS_PUNCTUATION;
break;
}
}
}
if (is_underscore(c)) { if (is_underscore(c)) {
sd_glyphs[i].flags |= GRAPHEME_IS_UNDERSCORE; sd_glyphs[i].flags |= GRAPHEME_IS_UNDERSCORE;
} }
if (u_ispunct(c) && c != 0x005F) {
sd_glyphs[i].flags |= GRAPHEME_IS_PUNCTUATION;
}
if (breaks.has(sd->glyphs[i].start)) { if (breaks.has(sd->glyphs[i].start)) {
if (breaks[sd->glyphs[i].start]) { if (breaks[sd->glyphs[i].start]) {
sd_glyphs[i].flags |= GRAPHEME_IS_BREAK_HARD; sd_glyphs[i].flags |= GRAPHEME_IS_BREAK_HARD;

View File

@ -436,6 +436,9 @@ public:
virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override; virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override;
virtual void shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) override;
virtual String shaped_text_get_custom_punctuation(RID p_shaped) const override;
virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override; virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override;
virtual Orientation shaped_text_get_orientation(RID p_shaped) const override; virtual Orientation shaped_text_get_orientation(RID p_shaped) const override;

View File

@ -2031,6 +2031,27 @@ TextServer::Direction TextServerFallback::shaped_text_get_direction(RID p_shaped
return TextServer::DIRECTION_LTR; return TextServer::DIRECTION_LTR;
} }
void TextServerFallback::shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) {
_THREAD_SAFE_METHOD_
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND(!sd);
if (sd->custom_punct != p_punct) {
if (sd->parent != RID()) {
full_copy(sd);
}
sd->custom_punct = p_punct;
invalidate(sd);
}
}
String TextServerFallback::shaped_text_get_custom_punctuation(RID p_shaped) const {
_THREAD_SAFE_METHOD_
const ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, String());
return sd->custom_punct;
}
void TextServerFallback::shaped_text_set_orientation(RID p_shaped, TextServer::Orientation p_orientation) { void TextServerFallback::shaped_text_set_orientation(RID p_shaped, TextServer::Orientation p_orientation) {
ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND(!sd); ERR_FAIL_COND(!sd);
@ -2333,6 +2354,7 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng
new_sd->orientation = sd->orientation; new_sd->orientation = sd->orientation;
new_sd->direction = sd->direction; new_sd->direction = sd->direction;
new_sd->custom_punct = sd->custom_punct;
new_sd->para_direction = sd->para_direction; new_sd->para_direction = sd->para_direction;
new_sd->line_breaks_valid = sd->line_breaks_valid; new_sd->line_breaks_valid = sd->line_breaks_valid;
new_sd->justification_ops_valid = sd->justification_ops_valid; new_sd->justification_ops_valid = sd->justification_ops_valid;
@ -2616,27 +2638,41 @@ bool TextServerFallback::shaped_text_update_breaks(RID p_shaped) {
} }
int sd_size = sd->glyphs.size(); int sd_size = sd->glyphs.size();
Glyph *sd_glyphs = sd->glyphs.ptrw();
int c_punct_size = sd->custom_punct.length();
const char32_t *c_punct = sd->custom_punct.ptr();
for (int i = 0; i < sd_size; i++) { for (int i = 0; i < sd_size; i++) {
if (sd->glyphs[i].count > 0) { if (sd_glyphs[i].count > 0) {
char32_t c = sd->text[sd->glyphs[i].start]; char32_t c = sd->text[sd_glyphs[i].start];
if (is_punct(c)) { if (c_punct_size == 0) {
sd->glyphs.write[i].flags |= GRAPHEME_IS_PUNCTUATION; if (is_punct(c)) {
sd_glyphs[i].flags |= GRAPHEME_IS_PUNCTUATION;
}
} else {
for (int j = 0; j < c_punct_size; j++) {
if (c_punct[j] == c) {
sd_glyphs[i].flags |= GRAPHEME_IS_PUNCTUATION;
break;
}
}
} }
if (is_underscore(c)) { if (is_underscore(c)) {
sd->glyphs.write[i].flags |= GRAPHEME_IS_UNDERSCORE; sd->glyphs.write[i].flags |= GRAPHEME_IS_UNDERSCORE;
} }
if (is_whitespace(c) && !is_linebreak(c)) { if (is_whitespace(c) && !is_linebreak(c)) {
sd->glyphs.write[i].flags |= GRAPHEME_IS_SPACE; sd_glyphs[i].flags |= GRAPHEME_IS_SPACE;
sd->glyphs.write[i].flags |= GRAPHEME_IS_BREAK_SOFT; sd_glyphs[i].flags |= GRAPHEME_IS_BREAK_SOFT;
} }
if (is_linebreak(c)) { if (is_linebreak(c)) {
sd->glyphs.write[i].flags |= GRAPHEME_IS_BREAK_HARD; sd_glyphs[i].flags |= GRAPHEME_IS_BREAK_HARD;
} }
if (c == 0x0009 || c == 0x000b) { if (c == 0x0009 || c == 0x000b) {
sd->glyphs.write[i].flags |= GRAPHEME_IS_TAB; sd_glyphs[i].flags |= GRAPHEME_IS_TAB;
} }
i += (sd->glyphs[i].count - 1); i += (sd_glyphs[i].count - 1);
} }
} }
sd->line_breaks_valid = true; sd->line_breaks_valid = true;

View File

@ -355,6 +355,9 @@ public:
virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override; virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override;
virtual void shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) override;
virtual String shaped_text_get_custom_punctuation(RID p_shaped) const override;
virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override; virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override;
virtual Orientation shaped_text_get_orientation(RID p_shaped) const override; virtual Orientation shaped_text_get_orientation(RID p_shaped) const override;

View File

@ -38,6 +38,11 @@ void TextParagraph::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "direction", PROPERTY_HINT_ENUM, "Auto,Light-to-right,Right-to-left"), "set_direction", "get_direction"); ADD_PROPERTY(PropertyInfo(Variant::INT, "direction", PROPERTY_HINT_ENUM, "Auto,Light-to-right,Right-to-left"), "set_direction", "get_direction");
ClassDB::bind_method(D_METHOD("set_custom_punctuation", "custom_punctuation"), &TextParagraph::set_custom_punctuation);
ClassDB::bind_method(D_METHOD("get_custom_punctuation"), &TextParagraph::get_custom_punctuation);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "custom_punctuation"), "set_custom_punctuation", "get_custom_punctuation");
ClassDB::bind_method(D_METHOD("set_orientation", "orientation"), &TextParagraph::set_orientation); ClassDB::bind_method(D_METHOD("set_orientation", "orientation"), &TextParagraph::set_orientation);
ClassDB::bind_method(D_METHOD("get_orientation"), &TextParagraph::get_orientation); ClassDB::bind_method(D_METHOD("get_orientation"), &TextParagraph::get_orientation);
@ -304,6 +309,15 @@ TextServer::Direction TextParagraph::get_direction() const {
return TS->shaped_text_get_direction(rid); return TS->shaped_text_get_direction(rid);
} }
void TextParagraph::set_custom_punctuation(const String &p_punct) {
TS->shaped_text_set_custom_punctuation(rid, p_punct);
lines_dirty = true;
}
String TextParagraph::get_custom_punctuation() const {
return TS->shaped_text_get_custom_punctuation(rid);
}
void TextParagraph::set_orientation(TextServer::Orientation p_orientation) { void TextParagraph::set_orientation(TextServer::Orientation p_orientation) {
TS->shaped_text_set_orientation(rid, p_orientation); TS->shaped_text_set_orientation(rid, p_orientation);
TS->shaped_text_set_orientation(dropcap_rid, p_orientation); TS->shaped_text_set_orientation(dropcap_rid, p_orientation);

View File

@ -96,6 +96,9 @@ public:
void set_bidi_override(const Array &p_override); void set_bidi_override(const Array &p_override);
void set_custom_punctuation(const String &p_punct);
String get_custom_punctuation() const;
bool set_dropcap(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Rect2 &p_dropcap_margins = Rect2(), const Dictionary &p_opentype_features = Dictionary(), const String &p_language = ""); bool set_dropcap(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Rect2 &p_dropcap_margins = Rect2(), const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "");
void clear_dropcap(); void clear_dropcap();

View File

@ -185,6 +185,9 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_shaped_text_set_bidi_override, "shaped", "override"); GDVIRTUAL_BIND(_shaped_text_set_bidi_override, "shaped", "override");
GDVIRTUAL_BIND(_shaped_text_set_custom_punctuation, "shaped", "punct");
GDVIRTUAL_BIND(_shaped_text_get_custom_punctuation, "shaped");
GDVIRTUAL_BIND(_shaped_text_set_orientation, "shaped", "orientation"); GDVIRTUAL_BIND(_shaped_text_set_orientation, "shaped", "orientation");
GDVIRTUAL_BIND(_shaped_text_get_orientation, "shaped"); GDVIRTUAL_BIND(_shaped_text_get_orientation, "shaped");
@ -906,6 +909,18 @@ void TextServerExtension::shaped_text_set_bidi_override(RID p_shaped, const Arra
GDVIRTUAL_CALL(_shaped_text_set_bidi_override, p_shaped, p_override); GDVIRTUAL_CALL(_shaped_text_set_bidi_override, p_shaped, p_override);
} }
void TextServerExtension::shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) {
GDVIRTUAL_CALL(_shaped_text_set_custom_punctuation, p_shaped, p_punct);
}
String TextServerExtension::shaped_text_get_custom_punctuation(RID p_shaped) const {
String ret;
if (GDVIRTUAL_CALL(_shaped_text_get_custom_punctuation, p_shaped, ret)) {
return ret;
}
return String();
}
void TextServerExtension::shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) { void TextServerExtension::shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) {
GDVIRTUAL_CALL(_shaped_text_set_preserve_invalid, p_shaped, p_enabled); GDVIRTUAL_CALL(_shaped_text_set_preserve_invalid, p_shaped, p_enabled);
} }

View File

@ -300,6 +300,11 @@ public:
virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override; virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override;
GDVIRTUAL2(_shaped_text_set_bidi_override, RID, const Array &); GDVIRTUAL2(_shaped_text_set_bidi_override, RID, const Array &);
virtual void shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) override;
virtual String shaped_text_get_custom_punctuation(RID p_shaped) const override;
GDVIRTUAL2(_shaped_text_set_custom_punctuation, RID, String);
GDVIRTUAL1RC(String, _shaped_text_get_custom_punctuation, RID);
virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override; virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override;
virtual Orientation shaped_text_get_orientation(RID p_shaped) const override; virtual Orientation shaped_text_get_orientation(RID p_shaped) const override;
GDVIRTUAL2(_shaped_text_set_orientation, RID, Orientation); GDVIRTUAL2(_shaped_text_set_orientation, RID, Orientation);

View File

@ -342,6 +342,9 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_set_bidi_override", "shaped", "override"), &TextServer::shaped_text_set_bidi_override); ClassDB::bind_method(D_METHOD("shaped_text_set_bidi_override", "shaped", "override"), &TextServer::shaped_text_set_bidi_override);
ClassDB::bind_method(D_METHOD("shaped_text_set_custom_punctuation", "shaped", "punct"), &TextServer::shaped_text_set_custom_punctuation);
ClassDB::bind_method(D_METHOD("shaped_text_get_custom_punctuation", "shaped"), &TextServer::shaped_text_get_custom_punctuation);
ClassDB::bind_method(D_METHOD("shaped_text_set_orientation", "shaped", "orientation"), &TextServer::shaped_text_set_orientation, DEFVAL(ORIENTATION_HORIZONTAL)); ClassDB::bind_method(D_METHOD("shaped_text_set_orientation", "shaped", "orientation"), &TextServer::shaped_text_set_orientation, DEFVAL(ORIENTATION_HORIZONTAL));
ClassDB::bind_method(D_METHOD("shaped_text_get_orientation", "shaped"), &TextServer::shaped_text_get_orientation); ClassDB::bind_method(D_METHOD("shaped_text_get_orientation", "shaped"), &TextServer::shaped_text_get_orientation);

View File

@ -145,6 +145,7 @@ protected:
int end = 0; // Substring end offset in the parent string. int end = 0; // Substring end offset in the parent string.
String text; String text;
String custom_punct;
TextServer::Direction direction = DIRECTION_LTR; // Desired text direction. TextServer::Direction direction = DIRECTION_LTR; // Desired text direction.
TextServer::Orientation orientation = ORIENTATION_HORIZONTAL; TextServer::Orientation orientation = ORIENTATION_HORIZONTAL;
@ -357,6 +358,9 @@ public:
virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) = 0; virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) = 0;
virtual void shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) = 0;
virtual String shaped_text_get_custom_punctuation(RID p_shaped) const = 0;
virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) = 0; virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) = 0;
virtual Orientation shaped_text_get_orientation(RID p_shaped) const = 0; virtual Orientation shaped_text_get_orientation(RID p_shaped) const = 0;