From 104fd82f74281471d69e61d06de44fca8fdf269c Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Thu, 6 Oct 2022 18:02:40 -0700 Subject: 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 --- .../blender/blenkernel/intern/vfontdata_freetype.c | 104 +++++++++------------ 1 file changed, 42 insertions(+), 62 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/vfontdata_freetype.c b/source/blender/blenkernel/intern/vfontdata_freetype.c index 91ca3100f8c..37e85e70bdb 100644 --- a/source/blender/blenkernel/intern/vfontdata_freetype.c +++ b/source/blender/blenkernel/intern/vfontdata_freetype.c @@ -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; -- cgit v1.2.3