Add new API to find out a font from current search path

This commit is contained in:
Akira TAGOH 2017-08-02 11:02:19 +01:00
parent 7b48fd3dd4
commit 85d9de58ed
5 changed files with 171 additions and 2 deletions

View File

@ -313,6 +313,16 @@ in preference to FcPatternGet to provide compile-time typechecking.
<function>FcPatternGetRange</function> are available since 2.11.91.
@@
@RET@ FcResult
@FUNC@ FcPatternFindFont
@TYPE1@ const FcPattern * @ARG1@ p
@TYPE3@ FcChar8 ** @ARG3@ ret
@PURPOSE@ Find a font corresponding to a filename in a pattern
@DESC@
Returns a filename in <parameter>p</parameter> to the font.
@SINCE@ 2.13.0
@@
@RET@ FcPattern *
@FUNC@ FcPatternBuild
@TYPE1@ FcPattern * @ARG1@ pattern

View File

@ -931,6 +931,9 @@ FcPatternGetLangSet (const FcPattern *p, const char *object, int n, FcLangSet **
FcPublic FcResult
FcPatternGetRange (const FcPattern *p, const char *object, int id, FcRange **r);
FcPublic FcResult
FcPatternFindFont (const FcPattern *p, FcChar8 **s);
FcPublic FcPattern *
FcPatternVaBuild (FcPattern *p, va_list va);

View File

@ -221,6 +221,115 @@ FcDirCacheReadUUID (const FcChar8 *dir)
}
}
#define FC_ALIAS_HASH_SIZE 4099
typedef struct _FcAliasBucket {
struct _FcAliasBucket *next;
FcChar8 *orig;
FcChar8 *alias;
} FcAliasBucket;
typedef struct _FcAliasHashTable {
FcAliasBucket *buckets[FC_ALIAS_HASH_SIZE];
} FcAliasHashTable;
static FcAliasHashTable alias_table;
static FcBool
FcCacheAliasAdd (FcAliasHashTable *table,
const FcChar8 *orig,
const FcChar8 *alias)
{
FcAliasBucket **prev, *bucket;
FcChar32 hash = FcStrHashIgnoreCase (orig);
for (prev = &table->buckets[hash % FC_ALIAS_HASH_SIZE];
(bucket = *prev); prev = &(bucket->next))
{
if (FcStrCmp (bucket->orig, orig) == 0)
return FcTrue;
}
bucket = (FcAliasBucket *) malloc (sizeof (FcAliasBucket));
if (!bucket)
return FcFalse;
bucket->next = NULL;
bucket->orig = FcStrdup (orig);
bucket->alias = FcStrdup (alias);
if (!bucket->orig || !bucket->alias)
{
if (bucket->orig)
FcStrFree (bucket->orig);
if (bucket->alias)
FcStrFree (bucket->alias);
free (bucket);
return FcFalse;
}
*prev = bucket;
return FcTrue;
}
static FcBool
FcCacheAliasRemove (FcAliasHashTable *table,
const FcChar8 *orig)
{
FcAliasBucket **prev, *bucket;
FcChar32 hash = FcStrHashIgnoreCase (orig);
for (prev = &table->buckets[hash % FC_ALIAS_HASH_SIZE];
(bucket = *prev); )
{
if (FcStrCmp (bucket->orig, orig) == 0)
{
*prev = bucket->next;
FcStrFree (bucket->orig);
FcStrFree (bucket->alias);
free (bucket);
return FcTrue;
}
else
prev = &(bucket->next);
}
return FcFalse;
}
static FcBool
FcCacheAliasFind (FcAliasHashTable *table,
const FcChar8 *orig,
const FcChar8 **ret)
{
FcAliasBucket *bucket;
FcChar32 hash = FcStrHashIgnoreCase (orig);
for (bucket = table->buckets[hash % FC_ALIAS_HASH_SIZE]; bucket; bucket = bucket->next)
{
if (FcStrCmp (bucket->orig, orig) == 0)
{
*ret = bucket->alias;
return FcTrue;
}
}
return FcFalse;
}
static void
FcDirCacheAddAliasPath (const FcChar8 *orig,
const FcChar8 *alias)
{
FcCacheAliasAdd (&alias_table, orig, alias);
}
const FcChar8 *
FcDirCacheFindAliasPath (const FcChar8 *dir)
{
const FcChar8 *ret = NULL;
if (FcCacheAliasFind (&alias_table, dir, &ret))
return ret;
return NULL;
}
struct MD5Context {
FcChar32 buf[4];
FcChar32 bits[2];
@ -300,8 +409,12 @@ static FcChar8 *
FcDirCacheBasenameUUID (const FcChar8 *dir, FcChar8 cache_base[CACHEBASE_LEN])
{
uuid_t uuid;
const FcChar8 *alias;
if (FcCacheUuidFind (&uuid_table, dir, uuid))
alias = FcDirCacheFindAliasPath (dir);
if (!alias)
alias = dir;
if (FcCacheUuidFind (&uuid_table, alias, uuid))
{
uuid_unparse (uuid, (char *) cache_base);
strcat ((char *) cache_base, "-" FC_ARCHITECTURE FC_CACHE_SUFFIX);
@ -728,7 +841,12 @@ FcCacheObjectDereference (void *object)
{
if (FcRefDec (&skip->ref) == 1)
{
const FcChar8 *d = FcDirCacheFindAliasPath (FcCacheDir (skip->cache));
FcCacheUuidRemove (&uuid_table, FcCacheDir (skip->cache));
if (d)
FcCacheUuidRemove (&uuid_table, d);
FcCacheAliasRemove (&alias_table, FcCacheDir (skip->cache));
FcDirCacheDisposeUnlocked (skip->cache);
}
}
@ -988,12 +1106,17 @@ FcCache *
FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file)
{
FcCache *cache = NULL;
const FcChar8 *d;
FcDirCacheReadUUID (dir);
if (!FcDirCacheProcess (config, dir,
FcDirCacheMapHelper,
&cache, cache_file))
return NULL;
FcDirCacheReadUUID (FcCacheDir (cache));
d = FcCacheDir (cache);
if (FcStrCmp (dir, d))
FcDirCacheAddAliasPath (d, dir);
return cache;
}

View File

@ -591,6 +591,9 @@ FcPrivate FcBool
FcDirCacheCreateUUID (const FcChar8 *dir,
FcBool force);
FcPrivate const FcChar8 *
FcDirCacheFindAliasPath (const FcChar8 *dir);
FcPrivate FcCache *
FcDirCacheScan (const FcChar8 *dir, FcConfig *config);

View File

@ -1105,6 +1105,36 @@ FcPatternGetRange (const FcPattern *p, const char *object, int id, FcRange **r)
return FcPatternObjectGetRange (p, FcObjectFromName (object), id, r);
}
FcResult
FcPatternFindFont (const FcPattern *p, FcChar8 **s)
{
FcChar8 *file;
FcResult ret = FcResultNoMatch;
if (FcPatternObjectGetString (p, FC_FILE_OBJECT, 0, &file) == FcResultMatch)
{
FcChar8 *dir = FcStrDirname (file);
const FcChar8 *alias;
if ((alias = FcDirCacheFindAliasPath (dir)))
{
FcChar8 *font = FcStrBasename (file);
if (s)
*s = FcStrBuildFilename (alias, font, NULL);
FcStrFree (font);
}
else
{
if (s)
*s = FcStrdup (file);
}
ret = FcResultMatch;
FcStrFree (dir);
}
return ret;
}
FcPattern *
FcPatternDuplicate (const FcPattern *orig)
{