ref: 9f5dd61bf3deee315da14d3aca7f436bbf9cc76a
parent: ec4372f56552b7370d6693db8b4d44d412e2dd6a
author: suzuki toshiya <[email protected]>
date: Mon Nov 22 21:47:10 EST 2010
[truetype] Identify the tricky fonts by cvt/fpgm/prep checksums. Some Latin TrueType fonts are still expected to be unhinted. Fix Savannah bug #31645. * src/truetype/ttobjs.c (tt_check_trickyness): Divided to... (tt_check_trickyness_family): this checking family name, and (tt_check_trickyness_sfnt_ids): this checking cvt/fpgm/prep. (tt_get_sfnt_checksum): Function to retrieve the sfnt checksum for specified subtable even if cleared by lazy PDF generators. (tt_synth_sfnt_checksum): Function to calculate the checksum.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2010-11-22 suzuki toshiya <[email protected]>
+
+ [truetype] Identify the tricky fonts by cvt/fpgm/prep checksums.
+ Some Latin TrueType fonts are still expected to be unhinted.
+ Fix Savannah bug #31645.
+
+ * src/truetype/ttobjs.c (tt_check_trickyness): Divided to...
+ (tt_check_trickyness_family): this checking family name, and
+ (tt_check_trickyness_sfnt_ids): this checking cvt/fpgm/prep.
+ (tt_get_sfnt_checksum): Function to retrieve the sfnt checksum
+ for specified subtable even if cleared by lazy PDF generators.
+ (tt_synth_sfnt_checksum): Function to calculate the checksum.
+
2010-11-18 Werner Lemberg <[email protected]>
[truetype] Fix `loca' handling for inconsistent number of glyphs.
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -147,7 +147,7 @@
/* This list shall be expanded as we find more of them. */
static FT_Bool
- tt_check_trickyness( FT_String* name )
+ tt_check_trickyness_family( FT_String* name )
{
#define TRICK_NAMES_MAX_CHARACTERS 16
#define TRICK_NAMES_COUNT 8
@@ -163,17 +163,166 @@
"MingLi43", /* mingli.ttf */
};
int nn;
+ for ( nn = 0; nn < TRICK_NAMES_COUNT; nn++ )
+ if ( ft_strstr( name, trick_names[nn] ) )
+ return TRUE;
+ return FALSE;
+ }
- if ( !name )
- return TRUE;
+ /* XXX: this function should be in sfnt module */
+ /* some PDF generators clear the checksum in TrueType header */
+ /* (Quartz ContextPDF clears all, Bullzip PDF Printer clears */
+ /* for the subsetted subtables), we have to recalculate when */
+ /* it is cleared. */
+ static FT_UInt32
+ tt_synth_sfnt_checksum( FT_Stream stream,
+ FT_ULong length )
+ {
+ FT_Error error;
+ FT_UInt32 checksum = 0;
+ int i;
+
+
+ if ( FT_FRAME_ENTER( length ) )
+ return 0;
+
+ for ( ; length > 3; length -= 4 )
+ checksum += (FT_UInt32)FT_GET_ULONG();
+
+ for ( i = 3; length > 0; length --, i-- )
+ checksum += (FT_UInt32)( FT_GET_BYTE() << ( i * 8 ) );
+
+ FT_FRAME_EXIT();
+
+ return checksum;
+ }
+
+
+ /* XXX: this function should be in sfnt module */
+ static FT_ULong
+ tt_get_sfnt_checksum( TT_Face face,
+ FT_UShort i )
+ {
+ if ( face->dir_tables[i].CheckSum )
+ return face->dir_tables[i].CheckSum;
+ else if ( !face->goto_table )
+ return 0;
+ else if ( !face->goto_table( face,
+ face->dir_tables[i].Tag,
+ face->root.stream,
+ NULL ) )
+ return 0;
+
+ return (FT_ULong)tt_synth_sfnt_checksum( face->root.stream,
+ face->dir_tables[i].Length );
+ }
+
+
+ typedef struct tt_sfnt_id_rec_
+ {
+ FT_ULong CheckSum;
+ FT_ULong Length;
+ } tt_sfnt_id_rec;
+
+
+ static FT_Bool
+ tt_check_trickyness_sfnt_ids( TT_Face face )
+ {
+#define TRICK_SFNT_IDS_PER_FACE 3
+#define TRICK_SFNT_IDS_NUM_FACES 5
+ static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES]
+ [TRICK_SFNT_IDS_PER_FACE] = {
+#define TRICK_SFNT_ID_cvt 0
+#define TRICK_SFNT_ID_fpgm 1
+#define TRICK_SFNT_ID_prep 2
+ { /* MingLiU 1995 */
+ { 0x05bcf058, 0x000002e4 }, /* cvt */
+ { 0x28233bf1, 0x000087c4 }, /* fpgm */
+ { 0xa344a1ea, 0x000001e1 } /* prep */
+ },
+ { /* MingLiU 1996- */
+ { 0x05bcf058, 0x000002e4 }, /* cvt */
+ { 0x28233bf1, 0x000087c4 }, /* fpgm */
+ { 0xa344a1eb, 0x000001e1 } /* prep */
+ },
+ { /* DFKaiShu */
+ { 0x11e5ead4, 0x00000350 }, /* cvt */
+ { 0x5a30ca3b, 0x00009063 }, /* fpgm */
+ { 0x13a42602, 0x0000007e } /* prep */
+ },
+ { /* HuaTianKaiTi */
+ { 0xfffbfffc, 0x00000008 }, /* cvt */
+ { 0x9c9e48b8, 0x0000bea2 }, /* fpgm */
+ { 0x70020112, 0x00000008 } /* prep */
+ },
+ { /* HuaTianSongTi */
+ { 0xfffbfffc, 0x00000008 }, /* cvt */
+ { 0x0a5a0483, 0x00017c39 }, /* fpgm */
+ { 0x70020112, 0x00000008 } /* prep */
+ }
+ };
+ FT_ULong checksum;
+ int num_matched_ids[TRICK_SFNT_IDS_NUM_FACES];
+ int i, j, k;
+
+ FT_MEM_SET( num_matched_ids, 0, sizeof( int ) * TRICK_SFNT_IDS_NUM_FACES );
+
+ for ( i = 0; i < face->num_tables; i++ )
+ {
+ checksum = 0;
+ switch( face->dir_tables[i].Tag )
+ {
+ case TTAG_cvt:
+ k = TRICK_SFNT_ID_cvt;
+ break;
+ case TTAG_fpgm:
+ k = TRICK_SFNT_ID_fpgm;
+ break;
+ case TTAG_prep:
+ k = TRICK_SFNT_ID_prep;
+ break;
+ default:
+ continue;
+ }
+ for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
+ if ( face->dir_tables[i].Length == sfnt_id[j][k].Length )
+ {
+ if ( !checksum )
+ checksum = tt_get_sfnt_checksum( face, i );
+ if ( sfnt_id[j][k].CheckSum == checksum )
+ num_matched_ids[j] ++;
+ if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+ }
+
+
+ static FT_Bool
+ tt_check_trickyness( FT_Face face )
+ {
+ if ( !face )
+ return FALSE;
+
/* Note that we only check the face name at the moment; it might */
/* be worth to do more checks for a few special cases. */
- for ( nn = 0; nn < TRICK_NAMES_COUNT; nn++ )
- if ( ft_strstr( name, trick_names[nn] ) )
+ if ( face->family_name )
+ {
+ if ( tt_check_trickyness_family( face->family_name ) )
return TRUE;
+ else
+ return FALSE;
+ }
+ /* Type42 may lack `name' tables, try to identfiy tricky fonts by */
+ /* the checksums of Type42-persistent sfnt tables; cvt, fpgm, prep */
+ if ( tt_check_trickyness_sfnt_ids( ( TT_Face )face ) )
+ return TRUE;
+
return FALSE;
}
@@ -252,7 +401,7 @@
if ( error )
goto Exit;
- if ( tt_check_trickyness( ttface->family_name ) )
+ if ( tt_check_trickyness( ttface ) )
ttface->face_flags |= FT_FACE_FLAG_TRICKY;
error = tt_face_load_hdmx( face, stream );