summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPatrick Lam <plam@MIT.EDU>2005-11-01 05:26:27 +0000
committerPatrick Lam <plam@MIT.EDU>2005-11-01 05:26:27 +0000
commite77c17184a6172d6368dd3193c791c4027065bbd (patch)
treec65be8e0335b94d5d14b016a991f547eac3a8767 /src
parentbe99726f672cef086b4256ad34163f6f9ed9d4a5 (diff)
downloadfontconfig-e77c17184a6172d6368dd3193c791c4027065bbd.tar.gz
Reinstate basename patch, but keep a hash table linking FcPatterns to their
fully-qualified font names for clients' benefit. Clients only pay for the font names once they request the FC_FILE property from an FcPattern, but the font name is malloc'd at that point (i.e. not mmapped: that's impossible, since it may vary between machines.) Clients do have to pay for a copy of the path name per cache file. Note that FcPatternGetString now does some rewriting if you ask for an FC_FILE, appending the pathname as appropriate.
Diffstat (limited to 'src')
-rw-r--r--src/fccache.c40
-rw-r--r--src/fcfreetype.c5
-rw-r--r--src/fcint.h9
-rw-r--r--src/fclist.c8
-rw-r--r--src/fcpat.c97
5 files changed, 154 insertions, 5 deletions
diff --git a/src/fccache.c b/src/fccache.c
index e761f36..a513652 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -44,7 +44,7 @@ static void *
FcDirCacheProduce (FcFontSet *set, FcCache * metadata);
static FcBool
-FcDirCacheConsume (int fd, FcFontSet *set);
+FcDirCacheConsume (int fd, const char * dir, FcFontSet *set);
FcBool
FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir);
@@ -58,6 +58,9 @@ FcCacheMachineSignature (void);
static FcBool
FcCacheHaveBank (int bank);
+static void
+FcCacheAddBankDir (int bank, const char * dir);
+
#define FC_DBG_CACHE_REF 1024
static char *
@@ -254,7 +257,7 @@ FcGlobalCacheReadDir (FcFontSet *set, FcStrSet *dirs, FcGlobalCache * cache, con
if (strncmp (d->name, dir, strlen(dir)) == 0)
{
lseek (cache->fd, d->offset, SEEK_SET);
- if (!FcDirCacheConsume (cache->fd, set))
+ if (!FcDirCacheConsume (cache->fd, dir, set))
return FcFalse;
if (strcmp (d->name, dir) == 0)
ret = FcTrue;
@@ -734,7 +737,7 @@ FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir)
while (strlen(FcCacheReadString (fd, subdirName, sizeof (subdirName))) > 0)
FcStrSetAdd (dirs, (FcChar8 *)subdirName);
- if (!FcDirCacheConsume (fd, set))
+ if (!FcDirCacheConsume (fd, (const char *)dir, set))
goto bail1;
close(fd);
@@ -749,7 +752,7 @@ FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir)
}
static FcBool
-FcDirCacheConsume (int fd, FcFontSet *set)
+FcDirCacheConsume (int fd, const char * dir, FcFontSet *set)
{
FcCache metadata;
void * current_dir_block;
@@ -771,6 +774,8 @@ FcDirCacheConsume (int fd, FcFontSet *set)
if (!FcFontSetUnserialize (metadata, set, current_dir_block))
return FcFalse;
+ FcCacheAddBankDir (metadata.bank, dir);
+
return FcTrue;
}
@@ -964,6 +969,7 @@ FcCacheMachineSignature ()
static int banks_ptr = 0, banks_alloc = 0;
static int * bankId = 0, * bankIdx = 0;
+static const char ** bankDirs = 0;
static FcBool
FcCacheHaveBank (int bank)
@@ -999,6 +1005,8 @@ FcCacheBankToIndex (int bank)
if (banks_ptr >= banks_alloc)
{
int * b, * bidx;
+ const char ** bds;
+
b = realloc (bankId, (banks_alloc + 4) * sizeof(int));
if (!b)
return -1;
@@ -1009,6 +1017,11 @@ FcCacheBankToIndex (int bank)
return -1;
bankIdx = bidx;
+ bds = realloc (bankDirs, (banks_alloc + 4) * sizeof (char *));
+ if (!bds)
+ return -1;
+ bankDirs = bds;
+
banks_alloc += 4;
}
@@ -1017,3 +1030,22 @@ FcCacheBankToIndex (int bank)
bankIdx[i] = i;
return i;
}
+
+static void
+FcCacheAddBankDir (int bank, const char * dir)
+{
+ int bi = FcCacheBankToIndex (bank);
+
+ if (bi < 0)
+ return;
+
+ bankDirs[bi] = (const char *)FcStrCopy ((FcChar8 *)dir);
+}
+
+const char *
+FcCacheFindBankDir (int bank)
+{
+ int bi = FcCacheBankToIndex (bank);
+ return bankDirs[bi];
+}
+
diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 20194f1..8a42fdb 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -47,6 +47,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <libgen.h>
#include "fcint.h"
#include <ft2build.h>
#include FT_FREETYPE_H
@@ -1287,9 +1288,11 @@ FcFreeTypeQuery (const FcChar8 *file,
printf ("Saving unique fullname %s\n", full);
}
- if (!FcPatternAddString (pat, FC_FILE, file))
+ if (!FcPatternAddString (pat, FC_FILE, (FcChar8 *)basename((char *)file)))
goto bail1;
+ FcPatternAddFullFname (pat, (const char *)file);
+
if (!FcPatternAddInteger (pat, FC_INDEX, id))
goto bail1;
diff --git a/src/fcint.h b/src/fcint.h
index 4fb8905..fccb941 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -450,6 +450,9 @@ FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir);
int
FcCacheBankToIndex (int bank);
+
+const char *
+FcCacheFindBankDir (int bank);
/* fccfg.c */
@@ -802,6 +805,12 @@ FcPatternFini (void);
FcBool
FcPatternAppend (FcPattern *p, FcPattern *s);
+void
+FcPatternAddFullFname (const FcPattern *p, const char *fname);
+
+const char *
+FcPatternFindFullFname (const FcPattern *p);
+
const FcChar8 *
FcStrStaticName (const FcChar8 *name);
diff --git a/src/fclist.c b/src/fclist.c
index 35d68ae..fa567a0 100644
--- a/src/fclist.c
+++ b/src/fclist.c
@@ -422,6 +422,14 @@ FcListAppend (FcListHashTable *table,
else
defidx = 0;
+ /* Also, copy over the full path info. */
+ if (!strcmp (os->objects[o], FC_FILE))
+ {
+ FcChar8 * s;
+ FcPatternGetString (font, FC_FILE, 0, &s);
+ FcPatternAddFullFname (bucket->pattern, FcPatternFindFullFname(font));
+ }
+
e = FcPatternFindElt (font, os->objects[o]);
if (e)
{
diff --git a/src/fcpat.c b/src/fcpat.c
index 0714dc7..6d8f357 100644
--- a/src/fcpat.c
+++ b/src/fcpat.c
@@ -295,6 +295,9 @@ FcPatternDestroy (FcPattern *p)
{
int i;
+ if (FcPatternFindFullFname (p))
+ FcPatternAddFullFname (p, 0);
+
if (p->ref == FC_REF_CONSTANT || --p->ref > 0)
return;
@@ -1115,6 +1118,42 @@ FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s
return r;
if (v.type != FcTypeString)
return FcResultTypeMismatch;
+
+ if (FcObjectToPtr(object) == FcObjectToPtr(FC_FILE))
+ {
+ const char *fn, *fpath;
+ FcChar8 *fname;
+ int size;
+
+ fn = FcPatternFindFullFname(p);
+ if (fn)
+ {
+ *s = (FcChar8 *) fn;
+ return FcResultMatch;
+ }
+
+ if (!p->bank)
+ {
+ *s = (FcChar8 *) v.u.s;
+ return FcResultMatch;
+ }
+
+ fpath = FcCacheFindBankDir (p->bank);
+ size = strlen((char*)fpath) + 1 + strlen ((char *)v.u.s) + 1;
+ fname = malloc (size);
+ if (!fname)
+ return FcResultOutOfMemory;
+
+ FcMemAlloc (FC_MEM_STRING, size);
+ strcpy ((char *)fname, (char *)fpath);
+ strcat ((char *)fname, "/");
+ strcat ((char *)fname, (char *)v.u.s);
+
+ FcPatternAddFullFname (p, (const char *)fname);
+ *s = (FcChar8 *)fname;
+ return FcResultMatch;
+ }
+
*s = (FcChar8 *) v.u.s;
return FcResultMatch;
}
@@ -1874,3 +1913,61 @@ FcStrUnserialize (FcCache metadata, void *block_ptr)
return block_ptr;
}
+/* we don't store these in the FcPattern itself because
+ * we don't want to serialize the directory names */
+
+/* I suppose this should be cleaned, too... */
+typedef struct _FcPatternDirMapping {
+ const FcPattern *p;
+ const char *fname;
+} FcPatternDirMapping;
+
+#define PATTERNDIR_HASH_SIZE 31
+static struct patternDirBucket {
+ struct patternDirBucket *next;
+ FcPatternDirMapping m;
+} FcPatternDirBuckets[PATTERNDIR_HASH_SIZE];
+
+void
+FcPatternAddFullFname (const FcPattern *p, const char *fname)
+{
+ struct patternDirBucket *pb;
+
+ /* N.B. FcPatternHash fails, since it's contents-based, not
+ * address-based, and we're in the process of mutating the FcPattern. */
+ for (pb = &FcPatternDirBuckets
+ [((int)p / sizeof (FcPattern *)) % PATTERNDIR_HASH_SIZE];
+ pb->m.p != p && pb->next;
+ pb = pb->next)
+ ;
+
+ if (pb->m.p == p)
+ {
+ pb->m.fname = fname;
+ return;
+ }
+
+ pb->next = malloc (sizeof (struct patternDirBucket));
+ if (!pb->next)
+ return;
+ FcMemAlloc (FC_MEM_CACHE, sizeof (struct patternDirBucket));
+
+ pb->next->next = 0;
+ pb->next->m.p = p;
+ pb->next->m.fname = fname;
+}
+
+const char *
+FcPatternFindFullFname (const FcPattern *p)
+{
+ struct patternDirBucket *pb;
+
+ for (pb = &FcPatternDirBuckets
+ [((int)p / sizeof (FcPattern *)) % PATTERNDIR_HASH_SIZE];
+ pb; pb = pb->next)
+ if (pb->m.p == p)
+ return pb->m.fname;
+
+ return 0;
+}
+