• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
_tt_check_patents_in_range(FT_Stream stream,FT_ULong size)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
_tt_check_patents_in_table(FT_Face face,FT_ULong tag)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
_tt_face_check_patents(FT_Face face)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 )
FT_Face_CheckTrueTypePatents(FT_Face face)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 )
FT_Face_SetUnpatentedHinting(FT_Face face,FT_Bool value)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_INTEPRETER )
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