misc/libfreetype/src/sfnt/ttbdf.c
changeset 5172 88f2e05288ba
equal deleted inserted replaced
5171:f9283dc4860d 5172:88f2e05288ba
       
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  ttbdf.c                                                                */
       
     4 /*                                                                         */
       
     5 /*    TrueType and OpenType embedded BDF properties (body).                */
       
     6 /*                                                                         */
       
     7 /*  Copyright 2005, 2006, 2010 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 != NULL )
       
    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 = SFNT_Err_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 = SFNT_Err_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 = SFNT_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 = SFNT_Err_Invalid_Argument;
       
   167 
       
   168     if ( size == NULL || property_name == NULL )
       
   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       if ( _ppem == size->metrics.y_ppem )
       
   181       {
       
   182         count = _count;
       
   183         goto FoundStrike;
       
   184       }
       
   185 
       
   186       strike += 10 * _count;
       
   187     }
       
   188     goto Exit;
       
   189 
       
   190   FoundStrike:
       
   191     p = strike;
       
   192     for ( ; count > 0; count-- )
       
   193     {
       
   194       FT_UInt  type = FT_PEEK_USHORT( p + 4 );
       
   195 
       
   196       if ( ( type & 0x10 ) != 0 )
       
   197       {
       
   198         FT_UInt32  name_offset = FT_PEEK_ULONG( p     );
       
   199         FT_UInt32  value       = FT_PEEK_ULONG( p + 6 );
       
   200 
       
   201         /* be a bit paranoid for invalid entries here */
       
   202         if ( name_offset < bdf->strings_size                    &&
       
   203              property_len < bdf->strings_size - name_offset     &&
       
   204              ft_strncmp( property_name,
       
   205                          (const char*)bdf->strings + name_offset,
       
   206                          bdf->strings_size - name_offset ) == 0 )
       
   207         {
       
   208           switch ( type & 0x0F )
       
   209           {
       
   210           case 0x00:  /* string */
       
   211           case 0x01:  /* atoms */
       
   212             /* check that the content is really 0-terminated */
       
   213             if ( value < bdf->strings_size &&
       
   214                  ft_memchr( bdf->strings + value, 0, bdf->strings_size ) )
       
   215             {
       
   216               aprop->type   = BDF_PROPERTY_TYPE_ATOM;
       
   217               aprop->u.atom = (const char*)bdf->strings + value;
       
   218               error         = SFNT_Err_Ok;
       
   219               goto Exit;
       
   220             }
       
   221             break;
       
   222 
       
   223           case 0x02:
       
   224             aprop->type      = BDF_PROPERTY_TYPE_INTEGER;
       
   225             aprop->u.integer = (FT_Int32)value;
       
   226             error            = SFNT_Err_Ok;
       
   227             goto Exit;
       
   228 
       
   229           case 0x03:
       
   230             aprop->type       = BDF_PROPERTY_TYPE_CARDINAL;
       
   231             aprop->u.cardinal = value;
       
   232             error             = SFNT_Err_Ok;
       
   233             goto Exit;
       
   234 
       
   235           default:
       
   236             ;
       
   237           }
       
   238         }
       
   239       }
       
   240       p += 10;
       
   241     }
       
   242 
       
   243   Exit:
       
   244     return error;
       
   245   }
       
   246 
       
   247 #endif /* TT_CONFIG_OPTION_BDF */
       
   248 
       
   249 
       
   250 /* END */