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.
|
<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 *
|
@RET@ FcPattern *
|
||||||
@FUNC@ FcPatternBuild
|
@FUNC@ FcPatternBuild
|
||||||
@TYPE1@ FcPattern * @ARG1@ pattern
|
@TYPE1@ FcPattern * @ARG1@ pattern
|
||||||
|
|
|
@ -931,6 +931,9 @@ FcPatternGetLangSet (const FcPattern *p, const char *object, int n, FcLangSet **
|
||||||
FcPublic FcResult
|
FcPublic FcResult
|
||||||
FcPatternGetRange (const FcPattern *p, const char *object, int id, FcRange **r);
|
FcPatternGetRange (const FcPattern *p, const char *object, int id, FcRange **r);
|
||||||
|
|
||||||
|
FcPublic FcResult
|
||||||
|
FcPatternFindFont (const FcPattern *p, FcChar8 **s);
|
||||||
|
|
||||||
FcPublic FcPattern *
|
FcPublic FcPattern *
|
||||||
FcPatternVaBuild (FcPattern *p, va_list va);
|
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 {
|
struct MD5Context {
|
||||||
FcChar32 buf[4];
|
FcChar32 buf[4];
|
||||||
FcChar32 bits[2];
|
FcChar32 bits[2];
|
||||||
|
@ -300,8 +409,12 @@ static FcChar8 *
|
||||||
FcDirCacheBasenameUUID (const FcChar8 *dir, FcChar8 cache_base[CACHEBASE_LEN])
|
FcDirCacheBasenameUUID (const FcChar8 *dir, FcChar8 cache_base[CACHEBASE_LEN])
|
||||||
{
|
{
|
||||||
uuid_t uuid;
|
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);
|
uuid_unparse (uuid, (char *) cache_base);
|
||||||
strcat ((char *) cache_base, "-" FC_ARCHITECTURE FC_CACHE_SUFFIX);
|
strcat ((char *) cache_base, "-" FC_ARCHITECTURE FC_CACHE_SUFFIX);
|
||||||
|
@ -728,7 +841,12 @@ FcCacheObjectDereference (void *object)
|
||||||
{
|
{
|
||||||
if (FcRefDec (&skip->ref) == 1)
|
if (FcRefDec (&skip->ref) == 1)
|
||||||
{
|
{
|
||||||
|
const FcChar8 *d = FcDirCacheFindAliasPath (FcCacheDir (skip->cache));
|
||||||
|
|
||||||
FcCacheUuidRemove (&uuid_table, FcCacheDir (skip->cache));
|
FcCacheUuidRemove (&uuid_table, FcCacheDir (skip->cache));
|
||||||
|
if (d)
|
||||||
|
FcCacheUuidRemove (&uuid_table, d);
|
||||||
|
FcCacheAliasRemove (&alias_table, FcCacheDir (skip->cache));
|
||||||
FcDirCacheDisposeUnlocked (skip->cache);
|
FcDirCacheDisposeUnlocked (skip->cache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -988,12 +1106,17 @@ FcCache *
|
||||||
FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file)
|
FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file)
|
||||||
{
|
{
|
||||||
FcCache *cache = NULL;
|
FcCache *cache = NULL;
|
||||||
|
const FcChar8 *d;
|
||||||
|
|
||||||
|
FcDirCacheReadUUID (dir);
|
||||||
if (!FcDirCacheProcess (config, dir,
|
if (!FcDirCacheProcess (config, dir,
|
||||||
FcDirCacheMapHelper,
|
FcDirCacheMapHelper,
|
||||||
&cache, cache_file))
|
&cache, cache_file))
|
||||||
return NULL;
|
return NULL;
|
||||||
FcDirCacheReadUUID (FcCacheDir (cache));
|
|
||||||
|
d = FcCacheDir (cache);
|
||||||
|
if (FcStrCmp (dir, d))
|
||||||
|
FcDirCacheAddAliasPath (d, dir);
|
||||||
|
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
|
@ -591,6 +591,9 @@ FcPrivate FcBool
|
||||||
FcDirCacheCreateUUID (const FcChar8 *dir,
|
FcDirCacheCreateUUID (const FcChar8 *dir,
|
||||||
FcBool force);
|
FcBool force);
|
||||||
|
|
||||||
|
FcPrivate const FcChar8 *
|
||||||
|
FcDirCacheFindAliasPath (const FcChar8 *dir);
|
||||||
|
|
||||||
FcPrivate FcCache *
|
FcPrivate FcCache *
|
||||||
FcDirCacheScan (const FcChar8 *dir, FcConfig *config);
|
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);
|
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 *
|
FcPattern *
|
||||||
FcPatternDuplicate (const FcPattern *orig)
|
FcPatternDuplicate (const FcPattern *orig)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue