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