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