Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport TextMesh and expose dynamic font vector outlines #61281

Merged
merged 1 commit into from
May 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions doc/classes/Font.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@
Returns the font ascent (number of pixels above the baseline).
</description>
</method>
<method name="get_char_contours" qualifiers="const">
<return type="Dictionary" />
<argument index="0" name="char" type="int" />
<argument index="1" name="next" type="int" default="0" />
<description>
Returns outline contours of the glyph as a [code]Dictionary[/code] with the following contents:
[code]points[/code] - [PoolVector3Array], 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] - [PoolIntArray], 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="get_char_size" qualifiers="const">
<return type="Vector2" />
<argument index="0" name="char" type="int" />
Expand Down Expand Up @@ -142,5 +153,14 @@
</method>
</methods>
<constants>
<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>
49 changes: 49 additions & 0 deletions doc/classes/TextMesh.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="TextMesh" inherits="PrimitiveMesh" version="3.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Generate an [PrimitiveMesh] from the text.
</brief_description>
<description>
Generate an [PrimitiveMesh] from the text.
TextMesh can be generated only when using dynamic fonts with vector glyph contours. Bitmap fonts (including bitmap data in the TrueType/OpenType containers, like color emoji fonts) are not supported.
The UV layout is arranged in 4 horizontal strips, top to bottom: 40% of the height for the front face, 40% for the back face, 10% for the outer edges and 10% for the inner edges.
</description>
<tutorials>
</tutorials>
<methods>
</methods>
<members>
<member name="curve_step" type="float" setter="set_curve_step" getter="get_curve_step" default="0.5">
Step (in pixels) used to approximate Bézier curves.
</member>
<member name="depth" type="float" setter="set_depth" getter="get_depth" default="0.05">
Depths of the mesh, if set to [code]0.0[/code] only front surface, is generated, and UV layout is changed to use full texture for the front face only.
</member>
<member name="font" type="Font" setter="set_font" getter="get_font">
[Font] used for the [TextMesh]'s text.
</member>
<member name="horizontal_alignment" type="int" setter="set_horizontal_alignment" getter="get_horizontal_alignment" enum="TextMesh.Align" default="1">
Controls the text's horizontal alignment. Supports left, center and right. Set it to one of the [enum Align] constants.
</member>
<member name="pixel_size" type="float" setter="set_pixel_size" getter="get_pixel_size" default="0.01">
The size of one pixel's width on the text to scale it in 3D.
</member>
<member name="text" type="String" setter="set_text" getter="get_text" default="&quot;&quot;">
The text to generate mesh from.
</member>
<member name="uppercase" type="bool" setter="set_uppercase" getter="is_uppercase" default="false">
If [code]true[/code], all the text displays as UPPERCASE.
</member>
</members>
<constants>
<constant name="ALIGN_LEFT" value="0" enum="Align">
Align rows to the left (default).
</constant>
<constant name="ALIGN_CENTER" value="1" enum="Align">
Align rows centered.
</constant>
<constant name="ALIGN_RIGHT" value="2" enum="Align">
Align rows to the right.
</constant>
</constants>
</class>
1 change: 1 addition & 0 deletions editor/icons/icon_text_mesh.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions scene/register_scene_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,7 @@ void register_scene_types() {
ClassDB::register_class<PrismMesh>();
ClassDB::register_class<QuadMesh>();
ClassDB::register_class<SphereMesh>();
ClassDB::register_class<TextMesh>();
ClassDB::register_class<PointMesh>();
ClassDB::register_virtual_class<Material>();
ClassDB::register_class<SpatialMaterial>();
Expand Down
53 changes: 53 additions & 0 deletions scene/resources/dynamic_font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,51 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT
return advance;
}

