From 3f992254f2a3b7f88df989067785141cbf265037 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 16 May 2014 15:02:58 -0600 Subject: [PATCH] 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. --- src/fcfreetype.c | 78 ++++++++++++++++++++++++++---------------------- src/fchash.c | 75 +++------------------------------------------- src/fcint.h | 19 +++++++++--- 3 files changed, 61 insertions(+), 111 deletions(-) diff --git a/src/fcfreetype.c b/src/fcfreetype.c index cd354d5..72da5ca 100644 --- a/src/fcfreetype.c +++ b/src/fcfreetype.c @@ -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 diff --git a/src/fchash.c b/src/fchash.c index 3fc51f7..1526cfd 100644 --- a/src/fchash.c +++ b/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); -} diff --git a/src/fcint.h b/src/fcint.h index b15123b..3d41b0c 100644 --- a/src/fcint.h +++ b/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 *