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