Dictionary DynamicFontAtSize::get_char_contours(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const {
if (!valid) {
return Dictionary();
}

int32_t c = p_char;
if (((p_char & 0xfffffc00) == 0xd800) && (p_next & 0xfffffc00) == 0xdc00) { // decode surrogate pair.
c = (p_char << 10UL) + p_next - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
}
if ((p_char & 0xfffffc00) == 0xdc00) { // skip trail surrogate.
return Dictionary();
}

const_cast<DynamicFontAtSize *>(this)->_update_char(c);

Pair<const Character *, DynamicFontAtSize *> char_pair_with_font = _find_char_with_font(c, p_fallbacks);
const Character *ch = char_pair_with_font.first;
DynamicFontAtSize *font = char_pair_with_font.second;

if (ch->found) {
PoolVector3Array points;
PoolIntArray contours;

int error = FT_Load_Char(font->face, c, FT_LOAD_NO_BITMAP | (font->font->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0));
ERR_FAIL_COND_V(error, Dictionary());

double scale = (1.0 / 64.0) / oversampling * scale_color_font;
for (short i = 0; i < font->face->glyph->outline.n_points; i++) {
points.push_back(Vector3(font->face->glyph->outline.points[i].x * scale, -font->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(font->face->glyph->outline.tags[i])));
}
for (short i = 0; i < font->face->glyph->outline.n_contours; i++) {
contours.push_back(font->face->glyph->outline.contours[i]);
}
bool orientation = (FT_Outline_Get_Orientation(&font->face->glyph->outline) == FT_ORIENTATION_FILL_RIGHT);

Dictionary out;
out["points"] = points;
out["contours"] = contours;
out["orientation"] = orientation;
return out;
} else {
return Dictionary();
}
}

DynamicFontAtSize::Character DynamicFontAtSize::Character::not_found() {
Character ch;
ch.texture_idx = -1;
Expand Down Expand Up @@ -1178,6 +1223,14 @@ float DynamicFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_
}
}

Dictionary DynamicFont::get_char_contours(CharType p_char, CharType p_next) const {
if (!data_at_size.is_valid()) {
return Dictionary();
}

return data_at_size->get_char_contours(p_char, p_next, fallback_data_at_size);
}

void DynamicFont::set_fallback(int p_idx, const Ref<DynamicFontData> &p_data) {
ERR_FAIL_COND(p_data.is_null());
ERR_FAIL_INDEX(p_idx, fallbacks.size());
Expand Down
4 changes: 4 additions & 0 deletions scene/resources/dynamic_font.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ class DynamicFontAtSize : public Reference {
void set_texture_flags(uint32_t p_flags);
void update_oversampling();

Dictionary get_char_contours(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const;

DynamicFontAtSize();
~DynamicFontAtSize();
};
Expand Down Expand Up @@ -300,6 +302,8 @@ class DynamicFont : public Font {
Size2 get_char_tx_size(CharType p_char, CharType p_next, bool p_outline) const;
Rect2 get_char_tx_uv_rect(CharType p_char, CharType p_next, bool p_outline) const;

Dictionary get_char_contours(CharType p_char, CharType p_next) const;

SelfList<DynamicFont> font_list;

static Mutex dynamic_font_mutex;
Expand Down
5 changes: 5 additions & 0 deletions scene/resources/font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ void Font::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_char_tx_uv_rect", "char", "next", "outline"), &Font::get_char_tx_uv_rect, DEFVAL(0), DEFVAL(false));

ClassDB::bind_method(D_METHOD("update_changes"), &Font::update_changes);
ClassDB::bind_method(D_METHOD("get_char_contours", "char", "next"), &Font::get_char_contours, DEFVAL(0));

BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_ON);
BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_OFF_CONIC);
BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_OFF_CUBIC);
}

Font::Font() {
Expand Down
10 changes: 10 additions & 0 deletions scene/resources/font.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ class Font : public Resource {
static void _bind_methods();

public:
enum ContourPointTag {
CONTOUR_CURVE_TAG_ON = 0x01,
CONTOUR_CURVE_TAG_OFF_CONIC = 0x00,
CONTOUR_CURVE_TAG_OFF_CUBIC = 0x02
};

virtual float get_height() const = 0;

virtual float get_ascent() const = 0;
Expand All @@ -66,6 +72,8 @@ class Font : public Resource {
virtual Size2 get_char_tx_size(CharType p_char, CharType p_next, bool p_outline) const = 0;
virtual Rect2 get_char_tx_uv_rect(CharType p_char, CharType p_next, bool p_outline) const = 0;

virtual Dictionary get_char_contours(CharType p_char, CharType p_next = 0) const { return Dictionary(); }

void update_changes();
Font();
};
Expand Down Expand Up @@ -216,4 +224,6 @@ class ResourceFormatLoaderBMFont : public ResourceFormatLoader {
virtual String get_resource_type(const String &p_path) const;
};

VARIANT_ENUM_CAST(Font::ContourPointTag);

#endif
Loading