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