Make path names in cache files absolute (NB, cache format change) Stop
permitting cache files to be stored in font dirs. Bump cache magic. Don't include /fonts.cache-2 in cache hash construction. reviewed by: Patrick Lam <plam@mit.edu>
This commit is contained in:
parent
3b013a034a
commit
c1c3ba06d5
30
ChangeLog
30
ChangeLog
|
@ -1,3 +1,33 @@
|
|||
2006-04-27 Keith Packard <keithp@keithp.com>
|
||||
|
||||
reviewed by: Patrick Lam <plam@mit.edu>
|
||||
|
||||
* src/fccache.c: (FcDirCacheUnlink), (FcDirCacheHashName),
|
||||
(FcDirCacheOpen), (FcDirCacheWrite):
|
||||
* src/fcfreetype.c: (FcFreeTypeQuery):
|
||||
* src/fcint.h:
|
||||
* src/fclist.c: (FcListAppend):
|
||||
* src/fcmatch.c: (FcFontRenderPrepare):
|
||||
* src/fcpat.c: (FcPatternDestroy), (FcPatternBaseFreeze),
|
||||
(FcPatternFreeze), (FcPatternGet), (FcPatternDuplicate),
|
||||
(FcStrUnserialize):
|
||||
Make path names in cache files absolute (NB, cache format change)
|
||||
Stop permitting cache files to be stored in font dirs.
|
||||
Bump cache magic.
|
||||
Don't include /fonts.cache-2 in cache hash construction.
|
||||
|
||||
2006-04-26 Keith Packard <keithp@keithp.com>
|
||||
|
||||
* src/fccache.c: (FcDirCacheUnlink), (FcDirCacheOpen),
|
||||
(FcDirCacheWrite):
|
||||
* src/fcfreetype.c: (FcFreeTypeQuery):
|
||||
* src/fcint.h:
|
||||
* src/fclist.c: (FcListAppend):
|
||||
* src/fcmatch.c: (FcFontRenderPrepare):
|
||||
* src/fcpat.c: (FcPatternDestroy), (FcPatternBaseFreeze),
|
||||
(FcPatternFreeze), (FcPatternGet), (FcPatternDuplicate),
|
||||
(FcStrUnserialize):
|
||||
|
||||
2006-04-25 Patrick Lam <plam@mit.edu>
|
||||
* ChangeLog:
|
||||
* README:
|
||||
|
|
104
src/fccache.c
104
src/fccache.c
|
@ -48,7 +48,7 @@ static int
|
|||
FcDirCacheOpen (const FcChar8 * dir);
|
||||
|
||||
static char *
|
||||
FcDirCacheHashName (char * cache_file, int collisions);
|
||||
FcDirCacheHashName (const FcChar8 * dir, int collisions);
|
||||
|
||||
static off_t
|
||||
FcCacheSkipToArch (int fd, const char * arch);
|
||||
|
@ -828,29 +828,21 @@ FcDirCacheHasCurrentArch (const FcChar8 *dir)
|
|||
FcBool
|
||||
FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
|
||||
{
|
||||
char *cache_file;
|
||||
char *cache_hashed = 0;
|
||||
int fd, collisions;
|
||||
struct stat cache_stat;
|
||||
char name_buf[FC_MAX_FILE_LEN];
|
||||
char dir_buf[FC_MAX_FILE_LEN];
|
||||
|
||||
dir = FcConfigNormalizeFontDir (config, dir);
|
||||
cache_file = (char *)FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
|
||||
if (!cache_file)
|
||||
return FcFalse;
|
||||
|
||||
/* First remove normal cache file. */
|
||||
if (stat ((char *) cache_file, &cache_stat) == 0)
|
||||
unlink ((char *)cache_file);
|
||||
|
||||
/* Next remove any applicable hashed files. */
|
||||
/* Remove any applicable hashed files. */
|
||||
fd = -1; collisions = 0;
|
||||
do
|
||||
{
|
||||
if (cache_hashed)
|
||||
FcStrFree ((FcChar8 *)cache_hashed);
|
||||
|
||||
cache_hashed = FcDirCacheHashName (cache_file, collisions++);
|
||||
cache_hashed = FcDirCacheHashName (dir, collisions++);
|
||||
if (!cache_hashed)
|
||||
goto bail;
|
||||
|
||||
|
@ -860,16 +852,15 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
|
|||
if (fd == -1)
|
||||
{
|
||||
FcStrFree ((FcChar8 *)cache_hashed);
|
||||
FcStrFree ((FcChar8 *)cache_file);
|
||||
return FcTrue;
|
||||
}
|
||||
|
||||
if (!FcCacheReadString (fd, name_buf, sizeof (name_buf)) || !strlen(name_buf))
|
||||
if (!FcCacheReadString (fd, dir_buf, sizeof (dir_buf)) || !strlen(dir_buf))
|
||||
{
|
||||
FcStrFree ((FcChar8 *)cache_hashed);
|
||||
goto bail;
|
||||
}
|
||||
} while (strcmp (name_buf, cache_file) != 0);
|
||||
} while (strcmp ((char *) dir_buf, (char *) dir) != 0);
|
||||
|
||||
close (fd);
|
||||
|
||||
|
@ -880,12 +871,10 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
|
|||
goto bail;
|
||||
}
|
||||
|
||||
FcStrFree ((FcChar8 *)cache_file);
|
||||
FcStrFree ((FcChar8 *)cache_hashed);
|
||||
return FcTrue;
|
||||
|
||||
bail:
|
||||
FcStrFree ((FcChar8 *)cache_file);
|
||||
return FcFalse;
|
||||
}
|
||||
|
||||
|
@ -1024,7 +1013,7 @@ static const char bin2hex[] = { '0', '1', '2', '3',
|
|||
'c', 'd', 'e', 'f' };
|
||||
|
||||
static char *
|
||||
FcDirCacheHashName (char * cache_file, int collisions)
|
||||
FcDirCacheHashName (const FcChar8 * dir, int collisions)
|
||||
{
|
||||
unsigned char hash[16], hex_hash[33];
|
||||
char *cache_hashed;
|
||||
|
@ -1034,7 +1023,7 @@ FcDirCacheHashName (char * cache_file, int collisions)
|
|||
struct MD5Context ctx;
|
||||
|
||||
MD5Init (&ctx);
|
||||
MD5Update (&ctx, (unsigned char *)cache_file, strlen (cache_file));
|
||||
MD5Update (&ctx, (unsigned char *)dir, strlen ((char *) dir));
|
||||
|
||||
for (i = 0; i < collisions; i++)
|
||||
MD5Update (&ctx, &uscore, 1);
|
||||
|
@ -1066,60 +1055,40 @@ FcDirCacheOpen (const FcChar8 *dir)
|
|||
{
|
||||
FcBool found;
|
||||
int fd = -1, collisions = 0;
|
||||
char *cache_file, *cache_hashed;
|
||||
char name_buf[FC_MAX_FILE_LEN];
|
||||
char *cache_hashed;
|
||||
char dir_buf[FC_MAX_FILE_LEN];
|
||||
struct stat dir_stat;
|
||||
|
||||
if (stat ((char *)dir, &dir_stat) == -1)
|
||||
return -1;
|
||||
|
||||
cache_file = (char *)FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
|
||||
if (!cache_file)
|
||||
return -1;
|
||||
|
||||
found = FcFalse;
|
||||
do
|
||||
{
|
||||
struct stat c;
|
||||
FcChar8 *name_buf_dir;
|
||||
|
||||
if (fd >= 0)
|
||||
close (fd);
|
||||
|
||||
cache_hashed = FcDirCacheHashName (cache_file, collisions++);
|
||||
cache_hashed = FcDirCacheHashName (dir, collisions++);
|
||||
if (!cache_hashed)
|
||||
{
|
||||
FcStrFree ((FcChar8 *)cache_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = open(cache_hashed, O_RDONLY | O_BINARY);
|
||||
FcStrFree ((FcChar8 *)cache_hashed);
|
||||
|
||||
if (fd == -1)
|
||||
break;
|
||||
if (!FcCacheReadString (fd, name_buf, sizeof (name_buf)) ||
|
||||
!strlen(name_buf))
|
||||
if (!FcCacheReadString (fd, dir_buf, sizeof (dir_buf)) ||
|
||||
!strlen(dir_buf))
|
||||
break;
|
||||
|
||||
name_buf_dir = FcStrDirname ((FcChar8 *)name_buf);
|
||||
if (stat ((char *)name_buf_dir, &c) == -1)
|
||||
{
|
||||
FcStrFree (name_buf_dir);
|
||||
if (stat ((char *)dir_buf, &c) == -1)
|
||||
continue;
|
||||
}
|
||||
FcStrFree (name_buf_dir);
|
||||
|
||||
found = (c.st_ino == dir_stat.st_ino) && (c.st_dev == dir_stat.st_dev);
|
||||
} while (!found);
|
||||
|
||||
if (!found || fd < 0)
|
||||
{
|
||||
if (fd >= 0)
|
||||
close (fd);
|
||||
fd = open(cache_file, O_RDONLY | O_BINARY);
|
||||
}
|
||||
|
||||
FcStrFree ((FcChar8 *)cache_file);
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
@ -1311,13 +1280,12 @@ FcDirCacheProduce (FcFontSet *set, FcCache *metadata)
|
|||
FcBool
|
||||
FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
|
||||
{
|
||||
char *cache_file;
|
||||
char *cache_hashed;
|
||||
int fd, fd_orig, i, dirs_count;
|
||||
FcAtomic *atomic;
|
||||
FcCache metadata;
|
||||
off_t current_arch_start = 0, truncate_to;
|
||||
char name_buf[FC_MAX_FILE_LEN];
|
||||
char dir_buf[FC_MAX_FILE_LEN];
|
||||
int collisions;
|
||||
|
||||
char *current_arch_machine_name, * header;
|
||||
|
@ -1327,17 +1295,13 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
|
|||
if (!dir)
|
||||
return FcFalse;
|
||||
|
||||
cache_file = (char *)FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
|
||||
if (!cache_file)
|
||||
goto bail;
|
||||
|
||||
/* Ensure that we're not trampling a cache for some other dir. */
|
||||
/* This is slightly different from FcDirCacheOpen, since it
|
||||
* needs the filename, not the file descriptor. */
|
||||
fd = -1; collisions = 0;
|
||||
do
|
||||
{
|
||||
cache_hashed = FcDirCacheHashName (cache_file, collisions++);
|
||||
cache_hashed = FcDirCacheHashName (dir, collisions++);
|
||||
if (!cache_hashed)
|
||||
goto bail0;
|
||||
|
||||
|
@ -1346,7 +1310,7 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
|
|||
fd = open(cache_hashed, O_RDONLY | O_BINARY);
|
||||
if (fd == -1)
|
||||
break;
|
||||
if(!FcCacheReadString (fd, name_buf, sizeof (name_buf)) || !strlen(name_buf))
|
||||
if(!FcCacheReadString (fd, dir_buf, sizeof (dir_buf)) || !strlen(dir_buf))
|
||||
{
|
||||
close (fd);
|
||||
FcStrFree ((FcChar8 *)cache_hashed);
|
||||
|
@ -1354,7 +1318,7 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
|
|||
}
|
||||
close (fd);
|
||||
|
||||
if (strcmp (name_buf, cache_file) != 0)
|
||||
if (strcmp (dir_buf, (char *) dir) != 0)
|
||||
{
|
||||
FcStrFree ((FcChar8 *)cache_hashed);
|
||||
continue;
|
||||
|
@ -1369,38 +1333,24 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
|
|||
goto bail1;
|
||||
|
||||
if (FcDebug () & FC_DBG_CACHE)
|
||||
printf ("FcDirCacheWriteDir cache_file \"%s\"\n", cache_file);
|
||||
printf ("FcDirCacheWriteDir dir \"%s\" file \"%s\"\n",
|
||||
dir, cache_hashed);
|
||||
|
||||
atomic = FcAtomicCreate ((FcChar8 *)cache_hashed);
|
||||
if (!atomic)
|
||||
goto bail1;
|
||||
|
||||
if (!FcAtomicLock (atomic))
|
||||
{
|
||||
/* Now try rewriting the original version of the file. */
|
||||
FcAtomicDestroy (atomic);
|
||||
goto bail2;
|
||||
|
||||
atomic = FcAtomicCreate ((FcChar8 *)cache_file);
|
||||
fd_orig = open (cache_file, O_RDONLY | O_BINARY);
|
||||
if (fd_orig == -1)
|
||||
fd_orig = open((char *)FcAtomicOrigFile (atomic), O_RDONLY | O_BINARY);
|
||||
|
||||
fd = open((char *)FcAtomicNewFile (atomic), O_RDWR | O_CREAT | O_BINARY, 0666);
|
||||
if (fd == -1)
|
||||
goto bail2;
|
||||
}
|
||||
|
||||
/* In all cases, try opening the real location of the cache file first. */
|
||||
/* (even if that's not atomic.) */
|
||||
fd_orig = open (cache_file, O_RDONLY | O_BINARY);
|
||||
if (fd_orig == -1)
|
||||
fd_orig = open((char *)FcAtomicOrigFile (atomic), O_RDONLY | O_BINARY);
|
||||
/* open the original file to save relevant portions */
|
||||
fd_orig = open((char *)FcAtomicOrigFile (atomic), O_RDONLY | O_BINARY);
|
||||
|
||||
fd = open((char *)FcAtomicNewFile (atomic), O_RDWR | O_CREAT | O_BINARY, 0666);
|
||||
if (fd == -1)
|
||||
goto bail3;
|
||||
|
||||
FcCacheWriteString (fd, cache_file);
|
||||
FcCacheWriteString (fd, (char *) dir);
|
||||
|
||||
current_arch_machine_name = FcCacheMachineSignature ();
|
||||
current_arch_start = 0;
|
||||
|
@ -1489,7 +1439,6 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
|
|||
if (!FcAtomicReplaceOrig(atomic))
|
||||
goto bail3;
|
||||
FcStrFree ((FcChar8 *)cache_hashed);
|
||||
FcStrFree ((FcChar8 *)cache_file);
|
||||
FcAtomicUnlock (atomic);
|
||||
FcAtomicDestroy (atomic);
|
||||
return FcTrue;
|
||||
|
@ -1505,11 +1454,8 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
|
|||
bail1:
|
||||
FcStrFree ((FcChar8 *)cache_hashed);
|
||||
bail0:
|
||||
unlink ((char *)cache_file);
|
||||
FcStrFree ((FcChar8 *)cache_file);
|
||||
if (current_dir_block)
|
||||
free (current_dir_block);
|
||||
bail:
|
||||
return FcFalse;
|
||||
}
|
||||
|
||||
|
|
|
@ -997,7 +997,6 @@ FcFreeTypeQuery (const FcChar8 *file,
|
|||
FcChar8 *family = 0;
|
||||
#endif
|
||||
FcChar8 *complex;
|
||||
FcChar8 *file2;
|
||||
const FcChar8 *foundry = 0;
|
||||
int spacing;
|
||||
TT_OS2 *os2;
|
||||
|
@ -1278,15 +1277,8 @@ FcFreeTypeQuery (const FcChar8 *file,
|
|||
printf ("Saving unique fullname %s\n", full);
|
||||
}
|
||||
|
||||
file2 = FcStrCopy (file);
|
||||
if (!FcPatternAddString (pat, FC_FILE, FcStrBasename(file2)))
|
||||
{
|
||||
FcStrFree (file2);
|
||||
if (!FcPatternAddString (pat, FC_FILE, file))
|
||||
goto bail1;
|
||||
}
|
||||
FcStrFree (file2);
|
||||
|
||||
FcPatternAddFullFname (pat, (const char *)FcStrCopy (file));
|
||||
|
||||
if (!FcPatternAddInteger (pat, FC_INDEX, id))
|
||||
goto bail1;
|
||||
|
|
|
@ -333,7 +333,7 @@ typedef struct _FcCaseFold {
|
|||
* cache which is then rewritten to the users home directory
|
||||
*/
|
||||
|
||||
#define FC_CACHE_MAGIC 0xFC02FC03
|
||||
#define FC_CACHE_MAGIC 0xFC02FC04
|
||||
|
||||
typedef struct _FcGlobalCacheDir FcGlobalCacheDir;
|
||||
|
||||
|
@ -871,12 +871,6 @@ FcPatternFini (void);
|
|||
FcBool
|
||||
FcPatternAppend (FcPattern *p, FcPattern *s);
|
||||
|
||||
void
|
||||
FcPatternAddFullFname (const FcPattern *p, const char *fname);
|
||||
|
||||
void
|
||||
FcPatternTransferFullFname (const FcPattern *new, const FcPattern *orig);
|
||||
|
||||
const FcChar8 *
|
||||
FcStrStaticName (const FcChar8 *name);
|
||||
|
||||
|
|
|
@ -422,10 +422,6 @@ FcListAppend (FcListHashTable *table,
|
|||
else
|
||||
defidx = 0;
|
||||
|
||||
/* Also, copy over the full path info. */
|
||||
if (!strcmp (os->objects[o], FC_FILE))
|
||||
FcPatternTransferFullFname (bucket->pattern, font);
|
||||
|
||||
e = FcPatternFindElt (font, os->objects[o]);
|
||||
if (e)
|
||||
{
|
||||
|
|
|
@ -495,9 +495,6 @@ FcFontRenderPrepare (FcConfig *config,
|
|||
FcValueCanonicalize(&FcValueListPtrU(pe->values)->value), FcTrue);
|
||||
}
|
||||
|
||||
if (FcPatternFindElt (font, FC_FILE))
|
||||
FcPatternTransferFullFname (new, font);
|
||||
|
||||
FcConfigSubstituteWithPat (config, new, pat, FcMatchFont);
|
||||
return new;
|
||||
}
|
||||
|
|
130
src/fcpat.c
130
src/fcpat.c
|
@ -39,16 +39,6 @@ FcPatternEltPtrCreateDynamic (FcPatternElt * e);
|
|||
static FcBool
|
||||
FcStrHashed (const FcChar8 *name);
|
||||
|
||||
static const char *
|
||||
FcPatternFindFullFname (const FcPattern *p);
|
||||
|
||||
/* If you are trying to duplicate an FcPattern which will be used for
|
||||
* rendering, be aware that (internally) you also have to use
|
||||
* FcPatternTransferFullFname to transfer the associated filename. If
|
||||
* you are copying the font (externally) using FcPatternGetString,
|
||||
* then everything's fine; this caveat only applies if you're copying
|
||||
* the bits individually. */
|
||||
|
||||
FcPattern *
|
||||
FcPatternCreate (void)
|
||||
{
|
||||
|
@ -311,12 +301,6 @@ FcPatternDestroy (FcPattern *p)
|
|||
if (p->ref == FC_REF_CONSTANT || --p->ref > 0)
|
||||
return;
|
||||
|
||||
if (FcPatternFindFullFname (p))
|
||||
{
|
||||
FcStrFree ((FcChar8 *)FcPatternFindFullFname (p));
|
||||
FcPatternAddFullFname (p, 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < p->num; i++)
|
||||
FcValueListDestroy ((FcPatternEltU(p->elts)+i)->values);
|
||||
|
||||
|
@ -602,9 +586,6 @@ FcPatternBaseFreeze (FcPattern *b)
|
|||
(FcPatternEltU(b->elts)+i)->object;
|
||||
}
|
||||
|
||||
if (FcPatternFindElt (b, FC_FILE))
|
||||
FcPatternTransferFullFname (ep, b);
|
||||
|
||||
ent->hash = hash;
|
||||
ent->next = *bucket;
|
||||
*bucket = ent;
|
||||
|
@ -679,9 +660,6 @@ FcPatternFreeze (FcPattern *p)
|
|||
}
|
||||
}
|
||||
|
||||
if (FcPatternFindElt (p, FC_FILE))
|
||||
FcPatternTransferFullFname (b, p);
|
||||
|
||||
/*
|
||||
* Freeze base
|
||||
*/
|
||||
|
@ -1112,39 +1090,6 @@ FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
|
|||
return FcPatternAdd (p, object, v, FcTrue);
|
||||
}
|
||||
|
||||
static FcResult
|
||||
FcPatternGetFile (const FcPattern *p, const char *object, int id, FcChar8 ** s)
|
||||
{
|
||||
const char *fn, *fpath;
|
||||
FcChar8 *fname;
|
||||
int size;
|
||||
|
||||
fn = FcPatternFindFullFname(p);
|
||||
if (fn)
|
||||
{
|
||||
*s = (FcChar8 *) fn;
|
||||
return FcResultMatch;
|
||||
}
|
||||
|
||||
if (!p->bank)
|
||||
return FcResultMatch;
|
||||
|
||||
fpath = FcCacheFindBankDir (p->bank);
|
||||
size = strlen((char *)fpath) + 1 + strlen ((char *)*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 *)*s);
|
||||
|
||||
FcPatternAddFullFname (p, (const char *)fname);
|
||||
*s = (FcChar8 *)fname;
|
||||
return FcResultMatch;
|
||||
}
|
||||
|
||||
FcResult
|
||||
FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
|
||||
{
|
||||
|
@ -1159,12 +1104,6 @@ FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
|
|||
if (!id)
|
||||
{
|
||||
*v = FcValueCanonicalize(&FcValueListPtrU(l)->value);
|
||||
|
||||
/* Pull the FC_FILE trick here too. */
|
||||
if (v->type == FcTypeString &&
|
||||
FcObjectToPtr(object) == FcObjectToPtr(FC_FILE))
|
||||
return FcPatternGetFile (p, object, id, (FcChar8 **)&(v->u.s));
|
||||
|
||||
return FcResultMatch;
|
||||
}
|
||||
id--;
|
||||
|
@ -1332,7 +1271,6 @@ FcPatternDuplicate (const FcPattern *orig)
|
|||
FcTrue))
|
||||
goto bail1;
|
||||
}
|
||||
FcPatternTransferFullFname (new, orig);
|
||||
|
||||
return new;
|
||||
|
||||
|
@ -2025,71 +1963,3 @@ 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 upon termination, 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
|
||||
[((unsigned long)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;
|
||||
}
|
||||
|
||||
static const char *
|
||||
FcPatternFindFullFname (const FcPattern *p)
|
||||
{
|
||||
struct patternDirBucket *pb;
|
||||
|
||||
for (pb = &FcPatternDirBuckets
|
||||
[((unsigned long)p / sizeof (FcPattern *)) % PATTERNDIR_HASH_SIZE];
|
||||
pb; pb = pb->next)
|
||||
if (pb->m.p == p)
|
||||
return pb->m.fname;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
FcPatternTransferFullFname (const FcPattern *new, const FcPattern *orig)
|
||||
{
|
||||
FcChar8 * s;
|
||||
FcPatternGetString (orig, FC_FILE, 0, &s);
|
||||
FcPatternAddFullFname (new,
|
||||
(char *)FcStrCopy
|
||||
((FcChar8 *)FcPatternFindFullFname(orig)));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue