Add options to embolden and transform font outlines to simulate bold and italic typefaces.

This commit is contained in:
bruvzg 2022-03-11 09:31:16 +02:00
parent 1e099afc8a
commit b32e8d63d8
No known key found for this signature in database
GPG Key ID: 7960FCF39844EC38
17 changed files with 364 additions and 25 deletions

View File

@ -567,6 +567,9 @@
<member name="data" type="PackedByteArray" setter="set_data" getter="get_data" default="PackedByteArray()"> <member name="data" type="PackedByteArray" setter="set_data" getter="get_data" default="PackedByteArray()">
Contents of the dynamic font source file. Contents of the dynamic font source file.
</member> </member>
<member name="embolden" type="float" setter="set_embolden" getter="get_embolden" default="0.0">
If is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
</member>
<member name="fixed_size" type="int" setter="set_fixed_size" getter="get_fixed_size" default="0"> <member name="fixed_size" type="int" setter="set_fixed_size" getter="get_fixed_size" default="0">
Font size, used only for the bitmap fonts. Font size, used only for the bitmap fonts.
</member> </member>
@ -603,5 +606,9 @@
<member name="subpixel_positioning" type="int" setter="set_subpixel_positioning" getter="get_subpixel_positioning" enum="TextServer.SubpixelPositioning" default="1"> <member name="subpixel_positioning" type="int" setter="set_subpixel_positioning" getter="get_subpixel_positioning" enum="TextServer.SubpixelPositioning" default="1">
Font glyph sub-pixel positioning mode. Subpixel positioning provides shaper text and better kerning for smaller font sizes, at the cost of memory usage and font rasterization speed. Use [constant TextServer.SUBPIXEL_POSITIONING_AUTO] to automatically enable it based on the font size. Font glyph sub-pixel positioning mode. Subpixel positioning provides shaper text and better kerning for smaller font sizes, at the cost of memory usage and font rasterization speed. Use [constant TextServer.SUBPIXEL_POSITIONING_AUTO] to automatically enable it based on the font size.
</member> </member>
<member name="transform" type="Transform2D" setter="set_transform" getter="get_transform" default="Transform2D(1, 0, 0, 1, 0, 0)">
2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs.
For example, to simulate italic typeface by slanting, apply the following transform [code]Transform2D(1.0, slant, 0.0, 1.0, 0.0, 0.0)[/code].
</member>
</members> </members>
</class> </class>

View File

@ -112,6 +112,13 @@
Returns the font descent (number of pixels below the baseline). Returns the font descent (number of pixels below the baseline).
</description> </description>
</method> </method>
<method name="font_get_embolden" qualifiers="const">
<return type="float" />
<argument index="0" name="font_rid" type="RID" />
<description>
Returns font embolden strength.
</description>
</method>
<method name="font_get_fixed_size" qualifiers="const"> <method name="font_get_fixed_size" qualifiers="const">
<return type="int" /> <return type="int" />
<argument index="0" name="font_rid" type="RID" /> <argument index="0" name="font_rid" type="RID" />
@ -368,6 +375,13 @@
Returns array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty. Returns array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty.
</description> </description>
</method> </method>
<method name="font_get_transform" qualifiers="const">
<return type="Transform2D" />
<argument index="0" name="font_rid" type="RID" />
<description>
Returns 2D transform applied to the font outlines.
</description>
</method>
<method name="font_get_underline_position" qualifiers="const"> <method name="font_get_underline_position" qualifiers="const">
<return type="float" /> <return type="float" />
<argument index="0" name="font_rid" type="RID" /> <argument index="0" name="font_rid" type="RID" />
@ -542,6 +556,14 @@
Sets the font descent (number of pixels below the baseline). Sets the font descent (number of pixels below the baseline).
</description> </description>
</method> </method>
<method name="font_set_embolden">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
<argument index="1" name="strength" type="float" />
<description>
Sets font embolden strength. If [code]strength[/code] is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
</description>
</method>
<method name="font_set_fixed_size"> <method name="font_set_fixed_size">
<return type="void" /> <return type="void" />
<argument index="0" name="font_rid" type="RID" /> <argument index="0" name="font_rid" type="RID" />
@ -765,6 +787,15 @@
Sets array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty. Sets array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty.
</description> </description>
</method> </method>
<method name="font_set_transform">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
<argument index="1" name="transform" type="Transform2D" />
<description>
Sets 2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs.
For example, to simulate italic typeface by slanting, apply the following transform [code]Transform2D(1.0, slant, 0.0, 1.0, 0.0, 0.0)[/code].
</description>
</method>
<method name="font_set_underline_position"> <method name="font_set_underline_position">
<return type="void" /> <return type="void" />
<argument index="0" name="font_rid" type="RID" /> <argument index="0" name="font_rid" type="RID" />

View File

