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
17 changed files with 364 additions and 25 deletions
+62 -8
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);