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.
This commit is contained in:
Behdad Esfahbod 2017-09-12 16:43:33 -04:00
parent c524522bb4
commit 27a6a299e0
6 changed files with 119 additions and 138 deletions

View File

@ -41,7 +41,7 @@ EXTRA_DIST=fc-query.sgml $(BUILT_MANS)
CLEANFILES = CLEANFILES =
fc_query_LDADD = ${top_builddir}/src/libfontconfig.la $(FREETYPE_LIBS) fc_query_LDADD = ${top_builddir}/src/libfontconfig.la
if USEDOCBOOK if USEDOCBOOK

View File

@ -98,12 +98,9 @@ usage (char *program, int error)
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
FT_Library ftLibrary; int id = -1;
int index_set = 0;
int set_index = 0;
int set_face_num = 0;
int set_instance_num = 0;
int ignore_blanks = 0; int ignore_blanks = 0;
FcFontSet *fs;
FcChar8 *format = NULL; FcChar8 *format = NULL;
FcBlanks *blanks = NULL; FcBlanks *blanks = NULL;
int err = 0; int err = 0;
@ -122,8 +119,7 @@ main (int argc, char **argv)
ignore_blanks = 1; ignore_blanks = 1;
break; break;
case 'i': case 'i':
index_set = 1; id = atoi (optarg);
set_index = atoi (optarg);
break; break;
case 'f': case 'f':
format = (FcChar8 *) strdup (optarg); format = (FcChar8 *) strdup (optarg);
@ -146,74 +142,42 @@ main (int argc, char **argv)
if (i == argc) if (i == argc)
usage (argv[0], 1); usage (argv[0], 1);
if (FT_Init_FreeType (&ftLibrary)) fs = FcFontSetCreate ();
return 1;
if (!ignore_blanks) if (!ignore_blanks)
blanks = FcConfigGetBlanks (NULL); blanks = FcConfigGetBlanks (NULL);
for (; i < argc; i++) for (; i < argc; i++)
{ {
FT_Face face; if (!FcFreeTypeQueryAll ((FcChar8*) argv[i], id, blanks, NULL, fs))
int num_faces = 0;
int num_instances = 0;
int face_num = 0;
int instance_num = 0;
int id;
if (index_set)
{ {
face_num = set_face_num = set_index & 0xFFFF; fprintf (stderr, "Can't query face %d of font file %s\n", id, argv[i]);
instance_num = set_instance_num = set_index >> 16; 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 (); FcFini ();
return err; return err;
} }

View File

@ -150,9 +150,7 @@ main (int argc, char **argv)
for (i = 0; i < fs->nfont; i++) for (i = 0; i < fs->nfont; i++)
{ {
FcPattern *pat; FcPattern *pat = fs->fonts[i];
pat = fs->fonts[i];
if (format) if (format)
{ {

View File

@ -577,6 +577,9 @@ FcDirCacheUnload (FcCache *cache);
FcPublic FcPattern * FcPublic FcPattern *
FcFreeTypeQuery (const FcChar8 *file, int id, FcBlanks *blanks, int *count); 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 */ /* fcfs.c */
FcPublic FcFontSet * FcPublic FcFontSet *

View File

@ -23,9 +23,6 @@
*/ */
#include "fcint.h" #include "fcint.h"
#include "fcftint.h"
#include <ft2build.h>
#include FT_FREETYPE_H
#include <dirent.h> #include <dirent.h>
FcBool FcBool
@ -67,47 +64,32 @@ FcFileScanFontConfig (FcFontSet *set,
const FcChar8 *file, const FcChar8 *file,
FcConfig *config) FcConfig *config)
{ {
FT_Library ftLibrary; int i;
FT_Face face;
FcPattern *font;
FcBool ret = FcTrue; FcBool ret = FcTrue;
int num_faces = 0; int old_nfont = set->nfont;
int num_instances = 0;
int face_num = 0;
int instance_num = 0;
int id;
const FcChar8 *sysroot = FcConfigGetSysRoot (config); 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; return FcFalse;
do if (FcDebug () & FC_DBG_SCAN)
printf ("done\n");
for (i = old_nfont; i < set->nfont; i++)
{ {
font = 0; FcPattern *font = set->fonts[i];
/*
* Nothing in the cache, scan the file
*/
if (FcDebug () & FC_DBG_SCAN)
{
printf ("\tScanning file %s...", file);
fflush (stdout);
}
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 * Get rid of sysroot here so that targeting scan rule may contains FC_FILE pattern
* and they should usually expect without sysroot. * and they should usually expect without sysroot.
*/ */
if (font && sysroot) if (sysroot)
{ {
size_t len = strlen ((const char *)sysroot); size_t len = strlen ((const char *)sysroot);
FcChar8 *f = NULL; FcChar8 *f = NULL;
@ -129,43 +111,15 @@ FcFileScanFontConfig (FcFontSet *set,
/* /*
* Edit pattern with user-defined rules * Edit pattern with user-defined rules
*/ */
if (font && config && !FcConfigSubstitute (config, font, FcMatchScan)) if (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
ret = FcFalse; ret = FcFalse;
if (instance_num < num_instances) if (FcDebug() & FC_DBG_SCANV)
instance_num++;
else
{ {
face_num++; printf ("Final font pattern:\n");
instance_num = 0; FcPatternPrint (font);
} }
} while (font && ret && face_num < num_faces); }
FT_Done_FreeType (ftLibrary);
return ret; return ret;
} }

View File

@ -1980,7 +1980,8 @@ FcFreeTypeQuery(const FcChar8 *file,
if (FT_New_Face (ftLibrary, (char *) file, id, &face)) if (FT_New_Face (ftLibrary, (char *) file, id, &face))
goto bail; goto bail;
*count = face->num_faces; if (count)
*count = face->num_faces;
pat = FcFreeTypeQueryFace (face, file, id, blanks); pat = FcFreeTypeQueryFace (face, file, id, blanks);
@ -1990,6 +1991,67 @@ bail:
return pat; 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 * For our purposes, this approximation is sufficient
*/ */