From 27a6a299e0fefca9c244213784d3c78b34281cd5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 12 Sep 2017 16:43:33 -0400 Subject: [PATCH] Add FcFreeTypeQueryAll() Like FcFreeTypeQuery(), but adds patterns for all fonts found, including named instances of variable fonts. If id is -1, then all collection faces are queried. Returns number of fonts added. This merges the same face loop that was in fc-query. and fcdir.c. Needs documentation update. --- fc-query/Makefile.am | 2 +- fc-query/fc-query.c | 98 +++++++++++++---------------------------- fc-scan/fc-scan.c | 4 +- fontconfig/fontconfig.h | 3 ++ src/fcdir.c | 86 +++++++++--------------------------- src/fcfreetype.c | 64 ++++++++++++++++++++++++++- 6 files changed, 119 insertions(+), 138 deletions(-) diff --git a/fc-query/Makefile.am b/fc-query/Makefile.am index 6fe357b..73b3f11 100644 --- a/fc-query/Makefile.am +++ b/fc-query/Makefile.am @@ -41,7 +41,7 @@ EXTRA_DIST=fc-query.sgml $(BUILT_MANS) CLEANFILES = -fc_query_LDADD = ${top_builddir}/src/libfontconfig.la $(FREETYPE_LIBS) +fc_query_LDADD = ${top_builddir}/src/libfontconfig.la if USEDOCBOOK diff --git a/fc-query/fc-query.c b/fc-query/fc-query.c index 6cd5abd..a5b2cda 100644 --- a/fc-query/fc-query.c +++ b/fc-query/fc-query.c @@ -98,12 +98,9 @@ usage (char *program, int error) int main (int argc, char **argv) { - FT_Library ftLibrary; - int index_set = 0; - int set_index = 0; - int set_face_num = 0; - int set_instance_num = 0; + int id = -1; int ignore_blanks = 0; + FcFontSet *fs; FcChar8 *format = NULL; FcBlanks *blanks = NULL; int err = 0; @@ -122,8 +119,7 @@ main (int argc, char **argv) ignore_blanks = 1; break; case 'i': - index_set = 1; - set_index = atoi (optarg); + id = atoi (optarg); break; case 'f': format = (FcChar8 *) strdup (optarg); @@ -146,74 +142,42 @@ main (int argc, char **argv) if (i == argc) usage (argv[0], 1); - if (FT_Init_FreeType (&ftLibrary)) - return 1; - + fs = FcFontSetCreate (); if (!ignore_blanks) blanks = FcConfigGetBlanks (NULL); + for (; i < argc; i++) { - FT_Face face; - int num_faces = 0; - int num_instances = 0; - int face_num = 0; - int instance_num = 0; - int id; - - if (index_set) + if (!FcFreeTypeQueryAll ((FcChar8*) argv[i], id, blanks, NULL, fs)) { - face_num = set_face_num = set_index & 0xFFFF; - instance_num = set_instance_num = set_index >> 16; + fprintf (stderr, "Can't query face %d of font file %s\n", id, argv[i]); + err = 1; } - - do { - FcPattern *pat; - - id = ((instance_num << 16) + face_num); - if (FT_New_Face (ftLibrary, argv[i], id, &face)) - break; - num_faces = face->num_faces; - num_instances = face->style_flags >> 16; - pat = FcFreeTypeQueryFace (face, (const FcChar8 *) argv[i], id, blanks); - FT_Done_Face (face); - - if (pat) - { - if (format) - { - FcChar8 *s; - - s = FcPatternFormat (pat, format); - if (s) - { - printf ("%s", s); - FcStrFree (s); - } - } - else - { - FcPatternPrint (pat); - } - - FcPatternDestroy (pat); - } - else - { - fprintf (stderr, "Can't query face %d of font file %s\n", id, argv[i]); - err = 1; - } - - if (instance_num < num_instances && !set_instance_num) - instance_num++; - else - { - face_num++; - instance_num = 0; - } - } while (!err && (!index_set || face_num == set_face_num) && face_num < num_faces); } - FT_Done_FreeType (ftLibrary); + for (i = 0; i < fs->nfont; i++) + { + FcPattern *pat = fs->fonts[i]; + + if (format) + { + FcChar8 *s; + + s = FcPatternFormat (pat, format); + if (s) + { + printf ("%s", s); + FcStrFree (s); + } + } + else + { + FcPatternPrint (pat); + } + } + + FcFontSetDestroy (fs); + FcFini (); return err; } diff --git a/fc-scan/fc-scan.c b/fc-scan/fc-scan.c index 1f18e80..58a0b15 100644 --- a/fc-scan/fc-scan.c +++ b/fc-scan/fc-scan.c @@ -150,9 +150,7 @@ main (int argc, char **argv) for (i = 0; i < fs->nfont; i++) { - FcPattern *pat; - - pat = fs->fonts[i]; + FcPattern *pat = fs->fonts[i]; if (format) { diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h index ecc1d90..f085aa0 100644 --- a/fontconfig/fontconfig.h +++ b/fontconfig/fontconfig.h @@ -577,6 +577,9 @@ FcDirCacheUnload (FcCache *cache); FcPublic FcPattern * FcFreeTypeQuery (const FcChar8 *file, int id, FcBlanks *blanks, int *count); +FcPublic unsigned int +FcFreeTypeQueryAll(const FcChar8 *file, int id, FcBlanks *blanks, int *count, FcFontSet *set); + /* fcfs.c */ FcPublic FcFontSet * diff --git a/src/fcdir.c b/src/fcdir.c index b6c0bf0..4f38f4b 100644 --- a/src/fcdir.c +++ b/src/fcdir.c @@ -23,9 +23,6 @@ */ #include "fcint.h" -#include "fcftint.h" -#include -#include FT_FREETYPE_H #include FcBool @@ -67,47 +64,32 @@ FcFileScanFontConfig (FcFontSet *set, const FcChar8 *file, FcConfig *config) { - FT_Library ftLibrary; - FT_Face face; - FcPattern *font; + int i; FcBool ret = FcTrue; - int num_faces = 0; - int num_instances = 0; - int face_num = 0; - int instance_num = 0; - int id; + int old_nfont = set->nfont; const FcChar8 *sysroot = FcConfigGetSysRoot (config); - if (FT_Init_FreeType (&ftLibrary)) + if (FcDebug () & FC_DBG_SCAN) + { + printf ("\tScanning file %s...", file); + fflush (stdout); + } + + if (!FcFreeTypeQueryAll (file, -1, NULL, NULL, set)) return FcFalse; - do + if (FcDebug () & FC_DBG_SCAN) + printf ("done\n"); + + for (i = old_nfont; i < set->nfont; i++) { - font = 0; - /* - * Nothing in the cache, scan the file - */ - if (FcDebug () & FC_DBG_SCAN) - { - printf ("\tScanning file %s...", file); - fflush (stdout); - } + FcPattern *font = set->fonts[i]; - id = ((instance_num << 16) + face_num); - if (FT_New_Face (ftLibrary, (char *) file, id, &face)) - return FcFalse; - num_faces = face->num_faces; - num_instances = face->style_flags >> 16; - font = FcFreeTypeQueryFace (face, file, id, NULL); - FT_Done_Face (face); - - if (FcDebug () & FC_DBG_SCAN) - printf ("done\n"); /* * Get rid of sysroot here so that targeting scan rule may contains FC_FILE pattern * and they should usually expect without sysroot. */ - if (font && sysroot) + if (sysroot) { size_t len = strlen ((const char *)sysroot); FcChar8 *f = NULL; @@ -129,43 +111,15 @@ FcFileScanFontConfig (FcFontSet *set, /* * Edit pattern with user-defined rules */ - if (font && config && !FcConfigSubstitute (config, font, FcMatchScan)) - { - FcPatternDestroy (font); - font = NULL; - ret = FcFalse; - } - - /* - * Add the font - */ - if (font) - { - if (FcDebug() & FC_DBG_SCANV) - { - printf ("Final font pattern:\n"); - FcPatternPrint (font); - } - if (!FcFontSetAdd (set, font)) - { - FcPatternDestroy (font); - font = NULL; - ret = FcFalse; - } - } - else + if (config && !FcConfigSubstitute (config, font, FcMatchScan)) ret = FcFalse; - if (instance_num < num_instances) - instance_num++; - else + if (FcDebug() & FC_DBG_SCANV) { - face_num++; - instance_num = 0; + printf ("Final font pattern:\n"); + FcPatternPrint (font); } - } while (font && ret && face_num < num_faces); - - FT_Done_FreeType (ftLibrary); + } return ret; } diff --git a/src/fcfreetype.c b/src/fcfreetype.c index dbfe291..a6e7058 100644 --- a/src/fcfreetype.c +++ b/src/fcfreetype.c @@ -1980,7 +1980,8 @@ FcFreeTypeQuery(const FcChar8 *file, if (FT_New_Face (ftLibrary, (char *) file, id, &face)) goto bail; - *count = face->num_faces; + if (count) + *count = face->num_faces; pat = FcFreeTypeQueryFace (face, file, id, blanks); @@ -1990,6 +1991,67 @@ bail: return pat; } +unsigned int +FcFreeTypeQueryAll(const FcChar8 *file, + int id, + FcBlanks *blanks, + int *count, + FcFontSet *set) +{ + FT_Face face; + FT_Library ftLibrary = NULL; + int index_set = id != -1; + int set_face_num = index_set ? id & 0xFFFF : 0; + int set_instance_num = index_set ? id >> 16 : 0; + int face_num = set_face_num; + int instance_num = set_instance_num; + int num_faces = 0; + int num_instances = 0; + unsigned int ret = 0; + int err = 0; + + if (FT_Init_FreeType (&ftLibrary)) + return 0; + + do { + FcPattern *pat; + + id = ((instance_num << 16) + face_num); + if (FT_New_Face (ftLibrary, (const char *) file, id, &face)) + break; + + num_faces = face->num_faces; + num_instances = face->style_flags >> 16; + pat = FcFreeTypeQueryFace (face, (const FcChar8 *) file, id, blanks); + FT_Done_Face (face); + + if (pat) + { + ret++; + if (!set || ! FcFontSetAdd (set, pat)) + FcPatternDestroy (pat); + } + else + err = 1; + + if (instance_num < num_instances && !set_instance_num) + instance_num++; + else + { + face_num++; + instance_num = 0; + } + } while (!err && (!index_set || face_num == set_face_num) && face_num < num_faces); + + if (count) + *count = num_faces; + + FT_Done_FreeType (ftLibrary); + + return ret; +} + + /* * For our purposes, this approximation is sufficient */