Fix for T101481: Improved VFont Loading

Remove redundancy in the testing and loading of VFont fonts. Includes
improved setting of character map for using Wingding and Symbol fonts.

See D16174 for more details.

Differential Revision: https://developer.blender.org/D16174

Reviewed by Campbell Barton
This commit is contained in:
Harley Acheson 2022-10-06 18:02:40 -07:00
parent 781d03efe4
commit 104fd82f74
Notes: blender-bot 2023-02-14 06:00:50 +01:00
Referenced by issue #101481, Regression: Wingding type font doesn't load
1 changed files with 42 additions and 62 deletions

View File

@ -266,30 +266,22 @@ static VChar *objchr_to_ftvfontdata(VFont *vfont, FT_ULong charcode)
return che;
}
static VFontData *objfnt_to_ftvfontdata(PackedFile *pf)
static FT_Face vfont_face_load_from_packed_file(PackedFile *pf)
{
/* Variables */
FT_Face face;
VFontData *vfd;
/* load the freetype font */
err = FT_New_Memory_Face(library, pf->data, pf->size, 0, &face);
if (err) {
FT_Face face = NULL;
FT_New_Memory_Face(library, pf->data, pf->size, 0, &face);
if (!face) {
return NULL;
}
/* allocate blender font */
vfd = MEM_callocN(sizeof(*vfd), "FTVFontData");
/* Get the name. */
if (face->family_name) {
BLI_snprintf(vfd->name, sizeof(vfd->name), "%s %s", face->family_name, face->style_name);
BLI_str_utf8_invalid_strip(vfd->name, strlen(vfd->name));
/* Font must contain vectors, not bitmaps. */
if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) {
FT_Done_Face(face);
return NULL;
}
/* Select a character map. */
err = FT_Select_Charmap(face, FT_ENCODING_UNICODE);
FT_Error err = FT_Select_Charmap(face, FT_ENCODING_UNICODE);
if (err) {
err = FT_Select_Charmap(face, FT_ENCODING_APPLE_ROMAN);
}
@ -298,10 +290,42 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile *pf)
}
if (err) {
FT_Done_Face(face);
MEM_freeN(vfd);
return NULL;
}
/* Test that we can load glyphs from this font. */
FT_UInt glyph_index = 0;
FT_Get_First_Char(face, &glyph_index);
if (!glyph_index ||
FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP) != FT_Err_Ok) {
FT_Done_Face(face);
return NULL;
}
return face;
}
VFontData *BKE_vfontdata_from_freetypefont(PackedFile *pf)
{
if (FT_Init_FreeType(&library) != FT_Err_Ok) {
return NULL;
}
FT_Face face = vfont_face_load_from_packed_file(pf);
if (!face) {
FT_Done_FreeType(library);
return NULL;
}
/* allocate blender font */
VFontData *vfd = MEM_callocN(sizeof(*vfd), "FTVFontData");
/* Get the name. */
if (face->family_name) {
BLI_snprintf(vfd->name, sizeof(vfd->name), "%s %s", face->family_name, face->style_name);
BLI_str_utf8_invalid_strip(vfd->name, strlen(vfd->name));
}
/* Blender default BFont is not "complete". */
const bool complete_font = (face->ascender != 0) && (face->descender != 0) &&
(face->ascender != face->descender);
@ -344,50 +368,6 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile *pf)
freetypechar_to_vchar(face, charcode, vfd);
}
return vfd;
}
static bool check_freetypefont(PackedFile *pf)
{
FT_Face face = NULL;
FT_UInt glyph_index = 0;
bool success = false;
err = FT_New_Memory_Face(library, pf->data, pf->size, 0, &face);
if (err) {
return false;
// XXX error("This is not a valid font");
}
FT_Get_First_Char(face, &glyph_index);
if (glyph_index) {
err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);
if (!err) {
success = (face->glyph->format == ft_glyph_format_outline);
}
}
FT_Done_Face(face);
return success;
}
VFontData *BKE_vfontdata_from_freetypefont(PackedFile *pf)
{
VFontData *vfd = NULL;
/* init Freetype */
err = FT_Init_FreeType(&library);
if (err) {
/* XXX error("Failed to load the Freetype font library"); */
return NULL;
}
if (check_freetypefont(pf)) {
vfd = objfnt_to_ftvfontdata(pf);
}
/* free Freetype */
FT_Done_FreeType(library);
return vfd;