Home | History | Annotate | Download | only in sfnt
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  ttbdf.c                                                                */
      4 /*                                                                         */
      5 /*    TrueType and OpenType embedded BDF properties (body).                */
      6 /*                                                                         */
      7 /*  Copyright 2005-2018 by                                                 */
      8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
      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 
     19 #include <ft2build.h>
     20 #include FT_INTERNAL_DEBUG_H
     21 #include FT_INTERNAL_STREAM_H
     22 #include FT_TRUETYPE_TAGS_H
     23 #include "ttbdf.h"
     24 
     25 #include "sferrors.h"
     26 
     27 
     28 #ifdef TT_CONFIG_OPTION_BDF
     29 
     30   /*************************************************************************/
     31   /*                                                                       */
     32   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
     33   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
     34   /* messages during execution.                                            */
     35   /*                                                                       */
     36 #undef  FT_COMPONENT
     37 #define FT_COMPONENT  trace_ttbdf
     38 
     39 
     40   FT_LOCAL_DEF( void )
     41   tt_face_free_bdf_props( TT_Face  face )
     42   {
     43     TT_BDF  bdf = &face->bdf;
     44 
     45 
     46     if ( bdf->loaded )
     47     {
     48       FT_Stream  stream = FT_FACE(face)->stream;
     49 
     50 
     51       if ( bdf->table )
     52         FT_FRAME_RELEASE( bdf->table );
     53 
     54       bdf->table_end    = NULL;
     55       bdf->strings      = NULL;
     56       bdf->strings_size = 0;
     57     }
     58   }
     59 
     60 
     61   static FT_Error
     62   tt_face_load_bdf_props( TT_Face    face,
     63                           FT_Stream  stream )
     64   {
     65     TT_BDF    bdf = &face->bdf;
     66     FT_ULong  length;
     67     FT_Error  error;
     68 
     69 
     70     FT_ZERO( bdf );
     71 
     72     error = tt_face_goto_table( face, TTAG_BDF, stream, &length );
     73     if ( error                                  ||
     74          length < 8                             ||
     75          FT_FRAME_EXTRACT( length, bdf->table ) )
     76     {
     77       error = FT_THROW( Invalid_Table );
     78       goto Exit;
     79     }
     80 
     81     bdf->table_end = bdf->table + length;
     82 
     83     {
     84       FT_Byte*   p           = bdf->table;
     85       FT_UInt    version     = FT_NEXT_USHORT( p );
     86       FT_UInt    num_strikes = FT_NEXT_USHORT( p );
     87       FT_ULong   strings     = FT_NEXT_ULONG ( p );
     88       FT_UInt    count;
     89       FT_Byte*   strike;
     90 
     91 
     92       if ( version != 0x0001                 ||
     93            strings < 8                       ||
     94            ( strings - 8 ) / 4 < num_strikes ||
     95            strings + 1 > length              )
     96       {
     97         goto BadTable;
     98       }
     99 
    100       bdf->num_strikes  = num_strikes;
    101       bdf->strings      = bdf->table + strings;
    102       bdf->strings_size = length - strings;
    103 
    104       count  = bdf->num_strikes;
    105       p      = bdf->table + 8;
    106       strike = p + count * 4;
    107 
    108 
    109       for ( ; count > 0; count-- )
    110       {
    111         FT_UInt  num_items = FT_PEEK_USHORT( p + 2 );
    112 
    113         /*
    114          *  We don't need to check the value sets themselves, since this
    115          *  is done later.
    116          */
    117         strike += 10 * num_items;
    118 
    119         p += 4;
    120       }
    121 
    122       if ( strike > bdf->strings )
    123         goto BadTable;
    124     }
    125 
    126     bdf->loaded = 1;
    127 
    128   Exit:
    129     return error;
    130 
    131   BadTable:
    132     FT_FRAME_RELEASE( bdf->table );
    133     FT_ZERO( bdf );
    134     error = FT_THROW( Invalid_Table );
    135     goto Exit;
    136   }
    137 
    138 
    139   FT_LOCAL_DEF( FT_Error )
    140   tt_face_find_bdf_prop( TT_Face           face,
    141                          const char*       property_name,
    142                          BDF_PropertyRec  *aprop )
    143   {
    144     TT_BDF     bdf   = &face->bdf;
    145     FT_Size    size  = FT_FACE(face)->size;
    146     FT_Error   error = FT_Err_Ok;
    147     FT_Byte*   p;
    148     FT_UInt    count;
    149     FT_Byte*   strike;
    150     FT_Offset  property_len;
    151 
    152 
    153     aprop->type = BDF_PROPERTY_TYPE_NONE;
    154 
    155     if ( bdf->loaded == 0 )
    156     {
    157       error = tt_face_load_bdf_props( face, FT_FACE( face )->stream );
    158       if ( error )
    159         goto Exit;
    160     }
    161 
    162     count  = bdf->num_strikes;
    163     p      = bdf->table + 8;
    164     strike = p + 4 * count;
    165 
    166     error = FT_ERR( Invalid_Argument );
    167 
    168     if ( !size || !property_name )
    169       goto Exit;
    170 
    171     property_len = ft_strlen( property_name );
    172     if ( property_len == 0 )
    173       goto Exit;
    174 
    175     for ( ; count > 0; count-- )
    176     {
    177       FT_UInt  _ppem  = FT_NEXT_USHORT( p );
    178       FT_UInt  _count = FT_NEXT_USHORT( p );
    179 
    180 
    181       if ( _ppem == size->metrics.y_ppem )
    182       {
    183         count = _count;
    184         goto FoundStrike;
    185       }
    186 
    187       strike += 10 * _count;
    188     }
    189     goto Exit;
    190 
    191   FoundStrike:
    192     p = strike;
    193     for ( ; count > 0; count-- )
    194     {
    195       FT_UInt  type = FT_PEEK_USHORT( p + 4 );
    196 
    197 
    198       if ( ( type & 0x10 ) != 0 )
    199       {
    200         FT_UInt32  name_offset = FT_PEEK_ULONG( p     );
    201         FT_UInt32  value       = FT_PEEK_ULONG( p + 6 );
    202 
    203         /* be a bit paranoid for invalid entries here */
    204         if ( name_offset < bdf->strings_size                    &&
    205              property_len < bdf->strings_size - name_offset     &&
    206              ft_strncmp( property_name,
    207                          (const char*)bdf->strings + name_offset,
    208                          bdf->strings_size - name_offset ) == 0 )
    209         {
    210           switch ( type & 0x0F )
    211           {
    212           case 0x00:  /* string */
    213           case 0x01:  /* atoms */
    214             /* check that the content is really 0-terminated */
    215             if ( value < bdf->strings_size &&
    216                  ft_memchr( bdf->strings + value, 0, bdf->strings_size ) )
    217             {
    218               aprop->type   = BDF_PROPERTY_TYPE_ATOM;
    219               aprop->u.atom = (const char*)bdf->strings + value;
    220               error         = FT_Err_Ok;
    221               goto Exit;
    222             }
    223             break;
    224 
    225           case 0x02:
    226             aprop->type      = BDF_PROPERTY_TYPE_INTEGER;
    227             aprop->u.integer = (FT_Int32)value;
    228             error            = FT_Err_Ok;
    229             goto Exit;
    230 
    231           case 0x03:
    232             aprop->type       = BDF_PROPERTY_TYPE_CARDINAL;
    233             aprop->u.cardinal = value;
    234             error             = FT_Err_Ok;
    235             goto Exit;
    236 
    237           default:
    238             ;
    239           }
    240         }
    241       }
    242       p += 10;
    243     }
    244 
    245   Exit:
    246     return error;
    247   }
    248 
    249 #else /* !TT_CONFIG_OPTION_BDF */
    250 
    251   /* ANSI C doesn't like empty source files */
    252   typedef int  _tt_bdf_dummy;
    253 
    254 #endif /* !TT_CONFIG_OPTION_BDF */
    255 
    256 
    257 /* END */
    258