@ -112,6 +112,13 @@
Returns the font descent (number of pixels below the baseline). Returns the font descent (number of pixels below the baseline).
</description> </description>
</method> </method>
<method name="_font_get_embolden" qualifiers="virtual const">
<return type="float" />
<argument index="0" name="font_rid" type="RID" />
<description>
Returns font embolden strength.
</description>
</method>
<method name="_font_get_fixed_size" qualifiers="virtual const"> <method name="_font_get_fixed_size" qualifiers="virtual const">
<return type="int" /> <return type="int" />
<argument index="0" name="font_rid" type="RID" /> <argument index="0" name="font_rid" type="RID" />
@ -368,6 +375,13 @@
Returns array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty. Returns array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty.
</description> </description>
</method> </method>
<method name="_font_get_transform" qualifiers="virtual const">
<return type="Transform2D" />
<argument index="0" name="font_rid" type="RID" />
<description>
Retruns 2D transform applied to the font outlines.
</description>
</method>
<method name="_font_get_underline_position" qualifiers="virtual const"> <method name="_font_get_underline_position" qualifiers="virtual const">
<return type="float" /> <return type="float" />
<argument index="0" name="font_rid" type="RID" /> <argument index="0" name="font_rid" type="RID" />
@ -551,6 +565,14 @@
Sets bitmap font fixed size. If set to value greater than zero, same cache entry will be used for all font sizes. Sets bitmap font fixed size. If set to value greater than zero, same cache entry will be used for all font sizes.
</description> </description>
</method> </method>
<method name="_font_set_embolden" qualifiers="virtual">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
<argument index="1" name="strength" type="float" />
<description>
Sets font embolden strength. If [code]strength[/code] is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
</description>
</method>
<method name="_font_set_fixed_size" qualifiers="virtual"> <method name="_font_set_fixed_size" qualifiers="virtual">
<return type="void" /> <return type="void" />
<argument index="0" name="font_rid" type="RID" /> <argument index="0" name="font_rid" type="RID" />
@ -773,6 +795,15 @@
Sets array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty. Sets array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty.
</description> </description>
</method> </method>
<method name="_font_set_transform" qualifiers="virtual">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
<argument index="1" name="transform" type="Transform2D" />
<description>
Sets 2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs.
For example, to simulate italic typeface by slanting, apply the following transform [code]Transform2D(1.0, slant, 0.0, 1.0, 0.0, 0.0)[/code].
</description>
</method>
<method name="_font_set_underline_position" qualifiers="virtual"> <method name="_font_set_underline_position" qualifiers="virtual">
<return type="void" /> <return type="void" />
<argument index="0" name="font_rid" type="RID" /> <argument index="0" name="font_rid" type="RID" />

View File

@ -484,6 +484,14 @@ void DynamicFontImportSettings::_main_prop_changed(const String &p_edited_proper
if (font_preview->get_data_count() > 0) { if (font_preview->get_data_count() > 0) {
font_preview->get_data(0)->set_subpixel_positioning((TextServer::SubpixelPositioning)import_settings_data->get("subpixel_positioning").operator int()); font_preview->get_data(0)->set_subpixel_positioning((TextServer::SubpixelPositioning)import_settings_data->get("subpixel_positioning").operator int());
} }
} else if (p_edited_property == "embolden") {
if (font_preview->get_data_count() > 0) {
font_preview->get_data(0)->set_embolden(import_settings_data->get("embolden"));
}
} else if (p_edited_property == "transform") {
if (font_preview->get_data_count() > 0) {
font_preview->get_data(0)->set_transform(import_settings_data->get("transform"));
}
} else if (p_edited_property == "oversampling") { } else if (p_edited_property == "oversampling") {
if (font_preview->get_data_count() > 0) { if (font_preview->get_data_count() > 0) {
font_preview->get_data(0)->set_oversampling(import_settings_data->get("oversampling")); font_preview->get_data(0)->set_oversampling(import_settings_data->get("oversampling"));
@ -924,6 +932,8 @@ void DynamicFontImportSettings::_re_import() {
main_settings["force_autohinter"] = import_settings_data->get("force_autohinter"); main_settings["force_autohinter"] = import_settings_data->get("force_autohinter");
main_settings["hinting"] = import_settings_data->get("hinting"); main_settings["hinting"] = import_settings_data->get("hinting");
main_settings["subpixel_positioning"] = import_settings_data->get("subpixel_positioning"); main_settings["subpixel_positioning"] = import_settings_data->get("subpixel_positioning");
main_settings["embolden"] = import_settings_data->get("embolden");
main_settings["transform"] = import_settings_data->get("transform");
main_settings["oversampling"] = import_settings_data->get("oversampling"); main_settings["oversampling"] = import_settings_data->get("oversampling");
main_settings["compress"] = import_settings_data->get("compress"); main_settings["compress"] = import_settings_data->get("compress");
@ -1275,6 +1285,8 @@ void DynamicFontImportSettings::open_settings(const String &p_path) {
font_preview->get_data(0)->set_force_autohinter(import_settings_data->get("force_autohinter")); font_preview->get_data(0)->set_force_autohinter(import_settings_data->get("force_autohinter"));
font_preview->get_data(0)->set_hinting((TextServer::Hinting)import_settings_data->get("hinting").operator int()); font_preview->get_data(0)->set_hinting((TextServer::Hinting)import_settings_data->get("hinting").operator int());
font_preview->get_data(0)->set_subpixel_positioning((TextServer::SubpixelPositioning)import_settings_data->get("subpixel_positioning").operator int()); font_preview->get_data(0)->set_subpixel_positioning((TextServer::SubpixelPositioning)import_settings_data->get("subpixel_positioning").operator int());
font_preview->get_data(0)->set_embolden(import_settings_data->get("embolden"));
font_preview->get_data(0)->set_transform(import_settings_data->get("transform"));
font_preview->get_data(0)->set_oversampling(import_settings_data->get("oversampling")); font_preview->get_data(0)->set_oversampling(import_settings_data->get("oversampling"));
} }
font_preview_label->add_theme_font_override("font", font_preview); font_preview_label->add_theme_font_override("font", font_preview);
@ -1334,6 +1346,8 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "force_autohinter"), false)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "force_autohinter"), false));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), 1)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), 1));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), 1)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), 1));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::FLOAT, "embolden", PROPERTY_HINT_RANGE, "-2,2,0.01"), 0.f));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::TRANSFORM2D, "transform"), Transform2D()));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), 0.0)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), 0.0));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "compress", PROPERTY_HINT_NONE, ""), false)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "compress", PROPERTY_HINT_NONE, ""), false));

