1 /***************************************************************************/ 2 /* */ 3 /* ftpatent.c */ 4 /* */ 5 /* FreeType API for checking patented TrueType bytecode instructions */ 6 /* (body). */ 7 /* */ 8 /* Copyright 2007, 2008, 2010 by David Turner. */ 9 /* */ 10 /* This file is part of the FreeType project, and may only be used, */ 11 /* modified, and distributed under the terms of the FreeType project */ 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13 /* this file you indicate that you have read the license and */ 14 /* understand and accept it fully. */ 15 /* */ 16 /***************************************************************************/ 17 18 #include <ft2build.h> 19 #include FT_FREETYPE_H 20 #include FT_TRUETYPE_TAGS_H 21 #include FT_INTERNAL_OBJECTS_H 22 #include FT_INTERNAL_STREAM_H 23 #include FT_SERVICE_SFNT_H 24 #include FT_SERVICE_TRUETYPE_GLYF_H 25 26 27 static FT_Bool 28 _tt_check_patents_in_range( FT_Stream stream, 29 FT_ULong size ) 30 { 31 FT_Bool result = FALSE; 32 FT_Error error; 33 FT_Bytes p, end; 34 35 36 if ( FT_FRAME_ENTER( size ) ) 37 return 0; 38 39 p = stream->cursor; 40 end = p + size; 41 42 while ( p < end ) 43 { 44 switch (p[0]) 45 { 46 case 0x06: /* SPvTL // */ 47 case 0x07: /* SPvTL + */ 48 case 0x08: /* SFvTL // */ 49 case 0x09: /* SFvTL + */ 50 case 0x0A: /* SPvFS */ 51 case 0x0B: /* SFvFS */ 52 result = TRUE; 53 goto Exit; 54 55 case 0x40: 56 if ( p + 1 >= end ) 57 goto Exit; 58 59 p += p[1] + 2; 60 break; 61 62 case 0x41: 63 if ( p + 1 >= end ) 64 goto Exit; 65 66 p += p[1] * 2 + 2; 67 break; 68 69 case 0x71: /* DELTAP2 */ 70 case 0x72: /* DELTAP3 */ 71 case 0x73: /* DELTAC0 */ 72 case 0x74: /* DELTAC1 */ 73 case 0x75: /* DELTAC2 */ 74 result = TRUE; 75 goto Exit; 76 77 case 0xB0: 78 case 0xB1: 79 case 0xB2: 80 case 0xB3: 81 case 0xB4: 82 case 0xB5: 83 case 0xB6: 84 case 0xB7: 85 p += ( p[0] - 0xB0 ) + 2; 86 break; 87 88 case 0xB8: 89 case 0xB9: 90 case 0xBA: 91 case 0xBB: 92 case 0xBC: 93 case 0xBD: 94 case 0xBE: 95 case 0xBF: 96 p += ( p[0] - 0xB8 ) * 2 + 3; 97 break; 98 99 default: 100 p += 1; 101 break; 102 } 103 } 104 105 Exit: 106 FT_UNUSED( error ); 107 FT_FRAME_EXIT(); 108 return result; 109 } 110 111 112 static FT_Bool 113 _tt_check_patents_in_table( FT_Face face, 114 FT_ULong tag ) 115 { 116 FT_Stream stream = face->stream; 117 FT_Error error = FT_Err_Ok; 118 FT_Service_SFNT_Table service; 119 FT_Bool result = FALSE; 120 121 122 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE ); 123 124 if ( service ) 125 { 126 FT_UInt i = 0; 127 FT_ULong tag_i = 0, offset_i = 0, length_i = 0; 128 129 130 for ( i = 0; !error && tag_i != tag ; i++ ) 131 error = service->table_info( face, i, 132 &tag_i, &offset_i, &length_i ); 133 134 if ( error || 135 FT_STREAM_SEEK( offset_i ) ) 136 goto Exit; 137 138 result = _tt_check_patents_in_range( stream, length_i ); 139 } 140 141 Exit: 142 return result; 143 } 144 145 146 static FT_Bool 147 _tt_face_check_patents( FT_Face face ) 148 { 149 FT_Stream stream = face->stream; 150 FT_UInt gindex; 151 FT_Error error; 152 FT_Bool result; 153 154 FT_Service_TTGlyf service; 155 156 157 result = _tt_check_patents_in_table( face, TTAG_fpgm ); 158 if ( result ) 159 goto Exit; 160 161 result = _tt_check_patents_in_table( face, TTAG_prep ); 162 if ( result ) 163 goto Exit; 164 165 FT_FACE_FIND_SERVICE( face, service, TT_GLYF ); 166 if ( service == NULL ) 167 goto Exit; 168 169 for ( gindex = 0; gindex < (FT_UInt)face->num_glyphs; gindex++ ) 170 { 171 FT_ULong offset, num_ins, size; 172 FT_Int num_contours; 173 174 175 offset = service->get_location( face, gindex, &size ); 176 if ( size == 0 ) 177 continue; 178 179 if ( FT_STREAM_SEEK( offset ) || 180 FT_READ_SHORT( num_contours ) ) 181 continue; 182 183 if ( num_contours >= 0 ) /* simple glyph */ 184 { 185 if ( FT_STREAM_SKIP( 8 + num_contours * 2 ) ) 186 continue; 187 } 188 else /* compound glyph */ 189 { 190 FT_Bool has_instr = 0; 191 192 193 if ( FT_STREAM_SKIP( 8 ) ) 194 continue; 195 196 /* now read each component */ 197 for (;;) 198 { 199 FT_UInt flags, toskip; 200 201 202 if( FT_READ_USHORT( flags ) ) 203 break; 204 205 toskip = 2 + 1 + 1; 206 207 if ( ( flags & ( 1 << 0 ) ) != 0 ) /* ARGS_ARE_WORDS */ 208 toskip += 2; 209 210 if ( ( flags & ( 1 << 3 ) ) != 0 ) /* WE_HAVE_A_SCALE */ 211 toskip += 2; 212 else if ( ( flags & ( 1 << 6 ) ) != 0 ) /* WE_HAVE_X_Y_SCALE */ 213 toskip += 4; 214 else if ( ( flags & ( 1 << 7 ) ) != 0 ) /* WE_HAVE_A_2x2 */ 215 toskip += 8; 216 217 if ( ( flags & ( 1 << 8 ) ) != 0 ) /* WE_HAVE_INSTRUCTIONS */ 218 has_instr = 1; 219 220 if ( FT_STREAM_SKIP( toskip ) ) 221 goto NextGlyph; 222 223 if ( ( flags & ( 1 << 5 ) ) == 0 ) /* MORE_COMPONENTS */ 224 break; 225 } 226 227 if ( !has_instr ) 228 goto NextGlyph; 229 } 230 231 if ( FT_READ_USHORT( num_ins ) ) 232 continue; 233 234 result = _tt_check_patents_in_range( stream, num_ins ); 235 if ( result ) 236 goto Exit; 237 238 NextGlyph: 239 ; 240 } 241 242 Exit: 243 return result; 244 } 245 246 247 /* documentation is in freetype.h */ 248 249 FT_EXPORT_DEF( FT_Bool ) 250 FT_Face_CheckTrueTypePatents( FT_Face face ) 251 { 252 FT_Bool result = FALSE; 253 254 255 if ( face && FT_IS_SFNT( face ) ) 256 result = _tt_face_check_patents( face ); 257 258 return result; 259 } 260 261 262 /* documentation is in freetype.h */ 263 264 FT_EXPORT_DEF( FT_Bool ) 265 FT_Face_SetUnpatentedHinting( FT_Face face, 266 FT_Bool value ) 267 { 268 FT_Bool result = FALSE; 269 270 271 #if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \ 272 !defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER ) 273 if ( face && FT_IS_SFNT( face ) ) 274 { 275 result = !face->internal->ignore_unpatented_hinter; 276 face->internal->ignore_unpatented_hinter = !value; 277 } 278 #else 279 FT_UNUSED( face ); 280 FT_UNUSED( value ); 281 #endif 282 283 return result; 284 } 285 286 /* END */ 287