From 0d3fa2a12558d90e7b9cc05f38e8b5c866a2d794 Mon Sep 17 00:00:00 2001
From: bruvzg <7645683+bruvzg@users.noreply.github.com>
Date: Thu, 10 Dec 2020 17:30:25 +0200
Subject: [PATCH] [Complex Text Layouts] Provide access to glyph contour
points.
---
doc/classes/TextServer.xml | 25 +++++++++++++++++++
modules/gdnative/include/text/godot_text.h | 1 +
.../gdnative/text/text_server_gdnative.cpp | 6 +++++
modules/gdnative/text/text_server_gdnative.h | 2 ++
modules/text_server_adv/dynamic_font_adv.cpp | 23 +++++++++++++++++
modules/text_server_adv/dynamic_font_adv.h | 2 ++
modules/text_server_adv/font_adv.h | 6 +++--
modules/text_server_adv/text_server_adv.cpp | 7 ++++++
modules/text_server_adv/text_server_adv.h | 2 ++
modules/text_server_fb/dynamic_font_fb.cpp | 23 +++++++++++++++++
modules/text_server_fb/dynamic_font_fb.h | 2 ++
modules/text_server_fb/font_fb.h | 2 ++
modules/text_server_fb/text_server_fb.cpp | 7 ++++++
modules/text_server_fb/text_server_fb.h | 2 ++
servers/text_server.cpp | 22 ++++++++++++++++
servers/text_server.h | 11 ++++++++
16 files changed, 141 insertions(+), 2 deletions(-)
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index 4a41b68fee6..fe63e434c9b 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -258,6 +258,22 @@
Returns advance of the glyph.
+
+
+
+
+
+
+
+
+
+
+ Returns outline contours of the glyph in a Dictionary.
+ [code]points[/code] - [PackedVector3Array], containing outline points. [code]x[/code] and [code]y[/code] are point coordinates. [code]z[/code] is the type of the point, using the [enum ContourPointTag] values.
+ [code]contours[/code] - [PackedInt32Array], containing indices the end points of each contour.
+ [code]orientation[/code] - [bool], contour orientation. If [code]true[/code], clockwise contours must be filled.
+
+
@@ -1301,5 +1317,14 @@
TextServer require external data file for some features.
+
+ Contour point is on the curve.
+
+
+ Contour point isn't on the curve, but serves as a control point for a conic (quadratic) Bézier arc.
+
+
+ Contour point isn't on the curve, but serves as a control point for a cubic Bézier arc.
+
diff --git a/modules/gdnative/include/text/godot_text.h b/modules/gdnative/include/text/godot_text.h
index 86fc7451344..99c78c72e66 100644
--- a/modules/gdnative/include/text/godot_text.h
+++ b/modules/gdnative/include/text/godot_text.h
@@ -118,6 +118,7 @@ typedef struct {
godot_vector2 (*font_get_glyph_kerning)(void *, godot_rid *, uint32_t, uint32_t, int);
godot_vector2 (*font_draw_glyph)(void *, godot_rid *, godot_rid *, int, const godot_vector2 *, uint32_t, const godot_color *);
godot_vector2 (*font_draw_glyph_outline)(void *, godot_rid *, godot_rid *, int, int, const godot_vector2 *, uint32_t, const godot_color *);
+ bool (*font_get_glyph_contours)(void *, godot_rid *, int, uint32_t, godot_packed_vector3_array *, godot_packed_int32_array *, bool *);
float (*font_get_oversampling)(void *);
void (*font_set_oversampling)(void *, float);
godot_packed_string_array (*get_system_fonts)(void *);
diff --git a/modules/gdnative/text/text_server_gdnative.cpp b/modules/gdnative/text/text_server_gdnative.cpp
index 7cd8de5f2e6..7cb749309a7 100644
--- a/modules/gdnative/text/text_server_gdnative.cpp
+++ b/modules/gdnative/text/text_server_gdnative.cpp
@@ -359,6 +359,12 @@ Vector2 TextServerGDNative::font_draw_glyph_outline(RID p_font, RID p_canvas, in
return advance;
}
+bool TextServerGDNative::font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index, Vector &r_points, Vector &r_contours, bool &r_orientation) const {
+ ERR_FAIL_COND_V(interface == nullptr, false);
+ ERR_FAIL_COND_V(interface->font_get_glyph_contours == nullptr, false);
+ return interface->font_get_glyph_contours(data, (godot_rid *)&p_font, p_size, p_index, (godot_packed_vector3_array *)&r_points, (godot_packed_int32_array *)&r_contours, (bool *)&r_orientation);
+}
+
float TextServerGDNative::font_get_oversampling() const {
ERR_FAIL_COND_V(interface == nullptr, 1.f);
return interface->font_get_oversampling(data);
diff --git a/modules/gdnative/text/text_server_gdnative.h b/modules/gdnative/text/text_server_gdnative.h
index 931bb44885a..7e42b16fe17 100644
--- a/modules/gdnative/text/text_server_gdnative.h
+++ b/modules/gdnative/text/text_server_gdnative.h
@@ -126,6 +126,8 @@ public:
virtual Vector2 font_draw_glyph(RID p_font, RID p_canvas, int p_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const override;
virtual Vector2 font_draw_glyph_outline(RID p_font, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const override;
+ virtual bool font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index, Vector &r_points, Vector &r_contours, bool &r_orientation) const override;
+
virtual float font_get_oversampling() const override;
virtual void font_set_oversampling(float p_oversampling) override;
diff --git a/modules/text_server_adv/dynamic_font_adv.cpp b/modules/text_server_adv/dynamic_font_adv.cpp
index 2521e68dda6..19d04bdb022 100644
--- a/modules/text_server_adv/dynamic_font_adv.cpp
+++ b/modules/text_server_adv/dynamic_font_adv.cpp
@@ -997,6 +997,29 @@ Vector2 DynamicFontDataAdvanced::draw_glyph_outline(RID p_canvas, int p_size, in
return advance;
}
+bool DynamicFontDataAdvanced::get_glyph_contours(int p_size, uint32_t p_index, Vector &r_points, Vector &r_contours, bool &r_orientation) const {
+ _THREAD_SAFE_METHOD_
+ DataAtSize *fds = const_cast(this)->get_data_for_size(p_size);
+ ERR_FAIL_COND_V(fds == nullptr, false);
+
+ int error = FT_Load_Glyph(fds->face, p_index, FT_LOAD_NO_BITMAP | (force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0));
+ ERR_FAIL_COND_V(error, false);
+
+ r_points.clear();
+ r_contours.clear();
+
+ float h = fds->ascent;
+ float scale = (1.0 / 64.0) / oversampling * fds->scale_color_font;
+ for (short i = 0; i < fds->face->glyph->outline.n_points; i++) {
+ r_points.push_back(Vector3(fds->face->glyph->outline.points[i].x * scale, h - fds->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(fds->face->glyph->outline.tags[i])));
+ }
+ for (short i = 0; i < fds->face->glyph->outline.n_contours; i++) {
+ r_contours.push_back(fds->face->glyph->outline.contours[i]);
+ }
+ r_orientation = (FT_Outline_Get_Orientation(&fds->face->glyph->outline) == FT_ORIENTATION_FILL_RIGHT);
+ return true;
+}
+
DynamicFontDataAdvanced::~DynamicFontDataAdvanced() {
clear_cache();
if (library != nullptr) {
diff --git a/modules/text_server_adv/dynamic_font_adv.h b/modules/text_server_adv/dynamic_font_adv.h
index d69a30b321f..1292966f0cd 100644
--- a/modules/text_server_adv/dynamic_font_adv.h
+++ b/modules/text_server_adv/dynamic_font_adv.h
@@ -186,6 +186,8 @@ public:
virtual Vector2 draw_glyph(RID p_canvas, int p_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color) const override;
virtual Vector2 draw_glyph_outline(RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color) const override;
+ virtual bool get_glyph_contours(int p_size, uint32_t p_index, Vector &r_points, Vector &r_contours, bool &r_orientation) const override;
+
virtual ~DynamicFontDataAdvanced() override;
};
diff --git a/modules/text_server_adv/font_adv.h b/modules/text_server_adv/font_adv.h
index 2b6d977451b..4fadefc5693 100644
--- a/modules/text_server_adv/font_adv.h
+++ b/modules/text_server_adv/font_adv.h
@@ -92,8 +92,8 @@ struct FontDataAdvanced {
virtual bool has_outline() const = 0;
virtual float get_base_size() const = 0;
- virtual bool is_lang_supported(const String &p_lang) const { return false; };
- virtual bool is_script_supported(uint32_t p_script) const { return false; };
+ virtual bool is_lang_supported(const String &p_lang) const { return true; };
+ virtual bool is_script_supported(uint32_t p_script) const { return true; };
virtual bool has_char(char32_t p_char) const = 0;
virtual String get_supported_chars() const = 0;
@@ -107,6 +107,8 @@ struct FontDataAdvanced {
virtual Vector2 draw_glyph(RID p_canvas, int p_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color) const = 0;
virtual Vector2 draw_glyph_outline(RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color) const = 0;
+ virtual bool get_glyph_contours(int p_size, uint32_t p_index, Vector &r_points, Vector &r_contours, bool &r_orientation) const { return false; };
+
virtual ~FontDataAdvanced(){};
};
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 43b8f181017..9007c696ebf 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -906,6 +906,13 @@ Vector2 TextServerAdvanced::font_draw_glyph_outline(RID p_font, RID p_canvas, in
return fd->draw_glyph_outline(p_canvas, p_size, p_outline_size, p_pos, p_index, p_color);
}
+bool TextServerAdvanced::font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index, Vector &r_points, Vector &r_contours, bool &r_orientation) const {
+ _THREAD_SAFE_METHOD_
+ const FontDataAdvanced *fd = font_owner.getornull(p_font);
+ ERR_FAIL_COND_V(!fd, false);
+ return fd->get_glyph_contours(p_size, p_index, r_points, r_contours, r_orientation);
+}
+
float TextServerAdvanced::font_get_oversampling() const {
return oversampling;
}
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index b53b5716e52..4ad23ca0591 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -188,6 +188,8 @@ public:
virtual Vector2 font_draw_glyph(RID p_font, RID p_canvas, int p_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const override;
virtual Vector2 font_draw_glyph_outline(RID p_font, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const override;
+ virtual bool font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index, Vector &r_points, Vector &r_contours, bool &r_orientation) const override;
+
virtual float font_get_oversampling() const override;
virtual void font_set_oversampling(float p_oversampling) override;
diff --git a/modules/text_server_fb/dynamic_font_fb.cpp b/modules/text_server_fb/dynamic_font_fb.cpp
index 66d36bc885a..dec1d6f83fd 100644
--- a/modules/text_server_fb/dynamic_font_fb.cpp
+++ b/modules/text_server_fb/dynamic_font_fb.cpp
@@ -680,6 +680,29 @@ Vector2 DynamicFontDataFallback::draw_glyph_outline(RID p_canvas, int p_size, in
return advance;
}
+bool DynamicFontDataFallback::get_glyph_contours(int p_size, uint32_t p_index, Vector &r_points, Vector &r_contours, bool &r_orientation) const {
+ _THREAD_SAFE_METHOD_
+ DataAtSize *fds = const_cast(this)->get_data_for_size(p_size);
+ ERR_FAIL_COND_V(fds == nullptr, false);
+
+ int error = FT_Load_Glyph(fds->face, p_index, FT_LOAD_NO_BITMAP | (force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0));
+ ERR_FAIL_COND_V(error, false);
+
+ r_points.clear();
+ r_contours.clear();
+
+ float h = fds->ascent;
+ float scale = (1.0 / 64.0) / oversampling * fds->scale_color_font;
+ for (short i = 0; i < fds->face->glyph->outline.n_points; i++) {
+ r_points.push_back(Vector3(fds->face->glyph->outline.points[i].x * scale, h - fds->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(fds->face->glyph->outline.tags[i])));
+ }
+ for (short i = 0; i < fds->face->glyph->outline.n_contours; i++) {
+ r_contours.push_back(fds->face->glyph->outline.contours[i]);
+ }
+ r_orientation = (FT_Outline_Get_Orientation(&fds->face->glyph->outline) == FT_ORIENTATION_FILL_RIGHT);
+ return true;
+}
+
DynamicFontDataFallback::~DynamicFontDataFallback() {
clear_cache();
if (library != nullptr) {
diff --git a/modules/text_server_fb/dynamic_font_fb.h b/modules/text_server_fb/dynamic_font_fb.h
index eb70f466667..b34c8cbed5a 100644
--- a/modules/text_server_fb/dynamic_font_fb.h
+++ b/modules/text_server_fb/dynamic_font_fb.h
@@ -164,6 +164,8 @@ public:
virtual Vector2 draw_glyph(RID p_canvas, int p_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color) const override;
virtual Vector2 draw_glyph_outline(RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color) const override;
+ virtual bool get_glyph_contours(int p_size, uint32_t p_index, Vector &r_points, Vector &r_contours, bool &r_orientation) const override;
+
virtual ~DynamicFontDataFallback() override;
};
diff --git a/modules/text_server_fb/font_fb.h b/modules/text_server_fb/font_fb.h
index 218f3df03a2..fe9888b7f4b 100644
--- a/modules/text_server_fb/font_fb.h
+++ b/modules/text_server_fb/font_fb.h
@@ -93,6 +93,8 @@ struct FontDataFallback {
virtual Vector2 draw_glyph(RID p_canvas, int p_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color) const = 0;
virtual Vector2 draw_glyph_outline(RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color) const = 0;
+ virtual bool get_glyph_contours(int p_size, uint32_t p_index, Vector &r_points, Vector &r_contours, bool &r_orientation) const { return false; };
+
virtual ~FontDataFallback(){};
};
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index f46f96d30df..98a67ef309d 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -452,6 +452,13 @@ Vector2 TextServerFallback::font_draw_glyph_outline(RID p_font, RID p_canvas, in
return fd->draw_glyph_outline(p_canvas, p_size, p_outline_size, p_pos, p_index, p_color);
}
+bool TextServerFallback::font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index, Vector &r_points, Vector &r_contours, bool &r_orientation) const {
+ _THREAD_SAFE_METHOD_
+ const FontDataFallback *fd = font_owner.getornull(p_font);
+ ERR_FAIL_COND_V(!fd, false);
+ return fd->get_glyph_contours(p_size, p_index, r_points, r_contours, r_orientation);
+}
+
float TextServerFallback::font_get_oversampling() const {
return oversampling;
}
diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h
index b10369d1726..8f5eb1d315e 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -137,6 +137,8 @@ public:
virtual Vector2 font_draw_glyph(RID p_font, RID p_canvas, int p_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const override;
virtual Vector2 font_draw_glyph_outline(RID p_font, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const override;
+ virtual bool font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index, Vector &r_points, Vector &r_contours, bool &r_orientation) const override;
+
virtual float font_get_oversampling() const override;
virtual void font_set_oversampling(float p_oversampling) override;
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index d6d3c11cfba..8b035652911 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -291,6 +291,8 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_hex_code_box_size", "size", "index"), &TextServer::get_hex_code_box_size);
ClassDB::bind_method(D_METHOD("draw_hex_code_box", "canvas", "size", "pos", "index", "color"), &TextServer::draw_hex_code_box);
+ ClassDB::bind_method(D_METHOD("font_get_glyph_contours", "font", "size", "index"), &TextServer::_font_get_glyph_contours);
+
/* Shaped text buffer interface */
ClassDB::bind_method(D_METHOD("create_shaped_text", "direction", "orientation"), &TextServer::create_shaped_text, DEFVAL(DIRECTION_AUTO), DEFVAL(ORIENTATION_HORIZONTAL));
@@ -403,6 +405,11 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(FEATURE_FONT_SYSTEM);
BIND_ENUM_CONSTANT(FEATURE_FONT_VARIABLE);
BIND_ENUM_CONSTANT(FEATURE_USE_SUPPORT_DATA);
+
+ /* FT Contour Point Types */
+ BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_ON);
+ BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_OFF_CONIC);
+ BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_OFF_CUBIC);
}
Vector3 TextServer::hex_code_box_font_size[2] = { Vector3(5, 5, 1), Vector3(10, 10, 2) };
@@ -1212,6 +1219,21 @@ RID TextServer::_create_font_memory(const PackedByteArray &p_data, const String
return create_font_memory(p_data.ptr(), p_data.size(), p_type, p_base_size);
}
+Dictionary TextServer::_font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index) const {
+ Vector points;
+ Vector contours;
+ bool orientation;
+ bool ok = font_get_glyph_contours(p_font, p_size, p_index, points, contours, orientation);
+ Dictionary out;
+
+ if (ok) {
+ out["points"] = points;
+ out["contours"] = contours;
+ out["orientation"] = orientation;
+ }
+ return out;
+}
+
void TextServer::_shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) {
Vector overrides;
for (int i = 0; i < p_override.size(); i++) {
diff --git a/servers/text_server.h b/servers/text_server.h
index e1429da1d1c..7fcfb91151e 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -99,6 +99,12 @@ public:
FEATURE_USE_SUPPORT_DATA = 1 << 7
};
+ enum ContourPointTag {
+ CONTOUR_CURVE_TAG_ON = 0x01,
+ CONTOUR_CURVE_TAG_OFF_CONIC = 0x00,
+ CONTOUR_CURVE_TAG_OFF_CUBIC = 0x02
+ };
+
struct Glyph {
int start = -1; // Start offset in the source string.
int end = -1; // End offset in the source string.
@@ -286,6 +292,8 @@ public:
virtual Vector2 font_draw_glyph(RID p_font, RID p_canvas, int p_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const = 0;
virtual Vector2 font_draw_glyph_outline(RID p_font, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, uint32_t p_index, const Color &p_color = Color(1, 1, 1)) const = 0;
+ virtual bool font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index, Vector &r_points, Vector &r_contours, bool &r_orientation) const = 0;
+
virtual float font_get_oversampling() const = 0;
virtual void font_set_oversampling(float p_oversampling) = 0;
@@ -372,6 +380,8 @@ public:
/* GDScript wrappers */
RID _create_font_memory(const PackedByteArray &p_data, const String &p_type, int p_base_size = 16);
+ Dictionary _font_get_glyph_contours(RID p_font, int p_size, uint32_t p_index) const;
+
Array _shaped_text_get_glyphs(RID p_shaped) const;
Dictionary _shaped_text_get_carets(RID p_shaped, int p_position) const;
@@ -454,5 +464,6 @@ VARIANT_ENUM_CAST(TextServer::LineBreakFlag);
VARIANT_ENUM_CAST(TextServer::GraphemeFlag);
VARIANT_ENUM_CAST(TextServer::Hinting);
VARIANT_ENUM_CAST(TextServer::Feature);
+VARIANT_ENUM_CAST(TextServer::ContourPointTag);
#endif // TEXT_SERVER_H