ftpatent.c revision 049d6fea481044fcc000e7782e5bc7046fc70844
1/***************************************************************************/ 2/* */ 3/* ftpatent.c */ 4/* */ 5/* FreeType API for checking patented TrueType bytecode instructions */ 6/* (body). */ 7/* */ 8/* Copyright 2007 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_FRAME_EXIT(); 107 return result; 108 } 109 110 111 static FT_Bool 112 _tt_check_patents_in_table( FT_Face face, 113 FT_ULong tag ) 114 { 115 FT_Stream stream = face->stream; 116 FT_Error error; 117 FT_Service_SFNT_Table service; 118 FT_Bool result = FALSE; 119 120 121 FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE ); 122 123 if ( service ) 124 { 125 FT_ULong offset, size; 126 127 128 error = service->table_info( face, tag, &offset, &size ); 129 if ( error || 130 FT_STREAM_SEEK( offset ) ) 131 goto Exit; 132 133 result = _tt_check_patents_in_range( stream, size ); 134 } 135 136 Exit: 137 return result; 138 } 139 140 141 static FT_Bool 142 _tt_face_check_patents( FT_Face face ) 143 { 144 FT_Stream stream = face->stream; 145 FT_UInt gindex; 146 FT_Error error; 147 FT_Bool result; 148 149 FT_Service_TTGlyf service; 150 151 152 result = _tt_check_patents_in_table( face, TTAG_fpgm ); 153 if ( result ) 154 goto Exit; 155 156 result = _tt_check_patents_in_table( face, TTAG_prep ); 157 if ( result ) 158 goto Exit; 159 160 FT_FACE_FIND_SERVICE( face, service, TT_GLYF ); 161 if ( service == NULL ) 162 goto Exit; 163 164 for ( gindex = 0; gindex < (FT_UInt)face->num_glyphs; gindex++ ) 165 { 166 FT_ULong offset, num_ins, size; 167 FT_Int num_contours; 168 169 170 offset = service->get_location( face, gindex, &size ); 171 if ( size == 0 ) 172 continue; 173 174 if ( FT_STREAM_SEEK( offset ) || 175 FT_READ_SHORT( num_contours ) ) 176 continue; 177 178 if ( num_contours >= 0 ) /* simple glyph */ 179 { 180 if ( FT_STREAM_SKIP( 8 + num_contours * 2 ) ) 181 continue; 182 } 183 else /* compound glyph */ 184 { 185 FT_Bool has_instr = 0; 186 187 188 if ( FT_STREAM_SKIP( 8 ) ) 189 continue; 190 191 /* now read each component */ 192 for (;;) 193 { 194 FT_UInt flags, toskip; 195 196 197 if( FT_READ_USHORT( flags ) ) 198 break; 199 200 toskip = 2 + 1 + 1; 201 202 if ( ( flags & ( 1 << 0 ) ) != 0 ) /* ARGS_ARE_WORDS */ 203 toskip += 2; 204 205 if ( ( flags & ( 1 << 3 ) ) != 0 ) /* WE_HAVE_A_SCALE */ 206 toskip += 2; 207 else if ( ( flags & ( 1 << 6 ) ) != 0 ) /* WE_HAVE_X_Y_SCALE */ 208 toskip += 4; 209 else if ( ( flags & ( 1 << 7 ) ) != 0 ) /* WE_HAVE_A_2x2 */ 210 toskip += 8; 211 212 if ( ( flags & ( 1 << 8 ) ) != 0 ) /* WE_HAVE_INSTRUCTIONS */ 213 has_instr = 1; 214 215 if ( FT_STREAM_SKIP( toskip ) ) 216 goto NextGlyph; 217 218 if ( ( flags & ( 1 << 5 ) ) == 0 ) /* MORE_COMPONENTS */ 219 break; 220 } 221 222 if ( !has_instr ) 223 goto NextGlyph; 224 } 225 226 if ( FT_READ_USHORT( num_ins ) ) 227 continue; 228 229 result = _tt_check_patents_in_range( stream, num_ins ); 230 if ( result ) 231 goto Exit; 232 233 NextGlyph: 234 ; 235 } 236 237 Exit: 238 return result; 239 } 240 241 242 /* documentation is in freetype.h */ 243 244 FT_EXPORT_DEF( FT_Bool ) 245 FT_Face_CheckTrueTypePatents( FT_Face face ) 246 { 247 FT_Bool result = FALSE; 248 249 250 if ( face && FT_IS_SFNT( face ) ) 251 result = _tt_face_check_patents( face ); 252 253 return result; 254 } 255 256 257 /* documentation is in freetype.h */ 258 259 FT_EXPORT_DEF( FT_Bool ) 260 FT_Face_SetUnpatentedHinting( FT_Face face, 261 FT_Bool value ) 262 { 263 FT_Bool result = 0; 264 265 266#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \ 267 !defined( TT_CONFIG_OPTION_BYTECODE_INTEPRETER ) 268 if ( face && FT_IS_SFNT( face ) ) 269 { 270 result = !face->internal->ignore_unpatented_hinter; 271 face->internal->ignore_unpatented_hinter = !value; 272 } 273#else 274 FT_UNUSED( face ); 275 FT_UNUSED( value ); 276#endif 277 278 return result; 279 } 280 281/* END */ 282