summaryrefslogtreecommitdiff
blob: a3600c0186ba84790829bd4848ae841c67c759d8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 8a037c0..5e8990d 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1104,7 +1104,10 @@ FcFreeTypeQueryFace (const FT_Face  face,
     char	    psname[256];
     const char	    *tmp;
 
-    FcChar8	    *hashstr;
+    FcChar8	    *hashstr = NULL;
+    char	    *fontdata = NULL;
+    FT_Error	    err;
+    FT_ULong	    len = 0, alen;
 
     pat = FcPatternCreate ();
     if (!pat)
@@ -1662,12 +1665,34 @@ FcFreeTypeQueryFace (const FT_Face  face,
     if (!FcPatternAddBool (pat, FC_DECORATIVE, decorative))
 	goto bail1;
 
-    hashstr = FcHashGetSHA256DigestFromFile (file);
+    err = FT_Load_Sfnt_Table (face, 0, 0, NULL, &len);
+    if (err == FT_Err_Ok)
+    {
+	alen = (len + 63) & ~63;
+	fontdata = malloc (alen);
+	if (!fontdata)
+	    goto bail1;
+	err = FT_Load_Sfnt_Table (face, 0, 0, (FT_Byte *)fontdata, &len);
+	if (err != FT_Err_Ok)
+	    goto bail1;
+	memset (&fontdata[len], 0, alen - len);
+	hashstr = FcHashGetSHA256DigestFromMemory (fontdata, len);
+    }
+    else if (err == FT_Err_Invalid_Face_Handle)
+    {
+	/* font may not support SFNT. falling back to
+	 * read the font data from file directly
+	 */
+	hashstr = FcHashGetSHA256DigestFromFile (file);
+    }
+    else
+    {
+	goto bail1;
+    }
     if (!hashstr)
 	goto bail1;
     if (!FcPatternAddString (pat, FC_HASH, hashstr))
 	goto bail1;
-    free (hashstr);
 
     /*
      * Compute the unicode coverage for the font
@@ -1756,6 +1781,10 @@ FcFreeTypeQueryFace (const FT_Face  face,
 bail2:
     FcCharSetDestroy (cs);
 bail1:
+    if (hashstr)
+	free (hashstr);
+    if (fontdata)
+	free (fontdata);
     FcPatternDestroy (pat);
 bail0:
     return NULL;
diff --git a/src/fchash.c b/src/fchash.c
index 827b20f..92585a6 100644
--- a/src/fchash.c
+++ b/src/fchash.c
@@ -220,7 +220,7 @@ FcHashGetSHA256DigestFromFile (const FcChar8 *filename)
 
     ret = FcHashInitSHA256Digest ();
     if (!ret)
-	return NULL;
+	goto bail0;
 
     while (!feof (fp))
     {
@@ -261,5 +261,60 @@ FcHashGetSHA256DigestFromFile (const FcChar8 *filename)
 
 bail0:
     fclose (fp);
+
     return NULL;
 }
+
+FcChar8 *
+FcHashGetSHA256DigestFromMemory (const char *fontdata,
+				 size_t      length)
+{
+    char ibuf[64];
+    FcChar32 *ret;
+    size_t i = 0;
+
+    ret = FcHashInitSHA256Digest ();
+    if (!ret)
+	return NULL;
+
+    while (i <= length)
+    {
+	if ((length - i) < 64)
+	{
+	    long v;
+	    size_t n;
+
+	    /* add a padding */
+	    n = length - i;
+	    if (n > 0)
+		memcpy (ibuf, &fontdata[i], n);
+	    memset (&ibuf[n], 0, 64 - n);
+	    ibuf[n] = 0x80;
+	    if ((64 - n) < 9)
+	    {
+		/* process a block once */
+		FcHashComputeSHA256Digest (ret, ibuf);
+		memset (ibuf, 0, 64);
+	    }
+	    /* set input size at the end */
+	    v = length * 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, &fontdata[i]);
+	}
+	i += 64;
+    }
+
+    return FcHashSHA256ToString (ret);
+}
diff --git a/src/fcint.h b/src/fcint.h
index c45075e..8919958 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -818,9 +818,14 @@ FcFontSetSerialize (FcSerialize *serialize, const FcFontSet * s);
 FcPrivate FcChar8 *
 FcHashGetSHA256Digest (const FcChar8 *input_strings,
 		       size_t         len);
+
 FcPrivate FcChar8 *
 FcHashGetSHA256DigestFromFile (const FcChar8 *filename);
 
+FcPrivate FcChar8 *
+FcHashGetSHA256DigestFromMemory (const char *fontdata,
+				 size_t      length);
+
 /* fcinit.c */
 FcPrivate FcConfig *
 FcInitLoadOwnConfig (FcConfig *config);