View File

@ -109,6 +109,8 @@ void ResourceImporterDynamicFont::get_import_options(const String &p_path, List<
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force_autohinter"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force_autohinter"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), 1)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), 1));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), 1)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), 1));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "embolden", PROPERTY_HINT_RANGE, "-2,2,0.01"), 0.f));
r_options->push_back(ImportOption(PropertyInfo(Variant::TRANSFORM2D, "transform"), Transform2D()));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), 0.0)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), 0.0));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true));
@ -186,6 +188,8 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str
int hinting = p_options["hinting"]; int hinting = p_options["hinting"];
int subpixel_positioning = p_options["subpixel_positioning"]; int subpixel_positioning = p_options["subpixel_positioning"];
real_t oversampling = p_options["oversampling"]; real_t oversampling = p_options["oversampling"];
real_t embolden = p_options["embolden"];
Transform2D transform = p_options["transform"];
// Load base font data. // Load base font data.
Vector<uint8_t> data = FileAccess::get_file_as_array(p_source_file); Vector<uint8_t> data = FileAccess::get_file_as_array(p_source_file);
@ -202,6 +206,8 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str
font->set_fixed_size(0); font->set_fixed_size(0);
font->set_force_autohinter(autohinter); font->set_force_autohinter(autohinter);
font->set_subpixel_positioning((TextServer::SubpixelPositioning)subpixel_positioning); font->set_subpixel_positioning((TextServer::SubpixelPositioning)subpixel_positioning);
font->set_embolden(embolden);
font->set_transform(transform);
font->set_hinting((TextServer::Hinting)hinting); font->set_hinting((TextServer::Hinting)hinting);
font->set_oversampling(oversampling); font->set_oversampling(oversampling);

View File

