Add new API to find out a font from current search path
This commit is contained in:
parent
7b48fd3dd4
commit
85d9de58ed
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
127
src/fccache.c
127
src/fccache.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
30
src/fcpat.c
30
src/fcpat.c
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue