summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/fcpattern.fncs10
-rw-r--r--fontconfig/fontconfig.h3
-rw-r--r--src/fccache.c127
-rw-r--r--src/fcint.h3
-rw-r--r--src/fcpat.c30
5 files changed, 171 insertions, 2 deletions
diff --git a/doc/fcpattern.fncs b/doc/fcpattern.fncs
index 928f0bc..912d43d 100644
--- a/doc/fcpattern.fncs
+++ b/doc/fcpattern.fncs
@@ -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
diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
index 6ceabc3..e7a0a59 100644
--- a/fontconfig/fontconfig.h
+++ b/fontconfig/fontconfig.h
@@ -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);
diff --git a/src/fccache.c b/src/fccache.c
index 9176019..6f7722d 100644
--- a/src/fccache.c
+++ b/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;
}
diff --git a/src/fcint.h b/src/fcint.h
index d1a2383..4a0888b 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -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);
diff --git a/src/fcpat.c b/src/fcpat.c
index dd1307d..707afc0 100644
--- a/src/fcpat.c
+++ b/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)
{