psmodule.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  psmodule.c                                                             */
00004 /*                                                                         */
00005 /*    PSNames module implementation (body).                                */
00006 /*                                                                         */
00007 /*  Copyright 1996-2001, 2002, 2003, 2005, 2006, 2007, 2008 by             */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 
00019 #include <ft2build.h>
00020 #include FT_INTERNAL_OBJECTS_H
00021 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
00022 
00023 #include "psmodule.h"
00024 #include "pstables.h"
00025 
00026 #include "psnamerr.h"
00027 #include "pspic.h"
00028 
00029 
00030 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
00031 
00032 
00033 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
00034 
00035 
00036 #define VARIANT_BIT         0x80000000UL
00037 #define BASE_GLYPH( code )  ( (FT_UInt32)( (code) & ~VARIANT_BIT ) )
00038 
00039 
00040   /* Return the Unicode value corresponding to a given glyph.  Note that */
00041   /* we do deal with glyph variants by detecting a non-initial dot in    */
00042   /* the name, as in `A.swash' or `e.final'; in this case, the           */
00043   /* VARIANT_BIT is set in the return value.                             */
00044   /*                                                                     */
00045   static FT_UInt32
00046   ps_unicode_value( const char*  glyph_name )
00047   {
00048     /* If the name begins with `uni', then the glyph name may be a */
00049     /* hard-coded unicode character code.                          */
00050     if ( glyph_name[0] == 'u' &&
00051          glyph_name[1] == 'n' &&
00052          glyph_name[2] == 'i' )
00053     {
00054       /* determine whether the next four characters following are */
00055       /* hexadecimal.                                             */
00056 
00057       /* XXX: Add code to deal with ligatures, i.e. glyph names like */
00058       /*      `uniXXXXYYYYZZZZ'...                                   */
00059 
00060       FT_Int       count;
00061       FT_UInt32    value = 0;
00062       const char*  p     = glyph_name + 3;
00063 
00064 
00065       for ( count = 4; count > 0; count--, p++ )
00066       {
00067         char          c = *p;
00068         unsigned int  d;
00069 
00070 
00071         d = (unsigned char)c - '0';
00072         if ( d >= 10 )
00073         {
00074           d = (unsigned char)c - 'A';
00075           if ( d >= 6 )
00076             d = 16;
00077           else
00078             d += 10;
00079         }
00080 
00081         /* Exit if a non-uppercase hexadecimal character was found   */
00082         /* -- this also catches character codes below `0' since such */
00083         /* negative numbers cast to `unsigned int' are far too big.  */
00084         if ( d >= 16 )
00085           break;
00086 
00087         value = ( value << 4 ) + d;
00088       }
00089 
00090       /* there must be exactly four hex digits */
00091       if ( count == 0 )
00092       {
00093         if ( *p == '\0' )
00094           return value;
00095         if ( *p == '.' )
00096           return (FT_UInt32)( value | VARIANT_BIT );
00097       }
00098     }
00099 
00100     /* If the name begins with `u', followed by four to six uppercase */
00101     /* hexadecimal digits, it is a hard-coded unicode character code. */
00102     if ( glyph_name[0] == 'u' )
00103     {
00104       FT_Int       count;
00105       FT_UInt32    value = 0;
00106       const char*  p     = glyph_name + 1;
00107 
00108 
00109       for ( count = 6; count > 0; count--, p++ )
00110       {
00111         char          c = *p;
00112         unsigned int  d;
00113 
00114 
00115         d = (unsigned char)c - '0';
00116         if ( d >= 10 )
00117         {
00118           d = (unsigned char)c - 'A';
00119           if ( d >= 6 )
00120             d = 16;
00121           else
00122             d += 10;
00123         }
00124 
00125         if ( d >= 16 )
00126           break;
00127 
00128         value = ( value << 4 ) + d;
00129       }
00130 
00131       if ( count <= 2 )
00132       {
00133         if ( *p == '\0' )
00134           return value;
00135         if ( *p == '.' )
00136           return (FT_UInt32)( value | VARIANT_BIT );
00137       }
00138     }
00139 
00140     /* Look for a non-initial dot in the glyph name in order to */
00141     /* find variants like `A.swash', `e.final', etc.            */
00142     {
00143       const char*  p   = glyph_name;
00144       const char*  dot = NULL;
00145 
00146 
00147       for ( ; *p; p++ )
00148       {
00149         if ( *p == '.' && p > glyph_name )
00150         {
00151           dot = p;
00152           break;
00153         }
00154       }
00155 
00156       /* now look up the glyph in the Adobe Glyph List */
00157       if ( !dot )
00158         return (FT_UInt32)ft_get_adobe_glyph_index( glyph_name, p );
00159       else
00160         return (FT_UInt32)( ft_get_adobe_glyph_index( glyph_name, dot ) |
00161                             VARIANT_BIT );
00162     }
00163   }
00164 
00165 
00166   /* ft_qsort callback to sort the unicode map */
00167   FT_CALLBACK_DEF( int )
00168   compare_uni_maps( const void*  a,
00169                     const void*  b )
00170   {
00171     PS_UniMap*  map1 = (PS_UniMap*)a;
00172     PS_UniMap*  map2 = (PS_UniMap*)b;
00173     FT_UInt32   unicode1 = BASE_GLYPH( map1->unicode );
00174     FT_UInt32   unicode2 = BASE_GLYPH( map2->unicode );
00175 
00176 
00177     /* sort base glyphs before glyph variants */
00178     if ( unicode1 == unicode2 )
00179     {
00180       if ( map1->unicode > map2->unicode )
00181         return 1;
00182       else if ( map1->unicode < map2->unicode )
00183         return -1;
00184       else
00185         return 0;
00186     }
00187     else
00188     {
00189       if ( unicode1 > unicode2 )
00190         return 1;
00191       else if ( unicode1 < unicode2 )
00192         return -1;
00193       else
00194         return 0;
00195     }
00196   }
00197 
00198 
00199   /* support for extra glyphs not handled (well) in AGL; */
00200   /* we add extra mappings for them if necessary         */
00201 
00202 #define EXTRA_GLYPH_LIST_SIZE  10
00203 
00204   static const FT_UInt32  ft_extra_glyph_unicodes[EXTRA_GLYPH_LIST_SIZE] =
00205   {
00206     /* WGL 4 */
00207     0x0394,
00208     0x03A9,
00209     0x2215,
00210     0x00AD,
00211     0x02C9,
00212     0x03BC,
00213     0x2219,
00214     0x00A0,
00215     /* Romanian */
00216     0x021A,
00217     0x021B
00218   };
00219 
00220   static const char  ft_extra_glyph_names[] =
00221   {
00222     'D','e','l','t','a',0,
00223     'O','m','e','g','a',0,
00224     'f','r','a','c','t','i','o','n',0,
00225     'h','y','p','h','e','n',0,
00226     'm','a','c','r','o','n',0,
00227     'm','u',0,
00228     'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0,
00229     's','p','a','c','e',0,
00230     'T','c','o','m','m','a','a','c','c','e','n','t',0,
00231     't','c','o','m','m','a','a','c','c','e','n','t',0
00232   };
00233 
00234   static const FT_Int
00235   ft_extra_glyph_name_offsets[EXTRA_GLYPH_LIST_SIZE] =
00236   {
00237      0,
00238      6,
00239     12,
00240     21,
00241     28,
00242     35,
00243     38,
00244     53,
00245     59,
00246     72
00247   };
00248 
00249 
00250   static void
00251   ps_check_extra_glyph_name( const char*  gname,
00252                              FT_UInt      glyph,
00253                              FT_UInt*     extra_glyphs,
00254                              FT_UInt     *states )
00255   {
00256     FT_UInt  n;
00257 
00258 
00259     for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
00260     {
00261       if ( ft_strcmp( ft_extra_glyph_names +
00262                         ft_extra_glyph_name_offsets[n], gname ) == 0 )
00263       {
00264         if ( states[n] == 0 )
00265         {
00266           /* mark this extra glyph as a candidate for the cmap */
00267           states[n]     = 1;
00268           extra_glyphs[n] = glyph;
00269         }
00270 
00271         return;
00272       }
00273     }
00274   }
00275 
00276 
00277   static void
00278   ps_check_extra_glyph_unicode( FT_UInt32  uni_char,
00279                                 FT_UInt   *states )
00280   {
00281     FT_UInt  n;
00282 
00283 
00284     for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
00285     {
00286       if ( uni_char == ft_extra_glyph_unicodes[n] )
00287       {
00288         /* disable this extra glyph from being added to the cmap */
00289         states[n] = 2;
00290 
00291         return;
00292       }
00293     }
00294   }
00295 
00296 
00297   /* Build a table that maps Unicode values to glyph indices. */
00298   static FT_Error
00299   ps_unicodes_init( FT_Memory             memory,
00300                     PS_Unicodes           table,
00301                     FT_UInt               num_glyphs,
00302                     PS_GetGlyphNameFunc   get_glyph_name,
00303                     PS_FreeGlyphNameFunc  free_glyph_name,
00304                     FT_Pointer            glyph_data )
00305   {
00306     FT_Error  error;
00307 
00308     FT_UInt  extra_glyph_list_states[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
00309     FT_UInt  extra_glyphs[EXTRA_GLYPH_LIST_SIZE];
00310 
00311 
00312     /* we first allocate the table */
00313     table->num_maps = 0;
00314     table->maps     = 0;
00315 
00316     if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) )
00317     {
00318       FT_UInt     n;
00319       FT_UInt     count;
00320       PS_UniMap*  map;
00321       FT_UInt32   uni_char;
00322 
00323 
00324       map = table->maps;
00325 
00326       for ( n = 0; n < num_glyphs; n++ )
00327       {
00328         const char*  gname = get_glyph_name( glyph_data, n );
00329 
00330 
00331         if ( gname )
00332         {
00333           ps_check_extra_glyph_name( gname, n,
00334                                      extra_glyphs, extra_glyph_list_states );
00335           uni_char = ps_unicode_value( gname );
00336 
00337           if ( BASE_GLYPH( uni_char ) != 0 )
00338           {
00339             ps_check_extra_glyph_unicode( uni_char,
00340                                           extra_glyph_list_states );
00341             map->unicode     = uni_char;
00342             map->glyph_index = n;
00343             map++;
00344           }
00345 
00346           if ( free_glyph_name )
00347             free_glyph_name( glyph_data, gname );
00348         }
00349       }
00350 
00351       for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
00352       {
00353         if ( extra_glyph_list_states[n] == 1 )
00354         {
00355           /* This glyph name has an additional representation. */
00356           /* Add it to the cmap.                               */
00357 
00358           map->unicode     = ft_extra_glyph_unicodes[n];
00359           map->glyph_index = extra_glyphs[n];
00360           map++;
00361         }
00362       }
00363 
00364       /* now compress the table a bit */
00365       count = (FT_UInt)( map - table->maps );
00366 
00367       if ( count == 0 )
00368       {
00369         FT_FREE( table->maps );
00370         if ( !error )
00371           error = PSnames_Err_Invalid_Argument;  /* No unicode chars here! */
00372       }
00373       else {
00374         /* Reallocate if the number of used entries is much smaller. */
00375         if ( count < num_glyphs / 2 )
00376         {
00377           (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );
00378           error = PSnames_Err_Ok;
00379         }
00380 
00381         /* Sort the table in increasing order of unicode values, */
00382         /* taking care of glyph variants.                        */
00383         ft_qsort( table->maps, count, sizeof ( PS_UniMap ),
00384                   compare_uni_maps );
00385       }
00386 
00387       table->num_maps = count;
00388     }
00389 
00390     return error;
00391   }
00392 
00393 
00394   static FT_UInt
00395   ps_unicodes_char_index( PS_Unicodes  table,
00396                           FT_UInt32    unicode )
00397   {
00398     PS_UniMap  *min, *max, *mid, *result = NULL;
00399 
00400 
00401     /* Perform a binary search on the table. */
00402 
00403     min = table->maps;
00404     max = min + table->num_maps - 1;
00405 
00406     while ( min <= max )
00407     {
00408       FT_UInt32  base_glyph;
00409 
00410 
00411       mid = min + ( ( max - min ) >> 1 );
00412 
00413       if ( mid->unicode == unicode )
00414       {
00415         result = mid;
00416         break;
00417       }
00418 
00419       base_glyph = BASE_GLYPH( mid->unicode );
00420 
00421       if ( base_glyph == unicode )
00422         result = mid; /* remember match but continue search for base glyph */
00423 
00424       if ( min == max )
00425         break;
00426 
00427       if ( base_glyph < unicode )
00428         min = mid + 1;
00429       else
00430         max = mid - 1;
00431     }
00432 
00433     if ( result )
00434       return result->glyph_index;
00435     else
00436       return 0;
00437   }
00438 
00439 
00440   static FT_UInt32
00441   ps_unicodes_char_next( PS_Unicodes  table,
00442                          FT_UInt32   *unicode )
00443   {
00444     FT_UInt    result    = 0;
00445     FT_UInt32  char_code = *unicode + 1;
00446 
00447 
00448     {
00449       FT_UInt     min = 0;
00450       FT_UInt     max = table->num_maps;
00451       FT_UInt     mid;
00452       PS_UniMap*  map;
00453       FT_UInt32   base_glyph;
00454 
00455 
00456       while ( min < max )
00457       {
00458         mid = min + ( ( max - min ) >> 1 );
00459         map = table->maps + mid;
00460 
00461         if ( map->unicode == char_code )
00462         {
00463           result = map->glyph_index;
00464           goto Exit;
00465         }
00466 
00467         base_glyph = BASE_GLYPH( map->unicode );
00468 
00469         if ( base_glyph == char_code )
00470           result = map->glyph_index;
00471 
00472         if ( base_glyph < char_code )
00473           min = mid + 1;
00474         else
00475           max = mid;
00476       }
00477 
00478       if ( result )
00479         goto Exit;               /* we have a variant glyph */
00480 
00481       /* we didn't find it; check whether we have a map just above it */
00482       char_code = 0;
00483 
00484       if ( min < table->num_maps )
00485       {
00486         map       = table->maps + min;
00487         result    = map->glyph_index;
00488         char_code = BASE_GLYPH( map->unicode );
00489       }
00490     }
00491 
00492   Exit:
00493     *unicode = char_code;
00494     return result;
00495   }
00496 
00497 
00498 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
00499 
00500 
00501   static const char*
00502   ps_get_macintosh_name( FT_UInt  name_index )
00503   {
00504     if ( name_index >= FT_NUM_MAC_NAMES )
00505       name_index = 0;
00506 
00507     return ft_standard_glyph_names + ft_mac_names[name_index];
00508   }
00509 
00510 
00511   static const char*
00512   ps_get_standard_strings( FT_UInt  sid )
00513   {
00514     if ( sid >= FT_NUM_SID_NAMES )
00515       return 0;
00516 
00517     return ft_standard_glyph_names + ft_sid_names[sid];
00518   }
00519 
00520 
00521 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
00522   FT_DEFINE_SERVICE_PSCMAPSREC(pscmaps_interface, 
00523     (PS_Unicode_ValueFunc)     ps_unicode_value,
00524     (PS_Unicodes_InitFunc)     ps_unicodes_init,
00525     (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,
00526     (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,
00527 
00528     (PS_Macintosh_NameFunc)    ps_get_macintosh_name,
00529     (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
00530 
00531     t1_standard_encoding,
00532     t1_expert_encoding
00533   )
00534 
00535 #else
00536 
00537   FT_DEFINE_SERVICE_PSCMAPSREC(pscmaps_interface, 
00538     0,
00539     0,
00540     0,
00541     0,
00542 
00543     (PS_Macintosh_NameFunc)    ps_get_macintosh_name,
00544     (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
00545 
00546     t1_standard_encoding,
00547     t1_expert_encoding
00548   )
00549 
00550 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
00551 
00552 
00553   FT_DEFINE_SERVICEDESCREC1(pscmaps_services, 
00554     FT_SERVICE_ID_POSTSCRIPT_CMAPS, &FT_PSCMAPS_INTERFACE_GET
00555   )
00556 
00557 
00558 
00559 
00560   static FT_Pointer
00561   psnames_get_service( FT_Module    module,
00562                        const char*  service_id )
00563   {
00564     FT_UNUSED( module );
00565 
00566     return ft_service_list_lookup( FT_PSCMAPS_SERVICES_GET, service_id );
00567   }
00568 
00569 #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
00570 
00571 
00572 #ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
00573 #define PUT_PS_NAMES_SERVICE(a) 0
00574 #else
00575 #define PUT_PS_NAMES_SERVICE(a) a
00576 #endif
00577 
00578   FT_DEFINE_MODULE(psnames_module_class,
00579   
00580     0,  /* this is not a font driver, nor a renderer */
00581     sizeof ( FT_ModuleRec ),
00582 
00583     "psnames",  /* driver name                         */
00584     0x10000L,   /* driver version                      */
00585     0x20000L,   /* driver requires FreeType 2 or above */
00586 
00587     PUT_PS_NAMES_SERVICE((void*)&FT_PSCMAPS_INTERFACE_GET),   /* module specific interface */
00588     (FT_Module_Constructor)0,
00589     (FT_Module_Destructor) 0,
00590     (FT_Module_Requester)  PUT_PS_NAMES_SERVICE(psnames_get_service)
00591   )
00592 
00593 
00594 
00595 /* END */

Generated on Tue Jul 5 14:13:50 2011 for ROOT_528-00b_version by  doxygen 1.5.1