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];
|
char psname[256];
|
||||||
const char *tmp;
|
const char *tmp;
|
||||||
|
|
||||||
FcChar8 *hashstr = NULL;
|
|
||||||
FT_Error err;
|
|
||||||
FT_ULong len = 0, alen;
|
|
||||||
FcRange *r = NULL;
|
FcRange *r = NULL;
|
||||||
double lower_size = 0.0L, upper_size = DBL_MAX;
|
double lower_size = 0.0L, upper_size = DBL_MAX;
|
||||||
|
|
||||||
|
@ -1699,36 +1696,44 @@ FcFreeTypeQueryFace (const FT_Face face,
|
||||||
if (!FcPatternAddBool (pat, FC_DECORATIVE, decorative))
|
if (!FcPatternAddBool (pat, FC_DECORATIVE, decorative))
|
||||||
goto bail1;
|
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);
|
* Compute hash digest for the font
|
||||||
if (!fontdata)
|
|
||||||
goto bail3;
|
|
||||||
err = FT_Load_Sfnt_Table (face, 0, 0, (FT_Byte *)fontdata, &len);
|
|
||||||
if (err != FT_Err_Ok)
|
|
||||||
{
|
|
||||||
free (fontdata);
|
|
||||||
goto bail3;
|
|
||||||
}
|
|
||||||
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;
|
FcChar8 *hashstr = NULL;
|
||||||
|
FcHashDigest digest;
|
||||||
|
|
||||||
|
FcHashInitDigest (digest);
|
||||||
|
|
||||||
|
if (face->stream->read == NULL)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
hashstr = FcHashToString (digest);
|
||||||
if (hashstr)
|
if (hashstr)
|
||||||
{
|
{
|
||||||
if (!FcPatternAddString (pat, FC_HASH, hashstr))
|
if (!FcPatternAddString (pat, FC_HASH, hashstr))
|
||||||
|
@ -1738,7 +1743,8 @@ FcFreeTypeQueryFace (const FT_Face face,
|
||||||
}
|
}
|
||||||
free (hashstr);
|
free (hashstr);
|
||||||
}
|
}
|
||||||
bail3:
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compute the unicode coverage for the font
|
* 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))
|
#define ss1(x) (ROTR32(x, 17) ^ ROTR32(x, 19) ^ SHR(x, 10))
|
||||||
|
|
||||||
|
|
||||||
typedef FcChar32 FcHashDigest[8];
|
|
||||||
|
|
||||||
static void
|
void
|
||||||
FcHashInitDigest (FcHashDigest digest)
|
FcHashInitDigest (FcHashDigest digest)
|
||||||
{
|
{
|
||||||
static const FcHashDigest init = {
|
static const FcHashDigest init = {
|
||||||
|
@ -56,7 +55,7 @@ FcHashInitDigest (FcHashDigest digest)
|
||||||
memcpy (digest, init, sizeof (FcHashDigest));
|
memcpy (digest, init, sizeof (FcHashDigest));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
FcHashDigestAddBlock (FcHashDigest digest,
|
FcHashDigestAddBlock (FcHashDigest digest,
|
||||||
const char block[64])
|
const char block[64])
|
||||||
{
|
{
|
||||||
|
@ -129,7 +128,7 @@ FcHashDigestAddBlock (FcHashDigest digest,
|
||||||
#undef H
|
#undef H
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
FcHashDigestFinish (FcHashDigest digest,
|
FcHashDigestFinish (FcHashDigest digest,
|
||||||
const char *residual, /* < 64 bytes */
|
const char *residual, /* < 64 bytes */
|
||||||
size_t total_len)
|
size_t total_len)
|
||||||
|
@ -164,7 +163,7 @@ FcHashDigestFinish (FcHashDigest digest,
|
||||||
FcHashDigestAddBlock (digest, ibuf);
|
FcHashDigestAddBlock (digest, ibuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FcChar8 *
|
FcChar8 *
|
||||||
FcHashToString (const FcHashDigest digest)
|
FcHashToString (const FcHashDigest digest)
|
||||||
{
|
{
|
||||||
FcChar8 *ret = NULL;
|
FcChar8 *ret = NULL;
|
||||||
|
@ -188,69 +187,3 @@ FcHashToString (const FcHashDigest digest)
|
||||||
|
|
||||||
return ret;
|
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);
|
FcFontSetDeserialize (const FcFontSet *set);
|
||||||
|
|
||||||
/* fchash.c */
|
/* 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 *
|
FcPrivate FcChar8 *
|
||||||
FcHashGetDigestFromMemory (const char *fontdata,
|
FcHashToString (const FcHashDigest digest);
|
||||||
size_t length);
|
|
||||||
|
|
||||||
/* fcinit.c */
|
/* fcinit.c */
|
||||||
FcPrivate FcConfig *
|
FcPrivate FcConfig *
|
||||||
|
|
Loading…
Reference in New Issue