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-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
     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
    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
    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 )
    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 )
    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