(root)/
freetype-2.13.2/
src/
psnames/
psmodule.c
       1  /****************************************************************************
       2   *
       3   * psmodule.c
       4   *
       5   *   psnames module implementation (body).
       6   *
       7   * Copyright (C) 1996-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/ftobjs.h>
      21  #include <freetype/internal/services/svpscmap.h>
      22  
      23  #include "psmodule.h"
      24  
      25    /*
      26     * The file `pstables.h' with its arrays and its function
      27     * `ft_get_adobe_glyph_index' is useful for other projects also (for
      28     * example, `pdfium' is using it).  However, if used as a C++ header,
      29     * including it in two different source files makes it necessary to use
      30     * `extern const' for the declaration of its arrays, otherwise the data
      31     * would be duplicated as mandated by the C++ standard.
      32     *
      33     * For this reason, we use `DEFINE_PS_TABLES' to guard the function
      34     * definitions, and `DEFINE_PS_TABLES_DATA' to provide both proper array
      35     * declarations and definitions.
      36     */
      37  #include "pstables.h"
      38  #define  DEFINE_PS_TABLES
      39  #define  DEFINE_PS_TABLES_DATA
      40  #include "pstables.h"
      41  
      42  #include "psnamerr.h"
      43  
      44  
      45  #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
      46  
      47  
      48  #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
      49  
      50  
      51  #define VARIANT_BIT         0x80000000UL
      52  #define BASE_GLYPH( code )  ( (FT_UInt32)( (code) & ~VARIANT_BIT ) )
      53  
      54  
      55    /* Return the Unicode value corresponding to a given glyph.  Note that */
      56    /* we do deal with glyph variants by detecting a non-initial dot in    */
      57    /* the name, as in `A.swash' or `e.final'; in this case, the           */
      58    /* VARIANT_BIT is set in the return value.                             */
      59    /*                                                                     */
      60    FT_CALLBACK_DEF( FT_UInt32 )
      61    ps_unicode_value( const char*  glyph_name )
      62    {
      63      /* If the name begins with `uni', then the glyph name may be a */
      64      /* hard-coded unicode character code.                          */
      65      if ( glyph_name[0] == 'u' &&
      66           glyph_name[1] == 'n' &&
      67           glyph_name[2] == 'i' )
      68      {
      69        /* determine whether the next four characters following are */
      70        /* hexadecimal.                                             */
      71  
      72        /* XXX: Add code to deal with ligatures, i.e. glyph names like */
      73        /*      `uniXXXXYYYYZZZZ'...                                   */
      74  
      75        FT_Int       count;
      76        FT_UInt32    value = 0;
      77        const char*  p     = glyph_name + 3;
      78  
      79  
      80        for ( count = 4; count > 0; count--, p++ )
      81        {
      82          char          c = *p;
      83          unsigned int  d;
      84  
      85  
      86          d = (unsigned char)c - '0';
      87          if ( d >= 10 )
      88          {
      89            d = (unsigned char)c - 'A';
      90            if ( d >= 6 )
      91              d = 16;
      92            else
      93              d += 10;
      94          }
      95  
      96          /* Exit if a non-uppercase hexadecimal character was found   */
      97          /* -- this also catches character codes below `0' since such */
      98          /* negative numbers cast to `unsigned int' are far too big.  */
      99          if ( d >= 16 )
     100            break;
     101  
     102          value = ( value << 4 ) + d;
     103        }
     104  
     105        /* there must be exactly four hex digits */
     106        if ( count == 0 )
     107        {
     108          if ( *p == '\0' )
     109            return value;
     110          if ( *p == '.' )
     111            return (FT_UInt32)( value | VARIANT_BIT );
     112        }
     113      }
     114  
     115      /* If the name begins with `u', followed by four to six uppercase */
     116      /* hexadecimal digits, it is a hard-coded unicode character code. */
     117      if ( glyph_name[0] == 'u' )
     118      {
     119        FT_Int       count;
     120        FT_UInt32    value = 0;
     121        const char*  p     = glyph_name + 1;
     122  
     123  
     124        for ( count = 6; count > 0; count--, p++ )
     125        {
     126          char          c = *p;
     127          unsigned int  d;
     128  
     129  
     130          d = (unsigned char)c - '0';
     131          if ( d >= 10 )
     132          {
     133            d = (unsigned char)c - 'A';
     134            if ( d >= 6 )
     135              d = 16;
     136            else
     137              d += 10;
     138          }
     139  
     140          if ( d >= 16 )
     141            break;
     142  
     143          value = ( value << 4 ) + d;
     144        }
     145  
     146        if ( count <= 2 )
     147        {
     148          if ( *p == '\0' )
     149            return value;
     150          if ( *p == '.' )
     151            return (FT_UInt32)( value | VARIANT_BIT );
     152        }
     153      }
     154  
     155      /* Look for a non-initial dot in the glyph name in order to */
     156      /* find variants like `A.swash', `e.final', etc.            */
     157      {
     158        FT_UInt32    value = 0;
     159        const char*  p     = glyph_name;
     160  
     161  
     162        for ( ; *p && *p != '.'; p++ )
     163          ;
     164  
     165        /* now look up the glyph in the Adobe Glyph List;      */
     166        /* `.notdef', `.null' and the empty name are short cut */
     167        if ( p > glyph_name )
     168        {
     169          value = (FT_UInt32)ft_get_adobe_glyph_index( glyph_name, p );
     170  
     171          if ( *p == '.' )
     172            value |= (FT_UInt32)VARIANT_BIT;
     173        }
     174  
     175        return value;
     176      }
     177    }
     178  
     179  
     180    /* ft_qsort callback to sort the unicode map */
     181    FT_COMPARE_DEF( int )
     182    compare_uni_maps( const void*  a,
     183                      const void*  b )
     184    {
     185      PS_UniMap*  map1 = (PS_UniMap*)a;
     186      PS_UniMap*  map2 = (PS_UniMap*)b;
     187      FT_UInt32   unicode1 = BASE_GLYPH( map1->unicode );
     188      FT_UInt32   unicode2 = BASE_GLYPH( map2->unicode );
     189  
     190  
     191      /* sort base glyphs before glyph variants */
     192      if ( unicode1 == unicode2 )
     193      {
     194        if ( map1->unicode > map2->unicode )
     195          return 1;
     196        else if ( map1->unicode < map2->unicode )
     197          return -1;
     198        else
     199          return 0;
     200      }
     201      else
     202      {
     203        if ( unicode1 > unicode2 )
     204          return 1;
     205        else if ( unicode1 < unicode2 )
     206          return -1;
     207        else
     208          return 0;
     209      }
     210    }
     211  
     212  
     213    /* support for extra glyphs not handled (well) in AGL; */
     214    /* we add extra mappings for them if necessary         */
     215  
     216  #define EXTRA_GLYPH_LIST_SIZE  10
     217  
     218    static const FT_UInt32  ft_extra_glyph_unicodes[EXTRA_GLYPH_LIST_SIZE] =
     219    {
     220      /* WGL 4 */
     221      0x0394,
     222      0x03A9,
     223      0x2215,
     224      0x00AD,
     225      0x02C9,
     226      0x03BC,
     227      0x2219,
     228      0x00A0,
     229      /* Romanian */
     230      0x021A,
     231      0x021B
     232    };
     233  
     234    static const char  ft_extra_glyph_names[] =
     235    {
     236      'D','e','l','t','a',0,
     237      'O','m','e','g','a',0,
     238      'f','r','a','c','t','i','o','n',0,
     239      'h','y','p','h','e','n',0,
     240      'm','a','c','r','o','n',0,
     241      'm','u',0,
     242      'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0,
     243      's','p','a','c','e',0,
     244      'T','c','o','m','m','a','a','c','c','e','n','t',0,
     245      't','c','o','m','m','a','a','c','c','e','n','t',0
     246    };
     247  
     248    static const FT_Int
     249    ft_extra_glyph_name_offsets[EXTRA_GLYPH_LIST_SIZE] =
     250    {
     251       0,
     252       6,
     253      12,
     254      21,
     255      28,
     256      35,
     257      38,
     258      53,
     259      59,
     260      72
     261    };
     262  
     263  
     264    static void
     265    ps_check_extra_glyph_name( const char*  gname,
     266                               FT_UInt      glyph,
     267                               FT_UInt*     extra_glyphs,
     268                               FT_UInt     *states )
     269    {
     270      FT_UInt  n;
     271  
     272  
     273      for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
     274      {
     275        if ( ft_strcmp( ft_extra_glyph_names +
     276                          ft_extra_glyph_name_offsets[n], gname ) == 0 )
     277        {
     278          if ( states[n] == 0 )
     279          {
     280            /* mark this extra glyph as a candidate for the cmap */
     281            states[n]     = 1;
     282            extra_glyphs[n] = glyph;
     283          }
     284  
     285          return;
     286        }
     287      }
     288    }
     289  
     290  
     291    static void
     292    ps_check_extra_glyph_unicode( FT_UInt32  uni_char,
     293                                  FT_UInt   *states )
     294    {
     295      FT_UInt  n;
     296  
     297  
     298      for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
     299      {
     300        if ( uni_char == ft_extra_glyph_unicodes[n] )
     301        {
     302          /* disable this extra glyph from being added to the cmap */
     303          states[n] = 2;
     304  
     305          return;
     306        }
     307      }
     308    }
     309  
     310  
     311    /* Build a table that maps Unicode values to glyph indices. */
     312    FT_CALLBACK_DEF( FT_Error )
     313    ps_unicodes_init( FT_Memory             memory,
     314                      PS_Unicodes           table,
     315                      FT_UInt               num_glyphs,
     316                      PS_GetGlyphNameFunc   get_glyph_name,
     317                      PS_FreeGlyphNameFunc  free_glyph_name,
     318                      FT_Pointer            glyph_data )
     319    {
     320      FT_Error  error;
     321  
     322      FT_UInt  extra_glyph_list_states[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
     323      FT_UInt  extra_glyphs[EXTRA_GLYPH_LIST_SIZE];
     324  
     325  
     326      /* we first allocate the table */
     327      table->num_maps = 0;
     328  
     329      if ( !FT_QNEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) )
     330      {
     331        FT_UInt     n;
     332        FT_UInt     count;
     333        PS_UniMap*  map;
     334        FT_UInt32   uni_char;
     335  
     336  
     337        map = table->maps;
     338  
     339        for ( n = 0; n < num_glyphs; n++ )
     340        {
     341          const char*  gname = get_glyph_name( glyph_data, n );
     342  
     343  
     344          if ( gname && *gname )
     345          {
     346            ps_check_extra_glyph_name( gname, n,
     347                                       extra_glyphs, extra_glyph_list_states );
     348            uni_char = ps_unicode_value( gname );
     349  
     350            if ( BASE_GLYPH( uni_char ) != 0 )
     351            {
     352              ps_check_extra_glyph_unicode( uni_char,
     353                                            extra_glyph_list_states );
     354              map->unicode     = uni_char;
     355              map->glyph_index = n;
     356              map++;
     357            }
     358  
     359            if ( free_glyph_name )
     360              free_glyph_name( glyph_data, gname );
     361          }
     362        }
     363  
     364        for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
     365        {
     366          if ( extra_glyph_list_states[n] == 1 )
     367          {
     368            /* This glyph name has an additional representation. */
     369            /* Add it to the cmap.                               */
     370  
     371            map->unicode     = ft_extra_glyph_unicodes[n];
     372            map->glyph_index = extra_glyphs[n];
     373            map++;
     374          }
     375        }
     376  
     377        /* now compress the table a bit */
     378        count = (FT_UInt)( map - table->maps );
     379  
     380        if ( count == 0 )
     381        {
     382          /* No unicode chars here! */
     383          FT_FREE( table->maps );
     384          if ( !error )
     385            error = FT_THROW( No_Unicode_Glyph_Name );
     386        }
     387        else
     388        {
     389          /* Reallocate if the number of used entries is much smaller. */
     390          if ( count < num_glyphs / 2 )
     391          {
     392            FT_MEM_QRENEW_ARRAY( table->maps,
     393                                 num_glyphs + EXTRA_GLYPH_LIST_SIZE,
     394                                 count );
     395            error = FT_Err_Ok;
     396          }
     397  
     398          /* Sort the table in increasing order of unicode values, */
     399          /* taking care of glyph variants.                        */
     400          ft_qsort( table->maps, count, sizeof ( PS_UniMap ),
     401                    compare_uni_maps );
     402        }
     403  
     404        table->num_maps = count;
     405      }
     406  
     407      return error;
     408    }
     409  
     410  
     411    FT_CALLBACK_DEF( FT_UInt )
     412    ps_unicodes_char_index( PS_Unicodes  table,
     413                            FT_UInt32    unicode )
     414    {
     415      PS_UniMap  *result = NULL;
     416      PS_UniMap  *min = table->maps;
     417      PS_UniMap  *max = min + table->num_maps;
     418      PS_UniMap  *mid = min + ( ( max - min ) >> 1 );
     419  
     420  
     421      /* Perform a binary search on the table. */
     422      while ( min < max )
     423      {
     424        FT_UInt32  base_glyph;
     425  
     426  
     427        if ( mid->unicode == unicode )
     428        {
     429          result = mid;
     430          break;
     431        }
     432  
     433        base_glyph = BASE_GLYPH( mid->unicode );
     434  
     435        if ( base_glyph == unicode )
     436          result = mid; /* remember match but continue search for base glyph */
     437  
     438        if ( base_glyph < unicode )
     439          min = mid + 1;
     440        else
     441          max = mid;
     442  
     443        /* reasonable prediction in a continuous block */
     444        mid += unicode - base_glyph;
     445        if ( mid >= max || mid < min )
     446          mid = min + ( ( max - min ) >> 1 );
     447      }
     448  
     449      if ( result )
     450        return result->glyph_index;
     451      else
     452        return 0;
     453    }
     454  
     455  
     456    FT_CALLBACK_DEF( FT_UInt )
     457    ps_unicodes_char_next( PS_Unicodes  table,
     458                           FT_UInt32   *unicode )
     459    {
     460      FT_UInt    result    = 0;
     461      FT_UInt32  char_code = *unicode + 1;
     462  
     463  
     464      {
     465        FT_UInt     min = 0;
     466        FT_UInt     max = table->num_maps;
     467        FT_UInt     mid = min + ( ( max - min ) >> 1 );
     468        PS_UniMap*  map;
     469        FT_UInt32   base_glyph;
     470  
     471  
     472        while ( min < max )
     473        {
     474          map = table->maps + mid;
     475  
     476          if ( map->unicode == char_code )
     477          {
     478            result = map->glyph_index;
     479            goto Exit;
     480          }
     481  
     482          base_glyph = BASE_GLYPH( map->unicode );
     483  
     484          if ( base_glyph == char_code )
     485            result = map->glyph_index;
     486  
     487          if ( base_glyph < char_code )
     488            min = mid + 1;
     489          else
     490            max = mid;
     491  
     492          /* reasonable prediction in a continuous block */
     493          mid += char_code - base_glyph;
     494          if ( mid >= max || mid < min )
     495            mid = min + ( max - min ) / 2;
     496        }
     497  
     498        if ( result )
     499          goto Exit;               /* we have a variant glyph */
     500  
     501        /* we didn't find it; check whether we have a map just above it */
     502        char_code = 0;
     503  
     504        if ( min < table->num_maps )
     505        {
     506          map       = table->maps + min;
     507          result    = map->glyph_index;
     508          char_code = BASE_GLYPH( map->unicode );
     509        }
     510      }
     511  
     512    Exit:
     513      *unicode = char_code;
     514      return result;
     515    }
     516  
     517  
     518  #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
     519  
     520  
     521    FT_CALLBACK_DEF( const char* )
     522    ps_get_macintosh_name( FT_UInt  name_index )
     523    {
     524      if ( name_index >= FT_NUM_MAC_NAMES )
     525        name_index = 0;
     526  
     527      return ft_standard_glyph_names + ft_mac_names[name_index];
     528    }
     529  
     530  
     531    FT_CALLBACK_DEF( const char* )
     532    ps_get_standard_strings( FT_UInt  sid )
     533    {
     534      if ( sid >= FT_NUM_SID_NAMES )
     535        return 0;
     536  
     537      return ft_standard_glyph_names + ft_sid_names[sid];
     538    }
     539  
     540  
     541  #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
     542  
     543    FT_DEFINE_SERVICE_PSCMAPSREC(
     544      pscmaps_interface,
     545  
     546      ps_unicode_value,         /* PS_Unicode_ValueFunc      unicode_value         */
     547      ps_unicodes_init,         /* PS_Unicodes_InitFunc      unicodes_init         */
     548      ps_unicodes_char_index,   /* PS_Unicodes_CharIndexFunc unicodes_char_index   */
     549      ps_unicodes_char_next,    /* PS_Unicodes_CharNextFunc  unicodes_char_next    */
     550  
     551      ps_get_macintosh_name,    /* PS_Macintosh_NameFunc     macintosh_name        */
     552      ps_get_standard_strings,  /* PS_Adobe_Std_StringsFunc  adobe_std_strings     */
     553  
     554      t1_standard_encoding,                               /* adobe_std_encoding    */
     555      t1_expert_encoding                                  /* adobe_expert_encoding */
     556    )
     557  
     558  #else
     559  
     560    FT_DEFINE_SERVICE_PSCMAPSREC(
     561      pscmaps_interface,
     562  
     563      NULL,                     /* PS_Unicode_ValueFunc      unicode_value         */
     564      NULL,                     /* PS_Unicodes_InitFunc      unicodes_init         */
     565      NULL,                     /* PS_Unicodes_CharIndexFunc unicodes_char_index   */
     566      NULL,                     /* PS_Unicodes_CharNextFunc  unicodes_char_next    */
     567  
     568      ps_get_macintosh_name,    /* PS_Macintosh_NameFunc     macintosh_name        */
     569      ps_get_standard_strings,  /* PS_Adobe_Std_StringsFunc  adobe_std_strings     */
     570  
     571      t1_standard_encoding,                               /* adobe_std_encoding    */
     572      t1_expert_encoding                                  /* adobe_expert_encoding */
     573    )
     574  
     575  #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
     576  
     577  
     578    FT_DEFINE_SERVICEDESCREC1(
     579      pscmaps_services,
     580  
     581      FT_SERVICE_ID_POSTSCRIPT_CMAPS, &pscmaps_interface )
     582  
     583  
     584    static FT_Pointer
     585    psnames_get_service( FT_Module    module,
     586                         const char*  service_id )
     587    {
     588      FT_UNUSED( module );
     589  
     590      return ft_service_list_lookup( pscmaps_services, service_id );
     591    }
     592  
     593  #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
     594  
     595  
     596  #ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
     597  #define PUT_PS_NAMES_SERVICE( a )  NULL
     598  #else
     599  #define PUT_PS_NAMES_SERVICE( a )  a
     600  #endif
     601  
     602    FT_DEFINE_MODULE(
     603      psnames_module_class,
     604  
     605      0,  /* this is not a font driver, nor a renderer */
     606      sizeof ( FT_ModuleRec ),
     607  
     608      "psnames",  /* driver name                         */
     609      0x10000L,   /* driver version                      */
     610      0x20000L,   /* driver requires FreeType 2 or above */
     611  
     612      PUT_PS_NAMES_SERVICE(
     613        (void*)&pscmaps_interface ),   /* module specific interface */
     614  
     615      NULL,                                        /* FT_Module_Constructor module_init   */
     616      NULL,                                        /* FT_Module_Destructor  module_done   */
     617      PUT_PS_NAMES_SERVICE( psnames_get_service )  /* FT_Module_Requester   get_interface */
     618    )
     619  
     620  
     621  /* END */