Rewrite hashing to use FT_Stream directly
This is more robust but introduces a small change in behavior: For .pcf.gz fonts, the new code calculates the hash of the uncompressed font data whereas the original code was calculating the hash of the compressed data. No big deal IMO.
This commit is contained in:
parent
8284df49ef
commit
3f992254f2
|
@ -1104,9 +1104,6 @@ FcFreeTypeQueryFace (const FT_Face face,
|
|||
char psname[256];
|
||||
const char *tmp;
|
||||
|
||||
FcChar8 *hashstr = NULL;
|
||||
FT_Error err;
|
||||
FT_ULong len = 0, alen;
|
||||
FcRange *r = NULL;
|
||||
double lower_size = 0.0L, upper_size = DBL_MAX;
|
||||
|
||||
|
@ -1699,46 +1696,55 @@ FcFreeTypeQueryFace (const FT_Face face,
|
|||
if (!FcPatternAddBool (pat, FC_DECORATIVE, decorative))
|
||||
goto bail1;
|
||||
|
||||
err = FT_Load_Sfnt_Table (face, 0, 0, NULL, &len);
|
||||
if (err == FT_Err_Ok)
|
||||
{
|
||||
char *fontdata;
|
||||
|
||||
alen = (len + 63) & ~63;
|
||||
fontdata = malloc (alen);
|
||||
if (!fontdata)
|
||||
goto bail3;
|
||||
err = FT_Load_Sfnt_Table (face, 0, 0, (FT_Byte *)fontdata, &len);
|
||||
if (err != FT_Err_Ok)
|
||||
/*
|
||||
* Compute hash digest for the font
|
||||
*/
|
||||
{
|
||||
FcChar8 *hashstr = NULL;
|
||||
FcHashDigest digest;
|
||||
|
||||
FcHashInitDigest (digest);
|
||||
|
||||
if (face->stream->read == NULL)
|
||||
{
|
||||
free (fontdata);
|
||||
goto bail3;
|
||||
const char *data = (const char *) face->stream->base;
|
||||
size_t total_len = face->stream->size;
|
||||
size_t len = total_len;
|
||||
|
||||
while (len >= 64)
|
||||
{
|
||||
FcHashDigestAddBlock (digest, data);
|
||||
data += 64;
|
||||
len -= 64;
|
||||
}
|
||||
FcHashDigestFinish (digest, data, total_len);
|
||||
} else {
|
||||
char data[64];
|
||||
size_t total_len = 0;
|
||||
size_t len = 0;
|
||||
|
||||
while ((len = face->stream->read (face->stream, total_len, (unsigned char *) data, sizeof(data))) == 64)
|
||||
{
|
||||
FcHashDigestAddBlock (digest, data);
|
||||
total_len += 64;
|
||||
}
|
||||
total_len += len;
|
||||
FcHashDigestFinish (digest, data, total_len);
|
||||
}
|
||||
memset (&fontdata[len], 0, alen - len);
|
||||
hashstr = FcHashGetDigestFromMemory (fontdata, len);
|
||||
free (fontdata);
|
||||
}
|
||||
else if (err == FT_Err_Invalid_Face_Handle)
|
||||
{
|
||||
/* font may not support SFNT. falling back to
|
||||
* read the font data from file directly
|
||||
*/
|
||||
hashstr = FcHashGetDigestFromFile (file);
|
||||
}
|
||||
else
|
||||
{
|
||||
goto bail3;
|
||||
}
|
||||
if (hashstr)
|
||||
{
|
||||
if (!FcPatternAddString (pat, FC_HASH, hashstr))
|
||||
|
||||
hashstr = FcHashToString (digest);
|
||||
if (hashstr)
|
||||
{
|
||||
if (!FcPatternAddString (pat, FC_HASH, hashstr))
|
||||
{
|
||||
free (hashstr);
|
||||
goto bail1;
|
||||
}
|
||||
free (hashstr);
|
||||
goto bail1;
|
||||
}
|
||||
free (hashstr);
|
||||
}
|
||||
bail3:
|
||||
|
||||
|
||||
/*
|
||||
* Compute the unicode coverage for the font
|
||||
|
|
75
src/fchash.c
75
src/fchash.c
|
@ -43,9 +43,8 @@
|
|||
#define ss1(x) (ROTR32(x, 17) ^ ROTR32(x, 19) ^ SHR(x, 10))
|
||||
|
||||
|
||||
typedef FcChar32 FcHashDigest[8];
|
||||
|
||||
static void
|
||||
void
|
||||
FcHashInitDigest (FcHashDigest digest)
|
||||
{
|
||||
static const FcHashDigest init = {
|
||||
|
@ -56,7 +55,7 @@ FcHashInitDigest (FcHashDigest digest)
|
|||
memcpy (digest, init, sizeof (FcHashDigest));
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
FcHashDigestAddBlock (FcHashDigest digest,
|
||||
const char block[64])
|
||||
{
|
||||
|
@ -129,7 +128,7 @@ FcHashDigestAddBlock (FcHashDigest digest,
|
|||
#undef H
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
FcHashDigestFinish (FcHashDigest digest,
|
||||
const char *residual, /* < 64 bytes */
|
||||
size_t total_len)
|
||||
|
@ -164,7 +163,7 @@ FcHashDigestFinish (FcHashDigest digest,
|
|||
FcHashDigestAddBlock (digest, ibuf);
|
||||
}
|
||||
|
||||
static FcChar8 *
|
||||
FcChar8 *
|
||||
FcHashToString (const FcHashDigest digest)
|
||||
{
|
||||
FcChar8 *ret = NULL;
|
||||
|
@ -188,69 +187,3 @@ FcHashToString (const FcHashDigest digest)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
FcChar8 *
|
||||
FcHashGetDigestFromFile (const FcChar8 *filename)
|
||||
{
|
||||
FcHashDigest digest;
|
||||
FILE *fp;
|
||||
char ibuf[64];
|
||||
size_t len;
|
||||
struct stat st;
|
||||
|
||||
fp = fopen ((const char *)filename, "rb");
|
||||
if (!fp)
|
||||
return NULL;
|
||||
|
||||
FcHashInitDigest (digest);
|
||||
|
||||
if (FcStat (filename, &st))
|
||||
goto bail0;
|
||||
|
||||
while (!feof (fp))
|
||||
{
|
||||
if ((len = fread (ibuf, sizeof (char), 64, fp)) < 64)
|
||||
{
|
||||
FcHashDigestFinish (digest, ibuf, st.st_size);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
FcHashDigestAddBlock (digest, ibuf);
|
||||
}
|
||||
}
|
||||
fclose (fp);
|
||||
|
||||
return FcHashToString (digest);
|
||||
|
||||
bail0:
|
||||
fclose (fp);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FcChar8 *
|
||||
FcHashGetDigestFromMemory (const char *fontdata,
|
||||
size_t length)
|
||||
{
|
||||
FcHashDigest digest;
|
||||
size_t i = 0;
|
||||
|
||||
FcHashInitDigest (digest);
|
||||
|
||||
while (i <= length)
|
||||
{
|
||||
if ((length - i) < 64)
|
||||
{
|
||||
FcHashDigestFinish (digest, fontdata+i, length);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
FcHashDigestAddBlock (digest, &fontdata[i]);
|
||||
}
|
||||
i += 64;
|
||||
}
|
||||
|
||||
return FcHashToString (digest);
|
||||
}
|
||||
|
|
19
src/fcint.h
19
src/fcint.h
|
@ -867,12 +867,23 @@ FcPrivate FcFontSet *
|
|||
FcFontSetDeserialize (const FcFontSet *set);
|
||||
|
||||
/* fchash.c */
|
||||
FcPrivate FcChar8 *
|
||||
FcHashGetDigestFromFile (const FcChar8 *filename);
|
||||
|
||||
typedef FcChar32 FcHashDigest[8];
|
||||
|
||||
FcPrivate void
|
||||
FcHashInitDigest (FcHashDigest digest);
|
||||
|
||||
FcPrivate void
|
||||
FcHashDigestAddBlock (FcHashDigest digest,
|
||||
const char block[64]);
|
||||
|
||||
FcPrivate void
|
||||
FcHashDigestFinish (FcHashDigest digest,
|
||||
const char *residual, /* < 64 bytes */
|
||||
size_t total_len);
|
||||
|
||||
FcPrivate FcChar8 *
|
||||
FcHashGetDigestFromMemory (const char *fontdata,
|
||||
size_t length);
|
||||
FcHashToString (const FcHashDigest digest);
|
||||
|
||||
/* fcinit.c */
|
||||
FcPrivate FcConfig *
|
||||
|
|
Loading…
Reference in New Issue