Oh yeah, I think it should be even higher priority than FC_FILE. It's a binary match. On 02/05/2013 03:27 AM, Akira TAGOH wrote: > I didn't update the matcher for this. so even if one adds the hash value in > FcPattern, it doesn't affect the score of the best match. guess it may be not > something one expects? should we allow it to have a score? then what is the > expected order? it's supposed to be an unique so adding it after FC_FILE would > be ideal? > > > On Tue, Feb 5, 2013 at 3:35 PM, Akira TAGOH <tagoh@xxxxxxxxxxxxxxxxxxxxxx > <mailto:tagoh@xxxxxxxxxxxxxxxxxxxxxx>> wrote: > > fontconfig/fontconfig.h | 1 > src/Makefile.am | 1 > src/fcfreetype.c | 9 + > src/fchash.c | 265 > ++++++++++++++++++++++++++++++++++++++++++++++++ > src/fcint.h | 7 + > src/fcobjs.h | 1 > 6 files changed, 284 insertions(+) > > New commits: > commit 95af7447dba7c54ed162b667c0bb2ea6500e8f32 > Author: Akira TAGOH <akira@xxxxxxxxx <mailto:akira@xxxxxxxxx>> > Date: Mon Feb 4 16:03:29 2013 +0900 > > Bug 50733 - Add font-file hash? > > Add "hash" object which contains SHA256 hash value (so far) computed > from the font file. > > diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h > index dc2532f..ff52a61 100644 > --- a/fontconfig/fontconfig.h > +++ b/fontconfig/fontconfig.h > @@ -115,6 +115,7 @@ typedef int FcBool; > #define FC_FONT_FEATURES "fontfeatures" /* String */ > #define FC_NAMELANG "namelang" /* String RFC 3866 langs */ > #define FC_PRGNAME "prgname" /* String */ > +#define FC_HASH "hash" /* String */ > > #define FC_CACHE_SUFFIX ".cache-" FC_CACHE_VERSION > #define FC_DIR_CACHE_FILE "fonts.cache-" FC_CACHE_VERSION > diff --git a/src/Makefile.am b/src/Makefile.am > index 8fb8b64..9fd7dd8 100644 > --- a/src/Makefile.am > +++ b/src/Makefile.am > @@ -139,6 +139,7 @@ libfontconfig_la_SOURCES = \ > fcformat.c \ > fcfreetype.c \ > fcfs.c \ > + fchash.c \ > fcinit.c \ > fclang.c \ > fclist.c \ > diff --git a/src/fcfreetype.c b/src/fcfreetype.c > index faf3c35..111f784 100644 > --- a/src/fcfreetype.c > +++ b/src/fcfreetype.c > @@ -1123,6 +1123,8 @@ FcFreeTypeQueryFace (const FT_Face face, > FcChar8 *style = 0; > int st; > > + FcChar8 *hashstr; > + > pat = FcPatternCreate (); > if (!pat) > goto bail0; > @@ -1634,6 +1636,13 @@ FcFreeTypeQueryFace (const FT_Face face, > if (!FcPatternAddBool (pat, FC_DECORATIVE, decorative)) > goto bail1; > > + hashstr = FcHashGetSHA256DigestFromFile (file); > + if (!hashstr) > + goto bail1; > + if (!FcPatternAddString (pat, FC_HASH, hashstr)) > + goto bail1; > + free (hashstr); > + > /* > * Compute the unicode coverage for the font > */ > diff --git a/src/fchash.c b/src/fchash.c > new file mode 100644 > index 0000000..827b20f > --- /dev/null > +++ b/src/fchash.c > @@ -0,0 +1,265 @@ > +/* > + * fontconfig/src/fchash.c > + * > + * Copyright © 2003 Keith Packard > + * Copyright © 2013 Red Hat, Inc. > + * Red Hat Author(s): Akira TAGOH > + * > + * Permission to use, copy, modify, distribute, and sell this software > and its > + * documentation for any purpose is hereby granted without fee, provided that > + * the above copyright notice appear in all copies and that both that > + * copyright notice and this permission notice appear in supporting > + * documentation, and that the name of the author(s) not be used in > + * advertising or publicity pertaining to distribution of the software > without > + * specific, written prior permission. The authors make no > + * representations about the suitability of this software for any > purpose. It > + * is provided "as is" without express or implied warranty. > + * > + * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, > + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO > + * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR > + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF > USE, > + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER > + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR > + * PERFORMANCE OF THIS SOFTWARE. > + */ > +#ifdef HAVE_CONFIG_H > +#include "config.h" > +#endif > +#include "fcint.h" > +#include <stdio.h> > +#include <string.h> > + > +#define ROTRN(w, v, n) ((((FcChar32)v) >> n) | (((FcChar32)v) << (w - n))) > +#define ROTR32(v, n) ROTRN(32, v, n) > +#define SHR(v, n) (v >> n) > +#define Ch(x, y, z) ((x & y) ^ (~x & z)) > +#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) > +#define SS0(x) (ROTR32(x, 2) ^ ROTR32(x, 13) ^ ROTR32(x, 22)) > +#define SS1(x) (ROTR32(x, 6) ^ ROTR32(x, 11) ^ ROTR32(x, 25)) > +#define ss0(x) (ROTR32(x, 7) ^ ROTR32(x, 18) ^ SHR(x, 3)) > +#define ss1(x) (ROTR32(x, 17) ^ ROTR32(x, 19) ^ SHR(x, 10)) > + > + > +static FcChar32 * > +FcHashInitSHA256Digest (void) > +{ > + int i; > + static const FcChar32 h[] = { > + 0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL, > + 0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL > + }; > + FcChar32 *ret = malloc (sizeof (FcChar32) * 8); > + > + if (!ret) > + return NULL; > + > + for (i = 0; i < 8; i++) > + ret[i] = h[i]; > + > + return ret; > +} > + > +static void > +FcHashComputeSHA256Digest (FcChar32 *hash, > + const char *block) > +{ > + static const FcChar32 k[] = { > + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, > + 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, > + 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, > + 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, > + 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, > + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, > + 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, > + 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, > + 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, > + 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, > + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, > + 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, > + 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, > + 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, > + 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, > + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL > + }; > + FcChar32 w[64], i, j, t1, t2; > + FcChar32 a, b, c, d, e, f, g, h; > + > +#define H(n) (hash[n]) > + > + a = H(0); > + b = H(1); > + c = H(2); > + d = H(3); > + e = H(4); > + f = H(5); > + g = H(6); > + h = H(7); > + > + for (i = 0; i < 16; i++) > + { > + j = (block[(i * 4) + 0] & 0xff) << (8 * 3); > + j |= (block[(i * 4) + 1] & 0xff) << (8 * 2); > + j |= (block[(i * 4) + 2] & 0xff) << (8 * 1); > + j |= (block[(i * 4) + 3] & 0xff); > + w[i] = j; > + } > + for (i = 16; i < 64; i++) > + w[i] = ss1(w[i - 2]) + w[i - 7] + ss0(w[i - 15]) + w[i - 16]; > + > + for (i = 0; i < 64; i++) > + { > + t1 = h + SS1(e) + Ch(e, f, g) + k[i] + w[i]; > + t2 = SS0(a) + Maj(a, b, c); > + h = g; > + g = f; > + f = e; > + e = d + t1; > + d = c; > + c = b; > + b = a; > + a = t1 + t2; > + } > + > + H(0) += a; > + H(1) += b; > + H(2) += c; > + H(3) += d; > + H(4) += e; > + H(5) += f; > + H(6) += g; > + H(7) += h; > + > +#undef H > +} > + > +static FcChar8 * > +FcHashSHA256ToString (FcChar32 *hash) > +{ > + FcChar8 *ret = NULL; > + static const char hex[] = "0123456789abcdef"; > + int i, j; > + > + if (hash) > + { > + ret = malloc (sizeof (FcChar8) * (8 * 8 + 7 + 1)); > + if (!ret) > + return NULL; > + memcpy (ret, "sha256:", 7); > +#define H(n) hash[n] > + for (i = 0; i < 8; i++) > + { > + FcChar32 v = H(i); > + > + for (j = 0; j < 8; j++) > + ret[7 + (i * 8) + j] = hex[(v >> (28 - j * 4)) & 0xf]; > + } > + ret[7 + i * 8] = 0; > +#undef H > + free (hash); > + } > + > + return ret; > +} > + > +FcChar8 * > +FcHashGetSHA256Digest (const FcChar8 *input_strings, > + size_t len) > +{ > + size_t i, round_len = len / 64; > + char block[64]; > + FcChar32 *ret = FcHashInitSHA256Digest (); > + > + if (!ret) > + return NULL; > + > + for (i = 0; i < round_len; i++) > + { > + FcHashComputeSHA256Digest (ret, (const char *)&input_strings[i * 64]); > + } > + /* padding */ > + if ((len % 64) != 0) > + memcpy (block, &input_strings[len / 64], len % 64); > + memset (&block[len % 64], 0, 64 - (len % 64)); > + block[len % 64] = 0x80; > + if ((64 - (len % 64)) < 9) > + { > + /* process a block once */ > + FcHashComputeSHA256Digest (ret, block); > + memset (block, 0, 64); > + } > + /* set input size at the end */ > + len *= 8; > + block[63 - 0] = len & 0xff; > + block[63 - 1] = (len >> 8) & 0xff; > + block[63 - 2] = (len >> 16) & 0xff; > + block[63 - 3] = (len >> 24) & 0xff; > + block[63 - 4] = (len >> 32) & 0xff; > + block[63 - 5] = (len >> 40) & 0xff; > + block[63 - 6] = (len >> 48) & 0xff; > + block[63 - 7] = (len >> 56) & 0xff; > + FcHashComputeSHA256Digest (ret, block); > + > + return FcHashSHA256ToString (ret); > +} > + > +FcChar8 * > +FcHashGetSHA256DigestFromFile (const FcChar8 *filename) > +{ > + FILE *fp = fopen ((const char *)filename, "rb"); > + char ibuf[64]; > + FcChar32 *ret; > + size_t len; > + struct stat st; > + > + if (!fp) > + return NULL; > + > + if (FcStat (filename, &st)) > + goto bail0; > + > + ret = FcHashInitSHA256Digest (); > + if (!ret) > + return NULL; > + > + while (!feof (fp)) > + { > + if ((len = fread (ibuf, sizeof (char), 64, fp)) < 64) > + { > + long v; > + > + /* add a padding */ > + memset (&ibuf[len], 0, 64 - len); > + ibuf[len] = 0x80; > + if ((64 - len) < 9) > + { > + /* process a block once */ > + FcHashComputeSHA256Digest (ret, ibuf); > + memset (ibuf, 0, 64); > + } > + /* set input size at the end */ > + v = (long)st.st_size * 8; > + ibuf[63 - 0] = v & 0xff; > + ibuf[63 - 1] = (v >> 8) & 0xff; > + ibuf[63 - 2] = (v >> 16) & 0xff; > + ibuf[63 - 3] = (v >> 24) & 0xff; > + ibuf[63 - 4] = (v >> 32) & 0xff; > + ibuf[63 - 5] = (v >> 40) & 0xff; > + ibuf[63 - 6] = (v >> 48) & 0xff; > + ibuf[63 - 7] = (v >> 56) & 0xff; > + FcHashComputeSHA256Digest (ret, ibuf); > + break; > + } > + else > + { > + FcHashComputeSHA256Digest (ret, ibuf); > + } > + } > + fclose (fp); > + > + return FcHashSHA256ToString (ret); > + > +bail0: > + fclose (fp); > + return NULL; > +} > diff --git a/src/fcint.h b/src/fcint.h > index fceb8cc..b5ff382 100644 > --- a/src/fcint.h > +++ b/src/fcint.h > @@ -812,6 +812,13 @@ FcFontSetSerializeAlloc (FcSerialize *serialize, > const FcFontSet *s); > FcPrivate FcFontSet * > FcFontSetSerialize (FcSerialize *serialize, const FcFontSet * s); > > +/* fchash.c */ > +FcPrivate FcChar8 * > +FcHashGetSHA256Digest (const FcChar8 *input_strings, > + size_t len); > +FcPrivate FcChar8 * > +FcHashGetSHA256DigestFromFile (const FcChar8 *filename); > + > /* fcxml.c */ > FcPrivate void > FcTestDestroy (FcTest *test); > diff --git a/src/fcobjs.h b/src/fcobjs.h > index ad803eb..3cb2349 100644 > --- a/src/fcobjs.h > +++ b/src/fcobjs.h > @@ -43,4 +43,5 @@ FC_OBJECT (LCD_FILTER, FcTypeInteger) > FC_OBJECT (NAMELANG, FcTypeString) > FC_OBJECT (FONT_FEATURES, FcTypeString) > FC_OBJECT (PRGNAME, FcTypeString) > +FC_OBJECT (HASH, FcTypeString) > /* ^-------------- Add new objects here. */ > > _______________________________________________ > Fontconfig mailing list > Fontconfig@xxxxxxxxxxxxxxxxxxxxx <mailto:Fontconfig@xxxxxxxxxxxxxxxxxxxxx> > http://lists.freedesktop.org/mailman/listinfo/fontconfig > > > > > -- > Akira TAGOH > > > _______________________________________________ > Fontconfig mailing list > Fontconfig@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/fontconfig > -- behdad http://behdad.org/ _______________________________________________ Fontconfig mailing list Fontconfig@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/fontconfig