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