Selaa lähdekoodia

Merge pull request #46721 from bruvzg/custom_word_break_punct

Rémi Verschelde 3 vuotta sitten
vanhempi
commit
5968653662

+ 3 - 0
doc/classes/TextParagraph.xml

@@ -278,6 +278,9 @@
 		<member name="align" type="int" setter="set_align" getter="get_align" enum="HAlign" default="0">
 			Paragraph horizontal alignment.
 		</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">
 			Text writing direction.
 		</member>

+ 15 - 0
doc/classes/TextServer.xml

@@ -962,6 +962,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.
 			</description>
 		</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">
 			<return type="float" />
 			<argument index="0" name="shaped" type="RID" />
@@ -1212,6 +1219,14 @@
 				Override ranges should cover full source text without overlaps. BiDi algorithm will be used on each range separately.
 			</description>
 		</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">
 			<return type="void" />
 			<argument index="0" name="shaped" type="RID" />

+ 15 - 0
doc/classes/TextServerExtension.xml

@@ -969,6 +969,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.
 			</description>
 		</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">
 			<return type="float" />
 			<argument index="0" name="shaped" type="RID" />
@@ -1221,6 +1228,14 @@
 				Override ranges should cover full source text without overlaps. BiDi algorithm will be used on each range separately.
 			</description>
 		</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">
 			<return type="void" />
 			<argument index="0" name="shaped" type="RID" />

+ 37 - 3
modules/text_server_adv/text_server_adv.cpp

@@ -3008,6 +3008,27 @@ TextServer::Direction TextServerAdvanced::shaped_text_get_direction(RID p_shaped
 	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) {
 	ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
 	ERR_FAIL_COND(!sd);
@@ -3307,6 +3328,7 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng
 
 	new_sd->orientation = sd->orientation;
 	new_sd->direction = sd->direction;
+	new_sd->custom_punct = sd->custom_punct;
 	new_sd->para_direction = sd->para_direction;
 	new_sd->line_breaks_valid = sd->line_breaks_valid;
 	new_sd->justification_ops_valid = sd->justification_ops_valid;
@@ -3887,6 +3909,9 @@ bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) {
 	const char32_t *ch = sd->text.ptr();
 	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++) {
 		if (sd_glyphs[i].count > 0) {
 			char32_t c = ch[sd_glyphs[i].start - sd->start];
@@ -3899,12 +3924,21 @@ bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) {
 			if (is_whitespace(c)) {
 				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)) {
 				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[sd->glyphs[i].start]) {
 					sd_glyphs[i].flags |= GRAPHEME_IS_BREAK_HARD;

+ 3 - 0
modules/text_server_adv/text_server_adv.h

@@ -463,6 +463,9 @@ public:
 
 	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 Orientation shaped_text_get_orientation(RID p_shaped) const override;
 

+ 45 - 9
modules/text_server_fb/text_server_fb.cpp

@@ -2107,6 +2107,27 @@ TextServer::Direction TextServerFallback::shaped_text_get_direction(RID p_shaped
 	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) {
 	ShapedTextData *sd = shaped_owner.get_or_null(p_shaped);
 	ERR_FAIL_COND(!sd);
@@ -2409,6 +2430,7 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng
 
 	new_sd->orientation = sd->orientation;
 	new_sd->direction = sd->direction;
+	new_sd->custom_punct = sd->custom_punct;
 	new_sd->para_direction = sd->para_direction;
 	new_sd->line_breaks_valid = sd->line_breaks_valid;
 	new_sd->justification_ops_valid = sd->justification_ops_valid;
@@ -2692,27 +2714,41 @@ bool TextServerFallback::shaped_text_update_breaks(RID p_shaped) {
 	}
 
 	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++) {
-		if (sd->glyphs[i].count > 0) {
-			char32_t c = sd->text[sd->glyphs[i].start];
-			if (is_punct(c)) {
-				sd->glyphs.write[i].flags |= GRAPHEME_IS_PUNCTUATION;
+		if (sd_glyphs[i].count > 0) {
+			char32_t c = sd->text[sd_glyphs[i].start];
+			if (c_punct_size == 0) {
+				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)) {
 				sd->glyphs.write[i].flags |= GRAPHEME_IS_UNDERSCORE;
 			}
 			if (is_whitespace(c) && !is_linebreak(c)) {
-				sd->glyphs.write[i].flags |= GRAPHEME_IS_SPACE;
-				sd->glyphs.write[i].flags |= GRAPHEME_IS_BREAK_SOFT;
+				sd_glyphs[i].flags |= GRAPHEME_IS_SPACE;
+				sd_glyphs[i].flags |= GRAPHEME_IS_BREAK_SOFT;
 			}
 			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) {
-				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;

+ 3 - 0
modules/text_server_fb/text_server_fb.h

@@ -374,6 +374,9 @@ public:
 
 	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 Orientation shaped_text_get_orientation(RID p_shaped) const override;
 

+ 14 - 0
scene/resources/text_paragraph.cpp

@@ -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");
 
+	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("get_orientation"), &TextParagraph::get_orientation);
 
@@ -304,6 +309,15 @@ TextServer::Direction TextParagraph::get_direction() const {
 	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) {
 	TS->shaped_text_set_orientation(rid, p_orientation);
 	TS->shaped_text_set_orientation(dropcap_rid, p_orientation);

+ 3 - 0
scene/resources/text_paragraph.h

@@ -96,6 +96,9 @@ public:
 
 	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 = "");
 	void clear_dropcap();
 

+ 15 - 0
servers/text/text_server_extension.cpp

@@ -194,6 +194,9 @@ void TextServerExtension::_bind_methods() {
 
 	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_get_orientation, "shaped");
 
@@ -951,6 +954,18 @@ void TextServerExtension::shaped_text_set_bidi_override(RID p_shaped, const Arra
 	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) {
 	GDVIRTUAL_CALL(_shaped_text_set_preserve_invalid, p_shaped, p_enabled);
 }

+ 5 - 0
servers/text/text_server_extension.h

@@ -316,6 +316,11 @@ public:
 	virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override;
 	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 Orientation shaped_text_get_orientation(RID p_shaped) const override;
 	GDVIRTUAL2(_shaped_text_set_orientation, RID, Orientation);

+ 3 - 0
servers/text_server.cpp

@@ -347,6 +347,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_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_get_orientation", "shaped"), &TextServer::shaped_text_get_orientation);
 

+ 4 - 0
servers/text_server.h

@@ -150,6 +150,7 @@ protected:
 		int end = 0; // Substring end offset in the parent string.
 
 		String text;
+		String custom_punct;
 		TextServer::Direction direction = DIRECTION_LTR; // Desired text direction.
 		TextServer::Orientation orientation = ORIENTATION_HORIZONTAL;
 
@@ -369,6 +370,9 @@ public:
 
 	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 Orientation shaped_text_get_orientation(RID p_shaped) const = 0;