<div dir="ltr">That's true. done.</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Feb 6, 2013 at 1:36 AM, Behdad Esfahbod <span dir="ltr"><<a href="mailto:behdad@behdad.org" target="_blank">behdad@behdad.org</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Oh yeah, I think it should be even higher priority than FC_FILE. It's a<br>
binary match.<br>
<div class="im"><br>
On 02/05/2013 03:27 AM, Akira TAGOH wrote:<br>
> I didn't update the matcher for this. so even if one adds the hash value in<br>
> FcPattern, it doesn't affect the score of the best match. guess it may be not<br>
> something one expects? should we allow it to have a score? then what is the<br>
> expected order? it's supposed to be an unique so adding it after FC_FILE would<br>
> be ideal?<br>
><br>
><br>
> On Tue, Feb 5, 2013 at 3:35 PM, Akira TAGOH <<a href="mailto:tagoh@kemper.freedesktop.org">tagoh@kemper.freedesktop.org</a><br>
</div><div class="im">> <mailto:<a href="mailto:tagoh@kemper.freedesktop.org">tagoh@kemper.freedesktop.org</a>>> wrote:<br>
><br>
> fontconfig/fontconfig.h | 1<br>
> src/Makefile.am | 1<br>
> src/fcfreetype.c | 9 +<br>
> src/fchash.c | 265<br>
> ++++++++++++++++++++++++++++++++++++++++++++++++<br>
> src/fcint.h | 7 +<br>
> src/fcobjs.h | 1<br>
> 6 files changed, 284 insertions(+)<br>
><br>
> New commits:<br>
> commit 95af7447dba7c54ed162b667c0bb2ea6500e8f32<br>
</div>> Author: Akira TAGOH <<a href="mailto:akira@tagoh.org">akira@tagoh.org</a> <mailto:<a href="mailto:akira@tagoh.org">akira@tagoh.org</a>>><br>
<div><div class="h5">> 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<br>
> 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<br>
> 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<br>
> without<br>
> + * specific, written prior permission. The authors make no<br>
> + * representations about the suitability of this software for any<br>
> 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<br>
> 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,<br>
> 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>
</div></div>> <a href="mailto:Fontconfig@lists.freedesktop.org">Fontconfig@lists.freedesktop.org</a> <mailto:<a href="mailto:Fontconfig@lists.freedesktop.org">Fontconfig@lists.freedesktop.org</a>><br>
<div class="im">> <a href="http://lists.freedesktop.org/mailman/listinfo/fontconfig" target="_blank">http://lists.freedesktop.org/mailman/listinfo/fontconfig</a><br>
><br>
><br>
><br>
><br>
> --<br>
> Akira TAGOH<br>
><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>
<br>
--<br>
</div>behdad<br>
<a href="http://behdad.org/" target="_blank">http://behdad.org/</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br>Akira TAGOH
</div>