@ -704,7 +704,7 @@ String TextServerAdvanced::tag_to_name(int32_t p_tag) const {
/* Font Glyph Rendering */ /* Font Glyph Rendering */
/*************************************************************************/ /*************************************************************************/
_FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height) const { _FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const {
FontTexturePosition ret; FontTexturePosition ret;
ret.index = -1; ret.index = -1;
@ -769,8 +769,11 @@ _FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_
} }
texsize = next_power_of_2(texsize); texsize = next_power_of_2(texsize);
if (p_msdf) {
texsize = MIN(texsize, 4096); texsize = MIN(texsize, 2048);
} else {
texsize = MIN(texsize, 1024);
}
FontTexture tex; FontTexture tex;
tex.texture_w = texsize; tex.texture_w = texsize;
@ -935,10 +938,10 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(
int mw = w + p_rect_margin * 2; int mw = w + p_rect_margin * 2;
int mh = h + p_rect_margin * 2; int mh = h + p_rect_margin * 2;
ERR_FAIL_COND_V(mw > 4096, FontGlyph()); ERR_FAIL_COND_V(mw > 1024, FontGlyph());
ERR_FAIL_COND_V(mh > 4096, FontGlyph()); ERR_FAIL_COND_V(mh > 1024, FontGlyph());
FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, 4, Image::FORMAT_RGBA8, mw, mh); FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, 4, Image::FORMAT_RGBA8, mw, mh, true);
ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph()); ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph());
FontTexture &tex = p_data->textures.write[tex_pos.index]; FontTexture &tex = p_data->textures.write[tex_pos.index];
@ -1013,13 +1016,13 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma
int mw = w + p_rect_margin * 2; int mw = w + p_rect_margin * 2;
int mh = h + p_rect_margin * 2; int mh = h + p_rect_margin * 2;
ERR_FAIL_COND_V(mw > 4096, FontGlyph()); ERR_FAIL_COND_V(mw > 1024, FontGlyph());
ERR_FAIL_COND_V(mh > 4096, FontGlyph()); ERR_FAIL_COND_V(mh > 1024, FontGlyph());
int color_size = bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2; int color_size = bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2;
Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8; Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8;
FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh); FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh, false);
ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph()); ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph());
// Fit character in char texture. // Fit character in char texture.
@ -1155,6 +1158,16 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontDataAdvanced *p_font_d
} }
} }
if (p_font_data->embolden != 0.f) {
FT_Pos strength = p_font_data->embolden * p_size.x * 4; // 26.6 fractional units (1 / 64).
FT_Outline_Embolden(&fd->face->glyph->outline, strength);
}
if (p_font_data->transform != Transform2D()) {
FT_Matrix mat = { FT_Fixed(p_font_data->transform[0][0] * 65536), FT_Fixed(p_font_data->transform[0][1] * 65536), FT_Fixed(p_font_data->transform[1][0] * 65536), FT_Fixed(p_font_data->transform[1][1] * 65536) }; // 16.16 fractional units (1 / 65536).
FT_Outline_Transform(&fd->face->glyph->outline, &mat);
}
if (!outline) { if (!outline) {
if (!p_font_data->msdf) { if (!p_font_data->msdf) {
error = FT_Render_Glyph(fd->face->glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO); error = FT_Render_Glyph(fd->face->glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);
@ -1874,6 +1887,44 @@ TextServer::SubpixelPositioning TextServerAdvanced::font_get_subpixel_positionin
return fd->subpixel_positioning; return fd->subpixel_positioning;
} }
void TextServerAdvanced::font_set_embolden(RID p_font_rid, float p_strength) {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
if (fd->embolden != p_strength) {
_font_clear_cache(fd);
fd->embolden = p_strength;
}
}
float TextServerAdvanced::font_get_embolden(RID p_font_rid) const {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.f);
MutexLock lock(fd->mutex);
return fd->embolden;
}
void TextServerAdvanced::font_set_transform(RID p_font_rid, Transform2D p_transform) {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
if (fd->transform != p_transform) {
_font_clear_cache(fd);
fd->transform = p_transform;
}
}
Transform2D TextServerAdvanced::font_get_transform(RID p_font_rid) const {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Transform2D());
MutexLock lock(fd->mutex);
return fd->transform;
}
void TextServerAdvanced::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) { void TextServerAdvanced::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);

View File

@ -177,6 +177,8 @@ class TextServerAdvanced : public TextServer {
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO; TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
Dictionary variation_coordinates; Dictionary variation_coordinates;
float oversampling = 0.f; float oversampling = 0.f;
float embolden = 0.f;
Transform2D transform;
uint32_t style_flags = 0; uint32_t style_flags = 0;
String font_name; String font_name;
@ -208,7 +210,7 @@ class TextServerAdvanced : public TextServer {
} }
}; };
_FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height) const; _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const;
#ifdef MODULE_MSDFGEN_ENABLED #ifdef MODULE_MSDFGEN_ENABLED
_FORCE_INLINE_ FontGlyph rasterize_msdf(FontDataAdvanced *p_font_data, FontDataForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const; _FORCE_INLINE_ FontGlyph rasterize_msdf(FontDataAdvanced *p_font_data, FontDataForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const;
#endif #endif
@ -383,6 +385,12 @@ public:
virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) override; virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) override;
virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const override; virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const override;
virtual void font_set_embolden(RID p_font_rid, float p_strength) override;
virtual float font_get_embolden(RID p_font_rid) const override;
virtual void font_set_transform(RID p_font_rid, Transform2D p_transform) override;
virtual Transform2D font_get_transform(RID p_font_rid) const override;
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override; virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override;
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override; virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override;

View File

