Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpsmodule.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
1.7.6.1
|