From e77c17184a6172d6368dd3193c791c4027065bbd Mon Sep 17 00:00:00 2001 From: Patrick Lam Date: Tue, 1 Nov 2005 05:26:27 +0000 Subject: [PATCH] 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. --- ChangeLog | 23 ++++++++++++ fc-cat/fc-cat.c | 7 ++-- src/fccache.c | 40 ++++++++++++++++++-- src/fcfreetype.c | 5 ++- src/fcint.h | 9 +++++ src/fclist.c | 8 ++++ src/fcpat.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 181 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4ff3a07..6379c57 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2005-10-31 Patrick Lam + * fc-cat/fc-cat.c: + * src/fccache.c: + * src/fcfreetype.c: + * src/fcint.h: + * src/fclist.c: + * src/fcpat.c: + + 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. + +2005-10-31 Patrick Lam + * src/fcfreetype.c (FcFreeTypeQuery): + + Revert basename patch, which breaks fontconfig clients on my system. + 2005-10-25 Jinghua Luo reviewed by: plam diff --git a/fc-cat/fc-cat.c b/fc-cat/fc-cat.c index 109a058..a392327 100644 --- a/fc-cat/fc-cat.c +++ b/fc-cat/fc-cat.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -165,7 +166,7 @@ usage (char *program) /* read serialized state from the cache file */ static FcBool -FcCacheFileRead (FcFontSet * set, FcStrSet *dirs, char *cache_file) +FcCacheFileRead (FcFontSet * set, FcStrSet *dirs, char * dir, char *cache_file) { int fd; char * current_arch_machine_name; @@ -193,7 +194,7 @@ FcCacheFileRead (FcFontSet * set, FcStrSet *dirs, char *cache_file) while (strlen(FcCacheReadString (fd, subdirName, sizeof (subdirName))) > 0) FcStrSetAdd (dirs, (FcChar8 *)subdirName); - if (!FcDirCacheConsume (fd, set)) + if (!FcDirCacheConsume (fd, dir, set)) goto bail1; close(fd); @@ -326,7 +327,7 @@ main (int argc, char **argv) i = 1; #endif - if (FcCacheFileRead (fs, dirs, argv[i])) + if (FcCacheFileRead (fs, dirs, dirname (argv[i]), argv[i])) FcCachePrintSet (fs, dirs, argv[i]); FcStrSetDestroy (dirs); 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 #include #include +#include #include "fcint.h" #include #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; +} + -- 2.39.5