@ -155,7 +155,7 @@ String TextServerFallback::tag_to_name(int32_t p_tag) const {
/* Font Glyph Rendering */ /* Font Glyph Rendering */
/*************************************************************************/ /*************************************************************************/
_FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height) const { _FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const {
FontTexturePosition ret; FontTexturePosition ret;
ret.index = -1; ret.index = -1;
@ -221,7 +221,11 @@ _FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_
texsize = next_power_of_2(texsize); texsize = next_power_of_2(texsize);
texsize = MIN(texsize, 4096); if (p_msdf) {
texsize = MIN(texsize, 2048);
} else {
texsize = MIN(texsize, 1024);
}
FontTexture tex; FontTexture tex;
tex.texture_w = texsize; tex.texture_w = texsize;
@ -386,10 +390,10 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(
int mw = w + p_rect_margin * 2; int mw = w + p_rect_margin * 2;
int mh = h + p_rect_margin * 2; int mh = h + p_rect_margin * 2;
ERR_FAIL_COND_V(mw > 4096, FontGlyph()); ERR_FAIL_COND_V(mw > 1024, FontGlyph());
ERR_FAIL_COND_V(mh > 4096, FontGlyph()); ERR_FAIL_COND_V(mh > 1024, FontGlyph());
FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, 4, Image::FORMAT_RGBA8, mw, mh); FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, 4, Image::FORMAT_RGBA8, mw, mh, true);
ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph()); ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph());
FontTexture &tex = p_data->textures.write[tex_pos.index]; FontTexture &tex = p_data->textures.write[tex_pos.index];
@ -464,13 +468,13 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma
int mw = w + p_rect_margin * 2; int mw = w + p_rect_margin * 2;
int mh = h + p_rect_margin * 2; int mh = h + p_rect_margin * 2;
ERR_FAIL_COND_V(mw > 4096, FontGlyph()); ERR_FAIL_COND_V(mw > 1024, FontGlyph());
ERR_FAIL_COND_V(mh > 4096, FontGlyph()); ERR_FAIL_COND_V(mh > 1024, FontGlyph());
int color_size = bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2; int color_size = bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2;
Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8; Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8;
FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh); FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh, false);
ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph()); ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph());
// Fit character in char texture. // Fit character in char texture.
@ -586,6 +590,8 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontDataFallback *p_font_d
flags |= FT_LOAD_COLOR; flags |= FT_LOAD_COLOR;
} }
glyph_index = FT_Get_Char_Index(fd->face, glyph_index);
FT_Fixed v, h; FT_Fixed v, h;
FT_Get_Advance(fd->face, glyph_index, flags, &h); FT_Get_Advance(fd->face, glyph_index, flags, &h);
FT_Get_Advance(fd->face, glyph_index, flags | FT_LOAD_VERTICAL_LAYOUT, &v); FT_Get_Advance(fd->face, glyph_index, flags | FT_LOAD_VERTICAL_LAYOUT, &v);
@ -606,6 +612,16 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontDataFallback *p_font_d
} }
} }
if (p_font_data->embolden != 0.f) {
FT_Pos strength = p_font_data->embolden * p_size.x * 4; // 26.6 fractional units (1 / 64).
FT_Outline_Embolden(&fd->face->glyph->outline, strength);
}
if (p_font_data->transform != Transform2D()) {
FT_Matrix mat = { FT_Fixed(p_font_data->transform[0][0] * 65536), FT_Fixed(p_font_data->transform[0][1] * 65536), FT_Fixed(p_font_data->transform[1][0] * 65536), FT_Fixed(p_font_data->transform[1][1] * 65536) }; // 16.16 fractional units (1 / 65536).
FT_Outline_Transform(&fd->face->glyph->outline, &mat);
}
if (!outline) { if (!outline) {
if (!p_font_data->msdf) { if (!p_font_data->msdf) {
error = FT_Render_Glyph(fd->face->glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO); error = FT_Render_Glyph(fd->face->glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);
@ -1044,6 +1060,44 @@ TextServer::SubpixelPositioning TextServerFallback::font_get_subpixel_positionin
return fd->subpixel_positioning; return fd->subpixel_positioning;
} }
void TextServerFallback::font_set_embolden(RID p_font_rid, float p_strength) {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
if (fd->embolden != p_strength) {
_font_clear_cache(fd);
fd->embolden = p_strength;
}
}
float TextServerFallback::font_get_embolden(RID p_font_rid) const {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.f);
MutexLock lock(fd->mutex);
return fd->embolden;
}
void TextServerFallback::font_set_transform(RID p_font_rid, Transform2D p_transform) {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
if (fd->transform != p_transform) {
_font_clear_cache(fd);
fd->transform = p_transform;
}
}
Transform2D TextServerFallback::font_get_transform(RID p_font_rid) const {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Transform2D());
MutexLock lock(fd->mutex);
return fd->transform;
}
void TextServerFallback::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) { void TextServerFallback::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid); FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);

View File

@ -142,6 +142,8 @@ class TextServerFallback : public TextServer {
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO; TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
Dictionary variation_coordinates; Dictionary variation_coordinates;
float oversampling = 0.f; float oversampling = 0.f;
float embolden = 0.f;
Transform2D transform;
uint32_t style_flags = 0; uint32_t style_flags = 0;
String font_name; String font_name;
@ -172,7 +174,7 @@ class TextServerFallback : public TextServer {
} }
}; };
_FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height) const; _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const;
#ifdef MODULE_MSDFGEN_ENABLED #ifdef MODULE_MSDFGEN_ENABLED
_FORCE_INLINE_ FontGlyph rasterize_msdf(FontDataFallback *p_font_data, FontDataForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const; _FORCE_INLINE_ FontGlyph rasterize_msdf(FontDataFallback *p_font_data, FontDataForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const;
#endif #endif
@ -294,6 +296,12 @@ public:
virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) override; virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) override;
virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const override; virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const override;
virtual void font_set_embolden(RID p_font_rid, float p_strength) override;
virtual float font_get_embolden(RID p_font_rid) const override;
virtual void font_set_transform(RID p_font_rid, Transform2D p_transform) override;
virtual Transform2D font_get_transform(RID p_font_rid) const override;
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override; virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override;
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override; virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override;

View File

