浏览代码

Merge pull request #44289 from bruvzg/ctl_gl_contours

Expose dynamic font vector outlines to the GDScript.
Rémi Verschelde 4 年之前
父节点
当前提交
3096423ddc

+ 25 - 0
doc/classes/TextServer.xml

@@ -258,6 +258,22 @@
 				Returns advance of the glyph.
 			</description>
 		</method>
+		<method name="font_get_glyph_contours" qualifiers="const">
+			<return type="Dictionary">
+			</return>
+			<argument index="0" name="font" type="RID">
+			</argument>
+			<argument index="1" name="size" type="int">
+			</argument>
+			<argument index="2" name="index" type="int">
+			</argument>
+			<description>
+				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.
+			</description>
+		</method>
 		<method name="font_get_glyph_index" qualifiers="const">
 			<return type="int">
 			</return>
@@ -1301,5 +1317,14 @@
 		<constant name="FEATURE_USE_SUPPORT_DATA" value="128" enum="Feature">
 			TextServer require external data file for some features.
 		</constant>
+		<constant name="CONTOUR_CURVE_TAG_ON" value="1" enum="ContourPointTag">
+			Contour point is on the curve.
+		</constant>
+		<constant name="CONTOUR_CURVE_TAG_OFF_CONIC" value="0" enum="ContourPointTag">
+			Contour point isn't on the curve, but serves as a control point for a conic (quadratic) Bézier arc.
+		</constant>
+		<constant name="CONTOUR_CURVE_TAG_OFF_CUBIC" value="2" enum="ContourPointTag">
+			Contour point isn't on the curve, but serves as a control point for a cubic Bézier arc.
+		</constant>
 	</constants>
 </class>

+ 1 - 0
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 *);

+ 6 - 0
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<Vector3> &r_points, Vector<int32_t> &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);

+ 2 - 0
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<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const override;
+
 	virtual float font_get_oversampling() const override;
 	virtual void font_set_oversampling(float p_oversampling) override;
 

+ 23 - 0
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<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const {
+	_THREAD_SAFE_METHOD_
+	DataAtSize *fds = const_cast<DynamicFontDataAdvanced *>(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) {

+ 2 - 0
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<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const override;
+
 	virtual ~DynamicFontDataAdvanced() override;
 };
 

+ 4 - 2
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<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const { return false; };
+
 	virtual ~FontDataAdvanced(){};
 };
 

+ 7 - 0
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<Vector3> &r_points, Vector<int32_t> &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;
 }

+ 2 - 0
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<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const override;
+
 	virtual float font_get_oversampling() const override;
 	virtual void font_set_oversampling(float p_oversampling) override;
 

+ 23 - 0
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<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const {
+	_THREAD_SAFE_METHOD_
+	DataAtSize *fds = const_cast<DynamicFontDataFallback *>(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) {

+ 2 - 0
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<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const override;
+
 	virtual ~DynamicFontDataFallback() override;
 };
 

+ 2 - 0
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<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const { return false; };
+
 	virtual ~FontDataFallback(){};
 };
 

+ 7 - 0
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<Vector3> &r_points, Vector<int32_t> &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;
 }

+ 2 - 0
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<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const override;
+
 	virtual float font_get_oversampling() const override;
 	virtual void font_set_oversampling(float p_oversampling) override;
 

+ 22 - 0
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<Vector3> points;
+	Vector<int32_t> 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<Vector2i> overrides;
 	for (int i = 0; i < p_override.size(); i++) {

+ 11 - 0
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<Vector3> &r_points, Vector<int32_t> &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