ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

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         /* No unicode chars here! */
00370         FT_FREE( table->maps );
00371         if ( !error )
00372           error = PSnames_Err_No_Unicode_Glyph_Name;
00373       }
00374       else
00375       {
00376         /* Reallocate if the number of used entries is much smaller. */
00377         if ( count < num_glyphs / 2 )
00378         {
00379           (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );
00380           error = PSnames_Err_Ok;
00381         }
00382 
00383         /* Sort the table in increasing order of unicode values, */
00384         /* taking care of glyph variants.                        */
00385         ft_qsort( table->maps, count, sizeof ( PS_UniMap ),
00386                   compare_uni_maps );
00387       }
00388 
00389       table->num_maps = count;
00390     }
00391 
00392     return error;
00393   }
00394 
00395 
00396   static FT_UInt
00397   ps_unicodes_char_index( PS_Unicodes  table,
00398                           FT_UInt32    unicode )
00399   {
00400     PS_UniMap  *min, *max, *mid, *result = NULL;
00401 
00402 
00403     /* Perform a binary search on the table. */
00404 
00405     min = table->maps;
00406     max = min + table->num_maps - 1;
00407 
00408     while ( min <= max )
00409     {
00410       FT_UInt32  base_glyph;
00411 
00412 
00413       mid = min + ( ( max - min ) >> 1 );
00414 
00415       if ( mid->unicode == unicode )
00416       {
00417         result = mid;
00418         break;
00419       }
00420 
00421       base_glyph = BASE_GLYPH( mid->unicode );
00422 
00423       if ( base_glyph == unicode )
00424         result = mid; /* remember match but continue search for base glyph */
00425 
00426       if ( min == max )
00427         break;
00428 
00429       if ( base_glyph < unicode )
00430         min = mid + 1;
00431       else
00432         max = mid - 1;
00433     }
00434 
00435     if ( result )
00436       return result->glyph_index;
00437     else
00438       return 0;
00439   }
00440 
00441 
00442   static FT_UInt32
00443   ps_unicodes_char_next( PS_Unicodes  table,
00444                          FT_UInt32   *unicode )
00445   {
00446     FT_UInt    result    = 0;
00447     FT_UInt32  char_code = *unicode + 1;
00448 
00449 
00450     {
00451       FT_UInt     min = 0;
00452       FT_UInt     max = table->num_maps;
00453       FT_UInt     mid;
00454       PS_UniMap*  map;
00455       FT_UInt32   base_glyph;
00456 
00457 
00458       while ( min < max )
00459       {
00460         mid = min + ( ( max - min ) >> 1 );
00461         map = table->maps + mid;
00462 
00463         if ( map->unicode == char_code )
00464         {
00465           result = map->glyph_index;
00466           goto Exit;
00467         }
00468 
00469         base_glyph = BASE_GLYPH( map->unicode );
00470 
00471         if ( base_glyph == char_code )
00472           result = map->glyph_index;
00473 
00474         if ( base_glyph < char_code )
00475           min = mid + 1;
00476         else
00477           max = mid;
00478       }
00479 
00480       if ( result )
00481         goto Exit;               /* we have a variant glyph */
00482 
00483       /* we didn't find it; check whether we have a map just above it */
00484       char_code = 0;
00485 
00486       if ( min < table->num_maps )
00487       {
00488         map       = table->maps + min;
00489         result    = map->glyph_index;
00490         char_code = BASE_GLYPH( map->unicode );
00491       }
00492     }
00493 
00494   Exit:
00495     *unicode = char_code;
00496     return result;
00497   }
00498 
00499 
00500 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
00501 
00502 
00503   static const char*
00504   ps_get_macintosh_name( FT_UInt  name_index )
00505   {
00506     if ( name_index >= FT_NUM_MAC_NAMES )
00507       name_index = 0;
00508 
00509     return ft_standard_glyph_names + ft_mac_names[name_index];
00510   }
00511 
00512 
00513   static const char*
00514   ps_get_standard_strings( FT_UInt  sid )
00515   {
00516     if ( sid >= FT_NUM_SID_NAMES )
00517       return 0;
00518 
00519     return ft_standard_glyph_names + ft_sid_names[sid];
00520   }
00521 
00522 
00523 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
00524   FT_DEFINE_SERVICE_PSCMAPSREC(pscmaps_interface, 
00525     (PS_Unicode_ValueFunc)     ps_unicode_value,
00526     (PS_Unicodes_InitFunc)     ps_unicodes_init,
00527     (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,
00528     (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,
00529 
00530     (PS_Macintosh_NameFunc)    ps_get_macintosh_name,
00531     (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
00532 
00533     t1_standard_encoding,
00534     t1_expert_encoding
00535   )
00536 
00537 #else
00538 
00539   FT_DEFINE_SERVICE_PSCMAPSREC(pscmaps_interface, 
00540     0,
00541     0,
00542     0,
00543     0,
00544 
00545     (PS_Macintosh_NameFunc)    ps_get_macintosh_name,
00546     (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
00547 
00548     t1_standard_encoding,
00549     t1_expert_encoding
00550   )
00551 
00552 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
00553 
00554 
00555   FT_DEFINE_SERVICEDESCREC1(pscmaps_services, 
00556     FT_SERVICE_ID_POSTSCRIPT_CMAPS, &FT_PSCMAPS_INTERFACE_GET
00557   )
00558 
00559 
00560 
00561 
00562   static FT_Pointer
00563   psnames_get_service( FT_Module    module,
00564                        const char*  service_id )
00565   {
00566     FT_UNUSED( module );
00567 
00568     return ft_service_list_lookup( FT_PSCMAPS_SERVICES_GET, service_id );
00569   }
00570 
00571 #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
00572 
00573 
00574 #ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
00575 #define PUT_PS_NAMES_SERVICE(a) 0
00576 #else
00577 #define PUT_PS_NAMES_SERVICE(a) a
00578 #endif
00579 
00580   FT_DEFINE_MODULE(psnames_module_class,
00581   
00582     0,  /* this is not a font driver, nor a renderer */
00583     sizeof ( FT_ModuleRec ),
00584 
00585     "psnames",  /* driver name                         */
00586     0x10000L,   /* driver version                      */
00587     0x20000L,   /* driver requires FreeType 2 or above */
00588 
00589     PUT_PS_NAMES_SERVICE((void*)&FT_PSCMAPS_INTERFACE_GET),   /* module specific interface */
00590     (FT_Module_Constructor)0,
00591     (FT_Module_Destructor) 0,
00592     (FT_Module_Requester)  PUT_PS_NAMES_SERVICE(psnames_get_service)
00593   )
00594 
00595 
00596 
00597 /* END */

Generated on Sat May 26 2012 04:32:54 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.