@ -103,7 +103,7 @@ static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margi
return style; return style;
} }
void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale) { void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale) {
scale = p_scale; scale = p_scale;
// Font colors // Font colors
@ -924,9 +924,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Te
theme->set_stylebox("normal", "RichTextLabel", make_empty_stylebox(0, 0, 0, 0)); theme->set_stylebox("normal", "RichTextLabel", make_empty_stylebox(0, 0, 0, 0));
theme->set_font("normal_font", "RichTextLabel", Ref<Font>()); theme->set_font("normal_font", "RichTextLabel", Ref<Font>());
theme->set_font("bold_font", "RichTextLabel", Ref<Font>()); theme->set_font("bold_font", "RichTextLabel", bold_font);
theme->set_font("italics_font", "RichTextLabel", Ref<Font>()); theme->set_font("italics_font", "RichTextLabel", italics_font);
theme->set_font("bold_italics_font", "RichTextLabel", Ref<Font>()); theme->set_font("bold_italics_font", "RichTextLabel", bold_italics_font);
theme->set_font("mono_font", "RichTextLabel", Ref<Font>()); theme->set_font("mono_font", "RichTextLabel", Ref<Font>());
theme->set_font_size("normal_font_size", "RichTextLabel", -1); theme->set_font_size("normal_font_size", "RichTextLabel", -1);
@ -1025,6 +1025,9 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos
Ref<StyleBox> default_style; Ref<StyleBox> default_style;
Ref<Texture2D> default_icon; Ref<Texture2D> default_icon;
Ref<Font> default_font; Ref<Font> default_font;
Ref<Font> bold_font;
Ref<Font> bold_italics_font;
Ref<Font> italics_font;
float default_scale = CLAMP(p_scale, 0.5, 8.0); float default_scale = CLAMP(p_scale, 0.5, 8.0);
if (p_font.is_valid()) { if (p_font.is_valid()) {
@ -1048,7 +1051,31 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos
default_font = dynamic_font; default_font = dynamic_font;
} }
fill_default_theme(t, default_font, default_icon, default_style, default_scale); if (default_font.is_valid()) {
bold_font.instantiate();
for (int i = 0; i < default_font->get_data_count(); i++) {
Ref<FontData> data = default_font->get_data(i)->duplicate();
data->set_embolden(1.2);
bold_font->add_data(data);
}
bold_italics_font.instantiate();
for (int i = 0; i < default_font->get_data_count(); i++) {
Ref<FontData> data = default_font->get_data(i)->duplicate();
data->set_embolden(1.2);
data->set_transform(Transform2D(1.0, 0.4, 0.0, 1.0, 0.0, 0.0));
bold_italics_font->add_data(data);
}
italics_font.instantiate();
for (int i = 0; i < default_font->get_data_count(); i++) {
Ref<FontData> data = default_font->get_data(i)->duplicate();
data->set_transform(Transform2D(1.0, 0.4, 0.0, 1.0, 0.0, 0.0));
italics_font->add_data(data);
}
}
fill_default_theme(t, default_font, bold_font, bold_italics_font, italics_font, default_icon, default_style, default_scale);
Theme::set_default(t); Theme::set_default(t);
Theme::set_fallback_base_scale(default_scale); Theme::set_fallback_base_scale(default_scale);

View File

@ -35,7 +35,7 @@
const int default_font_size = 16; const int default_font_size = 16;
void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale); void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale);
void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_subpixel, TextServer::Hinting p_hinting, bool p_aa); void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_subpixel, TextServer::Hinting p_hinting, bool p_aa);
void clear_default_theme(); void clear_default_theme();

View File

