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()">
Contents of the dynamic font source file.
</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">
Font size, used only for the bitmap fonts.
</member>
@ -603,5 +606,9 @@
<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.
</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>
</class>

View File

@ -112,6 +112,13 @@
Returns the font descent (number of pixels below the baseline).
</description>
</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">
<return type="int" />
<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.
</description>
</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">
<return type="float" />
<argument index="0" name="font_rid" type="RID" />
@ -542,6 +556,14 @@
Sets the font descent (number of pixels below the baseline).
</description>
</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">
<return type="void" />
<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.
</description>
</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">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />

View File

@ -112,6 +112,13 @@
Returns the font descent (number of pixels below the baseline).
</description>
</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">
<return type="int" />
<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.
</description>
</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">
<return type="float" />
<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.
</description>
</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">
<return type="void" />
<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.
</description>
</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">
<return type="void" />
<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) {
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") {
if (font_preview->get_data_count() > 0) {
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["hinting"] = import_settings_data->get("hinting");
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["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_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_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_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::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::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::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::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::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::BOOL, "compress"), true));
@ -186,6 +188,8 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str
int hinting = p_options["hinting"];
int subpixel_positioning = p_options["subpixel_positioning"];
real_t oversampling = p_options["oversampling"];
real_t embolden = p_options["embolden"];
Transform2D transform = p_options["transform"];
// Load base font data.
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_force_autohinter(autohinter);
font->set_subpixel_positioning((TextServer::SubpixelPositioning)subpixel_positioning);
font->set_embolden(embolden);
font->set_transform(transform);
font->set_hinting((TextServer::Hinting)hinting);
font->set_oversampling(oversampling);

View File

@ -704,7 +704,7 @@ String TextServerAdvanced::tag_to_name(int32_t p_tag) const {
/* 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;
ret.index = -1;
@ -769,8 +769,11 @@ _FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_
}
texsize = next_power_of_2(texsize);
texsize = MIN(texsize, 4096);
if (p_msdf) {
texsize = MIN(texsize, 2048);
} else {
texsize = MIN(texsize, 1024);
}
FontTexture tex;
tex.texture_w = texsize;
@ -935,10 +938,10 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(
int mw = w + p_rect_margin * 2;
int mh = h + p_rect_margin * 2;
ERR_FAIL_COND_V(mw > 4096, FontGlyph());
ERR_FAIL_COND_V(mh > 4096, FontGlyph());
ERR_FAIL_COND_V(mw > 1024, 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());
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 mh = h + p_rect_margin * 2;
ERR_FAIL_COND_V(mw > 4096, FontGlyph());
ERR_FAIL_COND_V(mh > 4096, FontGlyph());
ERR_FAIL_COND_V(mw > 1024, FontGlyph());
ERR_FAIL_COND_V(mh > 1024, FontGlyph());
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;
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());
// 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 (!p_font_data->msdf) {
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;
}
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) {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);

View File

@ -177,6 +177,8 @@ class TextServerAdvanced : public TextServer {
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
Dictionary variation_coordinates;
float oversampling = 0.f;
float embolden = 0.f;
Transform2D transform;
uint32_t style_flags = 0;
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
_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
@ -383,6 +385,12 @@ public:
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 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 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 */
/*************************************************************************/
_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;
ret.index = -1;
@ -221,7 +221,11 @@ _FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_
texsize = next_power_of_2(texsize);
texsize = MIN(texsize, 4096);
if (p_msdf) {
texsize = MIN(texsize, 2048);
} else {
texsize = MIN(texsize, 1024);
}
FontTexture tex;
tex.texture_w = texsize;
@ -386,10 +390,10 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(
int mw = w + p_rect_margin * 2;
int mh = h + p_rect_margin * 2;
ERR_FAIL_COND_V(mw > 4096, FontGlyph());
ERR_FAIL_COND_V(mh > 4096, FontGlyph());
ERR_FAIL_COND_V(mw > 1024, 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());
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 mh = h + p_rect_margin * 2;
ERR_FAIL_COND_V(mw > 4096, FontGlyph());
ERR_FAIL_COND_V(mh > 4096, FontGlyph());
ERR_FAIL_COND_V(mw > 1024, FontGlyph());
ERR_FAIL_COND_V(mh > 1024, FontGlyph());
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;
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());
// Fit character in char texture.
@ -586,6 +590,8 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontDataFallback *p_font_d
flags |= FT_LOAD_COLOR;
}
glyph_index = FT_Get_Char_Index(fd->face, glyph_index);
FT_Fixed v, h;
FT_Get_Advance(fd->face, glyph_index, flags, &h);
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 (!p_font_data->msdf) {
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;
}
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) {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);

View File

@ -142,6 +142,8 @@ class TextServerFallback : public TextServer {
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
Dictionary variation_coordinates;
float oversampling = 0.f;
float embolden = 0.f;
Transform2D transform;
uint32_t style_flags = 0;
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
_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
@ -294,6 +296,12 @@ public:
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 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 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;
}
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;
// 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_font("normal_font", "RichTextLabel", Ref<Font>());
theme->set_font("bold_font", "RichTextLabel", Ref<Font>());
theme->set_font("italics_font", "RichTextLabel", Ref<Font>());
theme->set_font("bold_italics_font", "RichTextLabel", Ref<Font>());
theme->set_font("bold_font", "RichTextLabel", bold_font);
theme->set_font("italics_font", "RichTextLabel", italics_font);
theme->set_font("bold_italics_font", "RichTextLabel", bold_italics_font);
theme->set_font("mono_font", "RichTextLabel", Ref<Font>());
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<Texture2D> default_icon;
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);
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;
}
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_fallback_base_scale(default_scale);

View File

@ -35,7 +35,7 @@
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 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_hinting(cache[p_cache_index], hinting);
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);
}
}
@ -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("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("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::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::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::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");
@ -439,6 +449,8 @@ void FontData::reset_state() {
msdf_pixel_range = 14;
msdf_size = 128;
fixed_size = 0;
embolden = 0.f;
transform = Transform2D();
oversampling = 0.f;
}
@ -1385,6 +1397,36 @@ TextServer::SubpixelPositioning FontData::get_subpixel_positioning() const {
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) {
if (oversampling != p_oversampling) {
oversampling = p_oversampling;

View File

@ -57,6 +57,8 @@ class FontData : public Resource {
TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
real_t oversampling = 0.f;
real_t embolden = 0.f;
Transform2D transform;
// Cache.
mutable Vector<RID> cache;
@ -122,6 +124,12 @@ public:
virtual void set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel);
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 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_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_get_variation_coordinates, "font_rid");
@ -527,6 +533,30 @@ TextServer::SubpixelPositioning TextServerExtension::font_get_subpixel_positioni
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) {
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);
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 Dictionary font_get_variation_coordinates(RID p_font_rid) const override;
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_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_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 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 Dictionary font_get_variation_coordinates(RID p_font_rid) const = 0;