From 8459aeaab0047c1ee96c6987f6432420a6057c6b Mon Sep 17 00:00:00 2001
From: bruvzg <7645683+bruvzg@users.noreply.github.com>
Date: Mon, 27 Feb 2023 16:21:28 +0200
Subject: [PATCH] [Font] Implement `get_char_from_glyph_index` function.
---
doc/classes/FontFile.xml | 8 ++++++
doc/classes/TextServer.xml | 11 +++++++-
doc/classes/TextServerExtension.xml | 8 ++++++
modules/text_server_adv/text_server_adv.cpp | 31 +++++++++++++++++++++
modules/text_server_adv/text_server_adv.h | 2 ++
modules/text_server_fb/text_server_fb.cpp | 4 +++
modules/text_server_fb/text_server_fb.h | 1 +
scene/resources/font.cpp | 6 ++++
scene/resources/font.h | 1 +
servers/text/text_server_extension.cpp | 7 +++++
servers/text/text_server_extension.h | 3 ++
servers/text_server.cpp | 1 +
servers/text_server.h | 1 +
13 files changed, 83 insertions(+), 1 deletion(-)
diff --git a/doc/classes/FontFile.xml b/doc/classes/FontFile.xml
index a349c2b7b74b..ec14eca62044 100644
--- a/doc/classes/FontFile.xml
+++ b/doc/classes/FontFile.xml
@@ -115,6 +115,14 @@
Returns thickness of the underline in pixels.
+
+
+
+
+
+ Returns character code associated with [param glyph_index], or [code]0[/code] if [param glyph_index] is invalid. See [method get_glyph_index].
+
+
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index ad37cf5c86e1..55490042d92d 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -113,6 +113,15 @@
Returns the font ascent (number of pixels above the baseline).
+
+
+
+
+
+
+ Returns character code associated with [param glyph_index], or [code]0[/code] if [param glyph_index] is invalid. See [method font_get_glyph_index].
+
+
@@ -191,7 +200,7 @@
- Returns the glyph index of a [param char], optionally modified by the [param variation_selector].
+ Returns the glyph index of a [param char], optionally modified by the [param variation_selector]. See [method font_get_char_from_glyph_index].
diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml
index f4b306cf9667..1255bd1f99c3 100644
--- a/doc/classes/TextServerExtension.xml
+++ b/doc/classes/TextServerExtension.xml
@@ -99,6 +99,14 @@
+
+
+
+
+
+
+
+
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 22652daa24a4..800489e5cfc2 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -3082,6 +3082,37 @@ int64_t TextServerAdvanced::_font_get_glyph_index(const RID &p_font_rid, int64_t
#endif
}
+int64_t TextServerAdvanced::_font_get_char_from_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_glyph_index) const {
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, 0);
+
+ MutexLock lock(fd->mutex);
+ Vector2i size = _get_size(fd, p_size);
+ ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0);
+
+#ifdef MODULE_FREETYPE_ENABLED
+ if (fd->cache[size]->inv_glyph_map.is_empty()) {
+ FT_Face face = fd->cache[size]->face;
+ FT_UInt gindex;
+ FT_ULong charcode = FT_Get_First_Char(face, &gindex);
+ while (gindex != 0) {
+ if (charcode != 0) {
+ fd->cache[size]->inv_glyph_map[gindex] = charcode;
+ }
+ charcode = FT_Get_Next_Char(face, charcode, &gindex);
+ }
+ }
+
+ if (fd->cache[size]->inv_glyph_map.has(p_glyph_index)) {
+ return fd->cache[size]->inv_glyph_map[p_glyph_index];
+ } else {
+ return 0;
+ }
+#else
+ return p_glyph_index;
+#endif
+}
+
bool TextServerAdvanced::_font_has_char(const RID &p_font_rid, int64_t p_char) const {
FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V_MSG((p_char >= 0xd800 && p_char <= 0xdfff) || (p_char > 0x10ffff), false, "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_char, 16) + ".");
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index 02244a294ee1..6216c40b1b88 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -272,6 +272,7 @@ class TextServerAdvanced : public TextServerExtension {
Vector2i size;
Vector textures;
+ HashMap inv_glyph_map;
HashMap glyph_map;
HashMap kerning_map;
hb_font_t *hb_handle = nullptr;
@@ -812,6 +813,7 @@ public:
MODBIND3RC(Vector2, font_get_kerning, const RID &, int64_t, const Vector2i &);
MODBIND4RC(int64_t, font_get_glyph_index, const RID &, int64_t, int64_t, int64_t);
+ MODBIND3RC(int64_t, font_get_char_from_glyph_index, const RID &, int64_t, int64_t);
MODBIND2RC(bool, font_has_char, const RID &, int64_t);
MODBIND1RC(String, font_get_supported_chars, const RID &);
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 240ae8310a76..70df25942aef 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -2160,6 +2160,10 @@ int64_t TextServerFallback::_font_get_glyph_index(const RID &p_font_rid, int64_t
return (int64_t)p_char;
}
+int64_t TextServerFallback::_font_get_char_from_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_glyph_index) const {
+ return p_glyph_index;
+}
+
bool TextServerFallback::_font_has_char(const RID &p_font_rid, int64_t p_char) const {
FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V_MSG((p_char >= 0xd800 && p_char <= 0xdfff) || (p_char > 0x10ffff), false, "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_char, 16) + ".");
diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h
index 12ed21ee9507..105569c26dfe 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -685,6 +685,7 @@ public:
MODBIND3RC(Vector2, font_get_kerning, const RID &, int64_t, const Vector2i &);
MODBIND4RC(int64_t, font_get_glyph_index, const RID &, int64_t, int64_t, int64_t);
+ MODBIND3RC(int64_t, font_get_char_from_glyph_index, const RID &, int64_t, int64_t);
MODBIND2RC(bool, font_has_char, const RID &, int64_t);
MODBIND1RC(String, font_get_supported_chars, const RID &);
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index 0f7985bee6e0..85c51da22954 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -980,6 +980,7 @@ void FontFile::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_opentype_feature_overrides"), &FontFile::get_opentype_feature_overrides);
ClassDB::bind_method(D_METHOD("get_glyph_index", "size", "char", "variation_selector"), &FontFile::get_glyph_index);
+ ClassDB::bind_method(D_METHOD("get_char_from_glyph_index", "size", "glyph_index"), &FontFile::get_char_from_glyph_index);
ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_data", "get_data");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_generate_mipmaps", "get_generate_mipmaps");
@@ -2585,6 +2586,11 @@ int32_t FontFile::get_glyph_index(int p_size, char32_t p_char, char32_t p_variat
return TS->font_get_glyph_index(cache[0], p_size, p_char, p_variation_selector);
}
+char32_t FontFile::get_char_from_glyph_index(int p_size, int32_t p_glyph_index) const {
+ _ensure_rid(0);
+ return TS->font_get_char_from_glyph_index(cache[0], p_size, p_glyph_index);
+}
+
FontFile::FontFile() {
}
diff --git a/scene/resources/font.h b/scene/resources/font.h
index ef79f8bd0254..a99151640eb8 100644
--- a/scene/resources/font.h
+++ b/scene/resources/font.h
@@ -359,6 +359,7 @@ public:
// Base font properties.
virtual int32_t get_glyph_index(int p_size, char32_t p_char, char32_t p_variation_selector = 0x0000) const;
+ virtual char32_t get_char_from_glyph_index(int p_size, int32_t p_glyph_index) const;
FontFile();
~FontFile();
diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp
index 9a996c07d370..c1078d94930d 100644
--- a/servers/text/text_server_extension.cpp
+++ b/servers/text/text_server_extension.cpp
@@ -178,6 +178,7 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_font_get_kerning, "font_rid", "size", "glyph_pair");
GDVIRTUAL_BIND(_font_get_glyph_index, "font_rid", "size", "char", "variation_selector");
+ GDVIRTUAL_BIND(_font_get_char_from_glyph_index, "font_rid", "size", "glyph_index");
GDVIRTUAL_BIND(_font_has_char, "font_rid", "char");
GDVIRTUAL_BIND(_font_get_supported_chars, "font_rid");
@@ -825,6 +826,12 @@ int64_t TextServerExtension::font_get_glyph_index(const RID &p_font_rid, int64_t
return ret;
}
+int64_t TextServerExtension::font_get_char_from_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_glyph_index) const {
+ int64_t ret = 0;
+ GDVIRTUAL_CALL(_font_get_char_from_glyph_index, p_font_rid, p_size, p_glyph_index, ret);
+ return ret;
+}
+
bool TextServerExtension::font_has_char(const RID &p_font_rid, int64_t p_char) const {
bool ret = false;
GDVIRTUAL_CALL(_font_has_char, p_font_rid, p_char, ret);
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
index 5d11af0bf104..402f0ec7acbd 100644
--- a/servers/text/text_server_extension.h
+++ b/servers/text/text_server_extension.h
@@ -294,6 +294,9 @@ public:
virtual int64_t font_get_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_char, int64_t p_variation_selector = 0) const override;
GDVIRTUAL4RC(int64_t, _font_get_glyph_index, RID, int64_t, int64_t, int64_t);
+ virtual int64_t font_get_char_from_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_glyph_index) const override;
+ GDVIRTUAL3RC(int64_t, _font_get_char_from_glyph_index, RID, int64_t, int64_t);
+
virtual bool font_has_char(const RID &p_font_rid, int64_t p_char) const override;
virtual String font_get_supported_chars(const RID &p_font_rid) const override;
GDVIRTUAL2RC(bool, _font_has_char, RID, int64_t);
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index 027109b67d82..88f1e76811a8 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -332,6 +332,7 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_get_kerning", "font_rid", "size", "glyph_pair"), &TextServer::font_get_kerning);
ClassDB::bind_method(D_METHOD("font_get_glyph_index", "font_rid", "size", "char", "variation_selector"), &TextServer::font_get_glyph_index);
+ ClassDB::bind_method(D_METHOD("font_get_char_from_glyph_index", "font_rid", "size", "glyph_index"), &TextServer::font_get_char_from_glyph_index);
ClassDB::bind_method(D_METHOD("font_has_char", "font_rid", "char"), &TextServer::font_has_char);
ClassDB::bind_method(D_METHOD("font_get_supported_chars", "font_rid"), &TextServer::font_get_supported_chars);
diff --git a/servers/text_server.h b/servers/text_server.h
index 2c6a8af6825a..e3c668bd5ca4 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -359,6 +359,7 @@ public:
virtual Vector2 font_get_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) const = 0;
virtual int64_t font_get_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_char, int64_t p_variation_selector) const = 0;
+ virtual int64_t font_get_char_from_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_glyph_index) const = 0;
virtual bool font_has_char(const RID &p_font_rid, int64_t p_char) const = 0;
virtual String font_get_supported_chars(const RID &p_font_rid) const = 0;