@ -61,6 +61,8 @@ _FORCE_INLINE_ void FontData::_ensure_rid(int p_cache_index) const {
TS->font_set_force_autohinter(cache[p_cache_index], force_autohinter); TS->font_set_force_autohinter(cache[p_cache_index], force_autohinter);
TS->font_set_hinting(cache[p_cache_index], hinting); TS->font_set_hinting(cache[p_cache_index], hinting);
TS->font_set_subpixel_positioning(cache[p_cache_index], subpixel_positioning); TS->font_set_subpixel_positioning(cache[p_cache_index], subpixel_positioning);
TS->font_set_embolden(cache[p_cache_index], embolden);
TS->font_set_transform(cache[p_cache_index], transform);
TS->font_set_oversampling(cache[p_cache_index], oversampling); TS->font_set_oversampling(cache[p_cache_index], oversampling);
} }
} }
@ -105,6 +107,12 @@ void FontData::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_subpixel_positioning", "subpixel_positioning"), &FontData::set_subpixel_positioning); ClassDB::bind_method(D_METHOD("set_subpixel_positioning", "subpixel_positioning"), &FontData::set_subpixel_positioning);
ClassDB::bind_method(D_METHOD("get_subpixel_positioning"), &FontData::get_subpixel_positioning); ClassDB::bind_method(D_METHOD("get_subpixel_positioning"), &FontData::get_subpixel_positioning);
ClassDB::bind_method(D_METHOD("set_embolden", "strength"), &FontData::set_embolden);
ClassDB::bind_method(D_METHOD("get_embolden"), &FontData::get_embolden);
ClassDB::bind_method(D_METHOD("set_transform", "transform"), &FontData::set_transform);
ClassDB::bind_method(D_METHOD("get_transform"), &FontData::get_transform);
ClassDB::bind_method(D_METHOD("set_oversampling", "oversampling"), &FontData::set_oversampling); ClassDB::bind_method(D_METHOD("set_oversampling", "oversampling"), &FontData::set_oversampling);
ClassDB::bind_method(D_METHOD("get_oversampling"), &FontData::get_oversampling); ClassDB::bind_method(D_METHOD("get_oversampling"), &FontData::get_oversampling);
@ -209,6 +217,8 @@ void FontData::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "style_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style_name", "get_font_style_name"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "style_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style_name", "get_font_style_name");
ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style", "get_font_style"); ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style", "get_font_style");
ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel", PROPERTY_USAGE_STORAGE), "set_subpixel_positioning", "get_subpixel_positioning"); ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel", PROPERTY_USAGE_STORAGE), "set_subpixel_positioning", "get_subpixel_positioning");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "embolden", PROPERTY_HINT_RANGE, "-2,2,0.01", PROPERTY_USAGE_STORAGE), "set_embolden", "get_embolden");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_transform", "get_transform");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_multichannel_signed_distance_field", "is_multichannel_signed_distance_field"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_multichannel_signed_distance_field", "is_multichannel_signed_distance_field");
ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_pixel_range", "get_msdf_pixel_range"); ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_pixel_range", "get_msdf_pixel_range");
ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_size", "get_msdf_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_size", "get_msdf_size");
@ -439,6 +449,8 @@ void FontData::reset_state() {
msdf_pixel_range = 14; msdf_pixel_range = 14;
msdf_size = 128; msdf_size = 128;
fixed_size = 0; fixed_size = 0;
embolden = 0.f;
transform = Transform2D();
oversampling = 0.f; oversampling = 0.f;
} }
@ -1385,6 +1397,36 @@ TextServer::SubpixelPositioning FontData::get_subpixel_positioning() const {
return subpixel_positioning; return subpixel_positioning;
} }
void FontData::set_embolden(float p_strength) {
if (embolden != p_strength) {
embolden = p_strength;
for (int i = 0; i < cache.size(); i++) {
_ensure_rid(i);
TS->font_set_embolden(cache[i], embolden);
}
emit_changed();
}
}
float FontData::get_embolden() const {
return embolden;
}
void FontData::set_transform(Transform2D p_transform) {
if (transform != p_transform) {
transform = p_transform;
for (int i = 0; i < cache.size(); i++) {
_ensure_rid(i);
TS->font_set_transform(cache[i], transform);
}
emit_changed();
}
}
Transform2D FontData::get_transform() const {
return transform;
}
void FontData::set_oversampling(real_t p_oversampling) { void FontData::set_oversampling(real_t p_oversampling) {
if (oversampling != p_oversampling) { if (oversampling != p_oversampling) {
oversampling = p_oversampling; oversampling = p_oversampling;

View File

@ -57,6 +57,8 @@ class FontData : public Resource {
TextServer::Hinting hinting = TextServer::HINTING_LIGHT; TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO; TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
real_t oversampling = 0.f; real_t oversampling = 0.f;
real_t embolden = 0.f;
Transform2D transform;
// Cache. // Cache.
mutable Vector<RID> cache; mutable Vector<RID> cache;
@ -122,6 +124,12 @@ public:
virtual void set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel); virtual void set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel);
virtual TextServer::SubpixelPositioning get_subpixel_positioning() const; virtual TextServer::SubpixelPositioning get_subpixel_positioning() const;
virtual void set_embolden(float p_strength);
virtual float get_embolden() const;
virtual void set_transform(Transform2D p_transform);
virtual Transform2D get_transform() const;
virtual void set_oversampling(real_t p_oversampling); virtual void set_oversampling(real_t p_oversampling);
virtual real_t get_oversampling() const; virtual real_t get_oversampling() const;

View File

@ -88,6 +88,12 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_font_set_subpixel_positioning, "font_rid", "subpixel_positioning"); GDVIRTUAL_BIND(_font_set_subpixel_positioning, "font_rid", "subpixel_positioning");
GDVIRTUAL_BIND(_font_get_subpixel_positioning, "font_rid"); GDVIRTUAL_BIND(_font_get_subpixel_positioning, "font_rid");
GDVIRTUAL_BIND(_font_set_embolden, "font_rid", "strength");
GDVIRTUAL_BIND(_font_get_embolden, "font_rid");
GDVIRTUAL_BIND(_font_set_transform, "font_rid", "transform");
GDVIRTUAL_BIND(_font_get_transform, "font_rid");
GDVIRTUAL_BIND(_font_set_variation_coordinates, "font_rid", "variation_coordinates"); GDVIRTUAL_BIND(_font_set_variation_coordinates, "font_rid", "variation_coordinates");
GDVIRTUAL_BIND(_font_get_variation_coordinates, "font_rid"); GDVIRTUAL_BIND(_font_get_variation_coordinates, "font_rid");
@ -527,6 +533,30 @@ TextServer::SubpixelPositioning TextServerExtension::font_get_subpixel_positioni
return TextServer::SubpixelPositioning::SUBPIXEL_POSITIONING_DISABLED; return TextServer::SubpixelPositioning::SUBPIXEL_POSITIONING_DISABLED;
} }
void TextServerExtension::font_set_embolden(RID p_font_rid, float p_strength) {
GDVIRTUAL_CALL(_font_set_embolden, p_font_rid, p_strength);
}
float TextServerExtension::font_get_embolden(RID p_font_rid) const {
float ret;
if (GDVIRTUAL_CALL(_font_get_embolden, p_font_rid, ret)) {
return ret;
}
return 0.f;
}
void TextServerExtension::font_set_transform(RID p_font_rid, Transform2D p_transform) {
GDVIRTUAL_CALL(_font_set_transform, p_font_rid, p_transform);
}
Transform2D TextServerExtension::font_get_transform(RID p_font_rid) const {
Transform2D ret;
if (GDVIRTUAL_CALL(_font_get_transform, p_font_rid, ret)) {
return ret;
}
return Transform2D();
}
void TextServerExtension::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) { void TextServerExtension::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) {
GDVIRTUAL_CALL(_font_set_variation_coordinates, p_font_rid, p_variation_coordinates); GDVIRTUAL_CALL(_font_set_variation_coordinates, p_font_rid, p_variation_coordinates);
} }

