Home | History | Annotate | Download | only in base
      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