Lines 147-153
Link Here
|
147 |
/* This list shall be expanded as we find more of them. */ |
147 |
/* This list shall be expanded as we find more of them. */ |
148 |
|
148 |
|
149 |
static FT_Bool |
149 |
static FT_Bool |
150 |
tt_check_trickyness( FT_String* name ) |
150 |
tt_check_trickyness_family( FT_String* name ) |
151 |
{ |
151 |
{ |
152 |
#define TRICK_NAMES_MAX_CHARACTERS 16 |
152 |
#define TRICK_NAMES_MAX_CHARACTERS 16 |
153 |
#define TRICK_NAMES_COUNT 8 |
153 |
#define TRICK_NAMES_COUNT 8 |
Lines 163-178
Link Here
|
163 |
"MingLi43", /* mingli.ttf */ |
163 |
"MingLi43", /* mingli.ttf */ |
164 |
}; |
164 |
}; |
165 |
int nn; |
165 |
int nn; |
|
|
166 |
for ( nn = 0; nn < TRICK_NAMES_COUNT; nn++ ) |
167 |
if ( ft_strstr( name, trick_names[nn] ) ) |
168 |
return TRUE; |
166 |
|
169 |
|
|
|
170 |
return FALSE; |
171 |
} |
167 |
|
172 |
|
168 |
if ( !name ) |
173 |
|
169 |
return TRUE; |
174 |
/* XXX: this function should be in sfnt module */ |
|
|
175 |
/* some PDF generators clear the checksum in TrueType header */ |
176 |
/* (Quartz ContextPDF clears all, Bullzip PDF Printer clears */ |
177 |
/* for the subsetted subtables), we have to recalculate when */ |
178 |
/* it is cleared. */ |
179 |
static FT_UInt32 |
180 |
tt_synth_sfnt_checksum( FT_Stream stream, |
181 |
FT_ULong length ) |
182 |
{ |
183 |
FT_Error error; |
184 |
FT_UInt32 checksum = 0; |
185 |
int i; |
186 |
|
187 |
|
188 |
if ( FT_FRAME_ENTER( length ) ) |
189 |
return 0; |
190 |
|
191 |
for ( ; length > 3; length -= 4 ) |
192 |
checksum += (FT_UInt32)FT_GET_ULONG(); |
193 |
|
194 |
for ( i = 3; length > 0; length --, i-- ) |
195 |
checksum += (FT_UInt32)( FT_GET_BYTE() << ( i * 8 ) ); |
196 |
|
197 |
FT_FRAME_EXIT(); |
198 |
|
199 |
return checksum; |
200 |
} |
201 |
|
202 |
|
203 |
/* XXX: this function should be in sfnt module */ |
204 |
static FT_ULong |
205 |
tt_get_sfnt_checksum( TT_Face face, |
206 |
FT_UShort i ) |
207 |
{ |
208 |
if ( face->dir_tables[i].CheckSum ) |
209 |
return face->dir_tables[i].CheckSum; |
210 |
else if ( !face->goto_table ) |
211 |
return 0; |
212 |
else if ( !face->goto_table( face, |
213 |
face->dir_tables[i].Tag, |
214 |
face->root.stream, |
215 |
NULL ) ) |
216 |
return 0; |
217 |
|
218 |
return (FT_ULong)tt_synth_sfnt_checksum( face->root.stream, |
219 |
face->dir_tables[i].Length ); |
220 |
} |
221 |
|
222 |
|
223 |
typedef struct tt_sfnt_id_rec_ |
224 |
{ |
225 |
FT_ULong CheckSum; |
226 |
FT_ULong Length; |
227 |
} tt_sfnt_id_rec; |
228 |
|
229 |
|
230 |
static FT_Bool |
231 |
tt_check_trickyness_sfnt_ids( TT_Face face ) |
232 |
{ |
233 |
#define TRICK_SFNT_IDS_PER_FACE 3 |
234 |
#define TRICK_SFNT_IDS_NUM_FACES 5 |
235 |
static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES] |
236 |
[TRICK_SFNT_IDS_PER_FACE] = { |
237 |
#define TRICK_SFNT_ID_cvt 0 |
238 |
#define TRICK_SFNT_ID_fpgm 1 |
239 |
#define TRICK_SFNT_ID_prep 2 |
240 |
{ /* MingLiU 1995 */ |
241 |
{ 0x05bcf058, 0x000002e4 }, /* cvt */ |
242 |
{ 0x28233bf1, 0x000087c4 }, /* fpgm */ |
243 |
{ 0xa344a1ea, 0x000001e1 } /* prep */ |
244 |
}, |
245 |
{ /* MingLiU 1996- */ |
246 |
{ 0x05bcf058, 0x000002e4 }, /* cvt */ |
247 |
{ 0x28233bf1, 0x000087c4 }, /* fpgm */ |
248 |
{ 0xa344a1eb, 0x000001e1 } /* prep */ |
249 |
}, |
250 |
{ /* DFKaiShu */ |
251 |
{ 0x11e5ead4, 0x00000350 }, /* cvt */ |
252 |
{ 0x5a30ca3b, 0x00009063 }, /* fpgm */ |
253 |
{ 0x13a42602, 0x0000007e } /* prep */ |
254 |
}, |
255 |
{ /* HuaTianKaiTi */ |
256 |
{ 0xfffbfffc, 0x00000008 }, /* cvt */ |
257 |
{ 0x9c9e48b8, 0x0000bea2 }, /* fpgm */ |
258 |
{ 0x70020112, 0x00000008 } /* prep */ |
259 |
}, |
260 |
{ /* HuaTianSongTi */ |
261 |
{ 0xfffbfffc, 0x00000008 }, /* cvt */ |
262 |
{ 0x0a5a0483, 0x00017c39 }, /* fpgm */ |
263 |
{ 0x70020112, 0x00000008 } /* prep */ |
264 |
} |
265 |
}; |
266 |
FT_ULong checksum; |
267 |
int num_matched_ids[TRICK_SFNT_IDS_NUM_FACES]; |
268 |
int i, j, k; |
269 |
|
270 |
FT_MEM_SET( num_matched_ids, 0, sizeof( int ) * TRICK_SFNT_IDS_NUM_FACES ); |
271 |
|
272 |
for ( i = 0; i < face->num_tables; i++ ) |
273 |
{ |
274 |
checksum = 0; |
275 |
switch( face->dir_tables[i].Tag ) |
276 |
{ |
277 |
case TTAG_cvt: |
278 |
k = TRICK_SFNT_ID_cvt; |
279 |
break; |
280 |
case TTAG_fpgm: |
281 |
k = TRICK_SFNT_ID_fpgm; |
282 |
break; |
283 |
case TTAG_prep: |
284 |
k = TRICK_SFNT_ID_prep; |
285 |
break; |
286 |
default: |
287 |
continue; |
288 |
} |
289 |
for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ ) |
290 |
if ( face->dir_tables[i].Length == sfnt_id[j][k].Length ) |
291 |
{ |
292 |
if ( !checksum ) |
293 |
checksum = tt_get_sfnt_checksum( face, i ); |
294 |
if ( sfnt_id[j][k].CheckSum == checksum ) |
295 |
num_matched_ids[j] ++; |
296 |
if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE ) |
297 |
return TRUE; |
298 |
} |
299 |
} |
300 |
|
301 |
return FALSE; |
302 |
} |
303 |
|
304 |
|
305 |
static FT_Bool |
306 |
tt_check_trickyness( FT_Face face ) |
307 |
{ |
308 |
if ( !face ) |
309 |
return FALSE; |
170 |
|
310 |
|
171 |
/* Note that we only check the face name at the moment; it might */ |
311 |
/* Note that we only check the face name at the moment; it might */ |
172 |
/* be worth to do more checks for a few special cases. */ |
312 |
/* be worth to do more checks for a few special cases. */ |
173 |
for ( nn = 0; nn < TRICK_NAMES_COUNT; nn++ ) |
313 |
if ( face->family_name ) |
174 |
if ( ft_strstr( name, trick_names[nn] ) ) |
314 |
{ |
|
|
315 |
if ( tt_check_trickyness_family( face->family_name ) ) |
175 |
return TRUE; |
316 |
return TRUE; |
|
|
317 |
else |
318 |
return FALSE; |
319 |
} |
320 |
|
321 |
/* Type42 may lack `name' tables, try to identfiy tricky fonts by */ |
322 |
/* the checksums of Type42-persistent sfnt tables; cvt, fpgm, prep */ |
323 |
if ( tt_check_trickyness_sfnt_ids( ( TT_Face )face ) ) |
324 |
return TRUE; |
176 |
|
325 |
|
177 |
return FALSE; |
326 |
return FALSE; |
178 |
} |
327 |
} |
Lines 252-258
Link Here
|
252 |
if ( error ) |
401 |
if ( error ) |
253 |
goto Exit; |
402 |
goto Exit; |
254 |
|
403 |
|
255 |
if ( tt_check_trickyness( ttface->family_name ) ) |
404 |
if ( tt_check_trickyness( ttface ) ) |
256 |
ttface->face_flags |= FT_FACE_FLAG_TRICKY; |
405 |
ttface->face_flags |= FT_FACE_FLAG_TRICKY; |
257 |
|
406 |
|
258 |
error = tt_face_load_hdmx( face, stream ); |
407 |
error = tt_face_load_hdmx( face, stream ); |