View File

@ -139,6 +139,16 @@ public:
GDVIRTUAL2(_font_set_subpixel_positioning, RID, SubpixelPositioning); GDVIRTUAL2(_font_set_subpixel_positioning, RID, SubpixelPositioning);
GDVIRTUAL1RC(SubpixelPositioning, _font_get_subpixel_positioning, RID); GDVIRTUAL1RC(SubpixelPositioning, _font_get_subpixel_positioning, RID);
virtual void font_set_embolden(RID p_font_rid, float p_strength) override;
virtual float font_get_embolden(RID p_font_rid) const override;
GDVIRTUAL2(_font_set_embolden, RID, float);
GDVIRTUAL1RC(float, _font_get_embolden, RID);
virtual void font_set_transform(RID p_font_rid, Transform2D p_transform) override;
virtual Transform2D font_get_transform(RID p_font_rid) const override;
GDVIRTUAL2(_font_set_transform, RID, Transform2D);
GDVIRTUAL1RC(Transform2D, _font_get_transform, RID);
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override; virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override;
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override; virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override;
GDVIRTUAL2(_font_set_variation_coordinates, RID, Dictionary); GDVIRTUAL2(_font_set_variation_coordinates, RID, Dictionary);

View File

@ -241,6 +241,12 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_subpixel_positioning", "font_rid", "subpixel_positioning"), &TextServer::font_set_subpixel_positioning); ClassDB::bind_method(D_METHOD("font_set_subpixel_positioning", "font_rid", "subpixel_positioning"), &TextServer::font_set_subpixel_positioning);
ClassDB::bind_method(D_METHOD("font_get_subpixel_positioning", "font_rid"), &TextServer::font_get_subpixel_positioning); ClassDB::bind_method(D_METHOD("font_get_subpixel_positioning", "font_rid"), &TextServer::font_get_subpixel_positioning);
ClassDB::bind_method(D_METHOD("font_set_embolden", "font_rid", "strength"), &TextServer::font_set_embolden);
ClassDB::bind_method(D_METHOD("font_get_embolden", "font_rid"), &TextServer::font_get_embolden);
ClassDB::bind_method(D_METHOD("font_set_transform", "font_rid", "transform"), &TextServer::font_set_transform);
ClassDB::bind_method(D_METHOD("font_get_transform", "font_rid"), &TextServer::font_get_transform);
ClassDB::bind_method(D_METHOD("font_set_variation_coordinates", "font_rid", "variation_coordinates"), &TextServer::font_set_variation_coordinates); ClassDB::bind_method(D_METHOD("font_set_variation_coordinates", "font_rid", "variation_coordinates"), &TextServer::font_set_variation_coordinates);
ClassDB::bind_method(D_METHOD("font_get_variation_coordinates", "font_rid"), &TextServer::font_get_variation_coordinates); ClassDB::bind_method(D_METHOD("font_get_variation_coordinates", "font_rid"), &TextServer::font_get_variation_coordinates);

View File

@ -261,6 +261,12 @@ public:
virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) = 0; virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) = 0;
virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const = 0; virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const = 0;
virtual void font_set_embolden(RID p_font_rid, float p_strength) = 0;
virtual float font_get_embolden(RID p_font_rid) const = 0;
virtual void font_set_transform(RID p_font_rid, Transform2D p_transform) = 0;
virtual Transform2D font_get_transform(RID p_font_rid) const = 0;
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) = 0; virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) = 0;
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const = 0; virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const = 0;