(root)/
freetype-2.13.2/
src/
sfnt/
ttbdf.c
       1  /****************************************************************************
       2   *
       3   * ttbdf.c
       4   *
       5   *   TrueType and OpenType embedded BDF properties (body).
       6   *
       7   * Copyright (C) 2005-2023 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 <freetype/internal/ftdebug.h>
      20  #include <freetype/internal/ftstream.h>
      21  #include <freetype/tttags.h>
      22  #include "ttbdf.h"
      23  
      24  #include "sferrors.h"
      25  
      26  
      27  #ifdef TT_CONFIG_OPTION_BDF
      28  
      29    /**************************************************************************
      30     *
      31     * The macro FT_COMPONENT is used in trace mode.  It is an implicit
      32     * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
      33     * messages during execution.
      34     */
      35  #undef  FT_COMPONENT
      36  #define FT_COMPONENT  ttbdf
      37  
      38  
      39    FT_LOCAL_DEF( void )
      40    tt_face_free_bdf_props( TT_Face  face )
      41    {
      42      TT_BDF  bdf = &face->bdf;
      43  
      44  
      45      if ( bdf->loaded )
      46      {
      47        FT_Stream  stream = FT_FACE( face )->stream;
      48  
      49  
      50        if ( bdf->table )
      51          FT_FRAME_RELEASE( bdf->table );
      52  
      53        bdf->table_end    = NULL;
      54        bdf->strings      = NULL;
      55        bdf->strings_size = 0;
      56      }
      57    }
      58  
      59  
      60    static FT_Error
      61    tt_face_load_bdf_props( TT_Face    face,
      62                            FT_Stream  stream )
      63    {
      64      TT_BDF    bdf = &face->bdf;
      65      FT_ULong  length;
      66      FT_Error  error;
      67  
      68  
      69      FT_ZERO( bdf );
      70  
      71      error = tt_face_goto_table( face, TTAG_BDF, stream, &length );
      72      if ( error                                  ||
      73           length < 8                             ||
      74           FT_FRAME_EXTRACT( length, bdf->table ) )
      75      {
      76        error = FT_THROW( Invalid_Table );
      77        goto Exit;
      78      }
      79  
      80      bdf->table_end = bdf->table + length;
      81  
      82      {
      83        FT_Byte*   p           = bdf->table;
      84        FT_UInt    version     = FT_NEXT_USHORT( p );
      85        FT_UInt    num_strikes = FT_NEXT_USHORT( p );
      86        FT_ULong   strings     = FT_NEXT_ULONG ( p );
      87        FT_UInt    count;
      88        FT_Byte*   strike;
      89  
      90  
      91        if ( version != 0x0001                 ||
      92             strings < 8                       ||
      93             ( strings - 8 ) / 4 < num_strikes ||
      94             strings + 1 > length              )
      95        {
      96          goto BadTable;
      97        }
      98  
      99        bdf->num_strikes  = num_strikes;
     100        bdf->strings      = bdf->table + strings;
     101        bdf->strings_size = length - strings;
     102  
     103        count  = bdf->num_strikes;
     104        p      = bdf->table + 8;
     105        strike = p + count * 4;
     106  
     107  
     108        for ( ; count > 0; count-- )
     109        {
     110          FT_UInt  num_items = FT_PEEK_USHORT( p + 2 );
     111  
     112          /*
     113           * We don't need to check the value sets themselves, since this
     114           * is done later.
     115           */
     116          strike += 10 * num_items;
     117  
     118          p += 4;
     119        }
     120  
     121        if ( strike > bdf->strings )
     122          goto BadTable;
     123      }
     124  
     125      bdf->loaded = 1;
     126  
     127    Exit:
     128      return error;
     129  
     130    BadTable:
     131      FT_FRAME_RELEASE( bdf->table );
     132      FT_ZERO( bdf );
     133      error = FT_THROW( Invalid_Table );
     134      goto Exit;
     135    }
     136  
     137  
     138    FT_LOCAL_DEF( FT_Error )
     139    tt_face_find_bdf_prop( FT_Face           face,          /* TT_Face */
     140                           const char*       property_name,
     141                           BDF_PropertyRec  *aprop )
     142    {
     143      TT_Face    ttface = (TT_Face)face;
     144      TT_BDF     bdf    = &ttface->bdf;
     145      FT_Size    size   = FT_FACE_SIZE( face );
     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( ttface, FT_FACE_STREAM( face ) );
     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 */