1 /****************************************************************************
5 * psnames module implementation (body).
7 * Copyright (C) 1996-2020 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
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.
19 #include <freetype/internal/ftdebug.h>
20 #include <freetype/internal/ftobjs.h>
21 #include <freetype/internal/services/svpscmap.h>
26 * The file `pstables.h' with its arrays and its function
27 * `ft_get_adobe_glyph_index' is useful for other projects also (for
28 * example, `pdfium' is using it). However, if used as a C++ header,
29 * including it in two different source files makes it necessary to use
30 * `extern const' for the declaration of its arrays, otherwise the data
31 * would be duplicated as mandated by the C++ standard.
33 * For this reason, we use `DEFINE_PS_TABLES' to guard the function
34 * definitions, and `DEFINE_PS_TABLES_DATA' to provide both proper array
35 * declarations and definitions.
38 #define DEFINE_PS_TABLES
39 #define DEFINE_PS_TABLES_DATA
45 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
48 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
51 #define VARIANT_BIT 0x80000000UL
52 #define BASE_GLYPH( code ) ( (FT_UInt32)( (code) & ~VARIANT_BIT ) )
55 /* Return the Unicode value corresponding to a given glyph. Note that */
56 /* we do deal with glyph variants by detecting a non-initial dot in */
57 /* the name, as in `A.swash' or `e.final'; in this case, the */
58 /* VARIANT_BIT is set in the return value. */
61 ps_unicode_value( const char* glyph_name )
63 /* If the name begins with `uni', then the glyph name may be a */
64 /* hard-coded unicode character code. */
65 if ( glyph_name[0] == 'u' &&
66 glyph_name[1] == 'n' &&
67 glyph_name[2] == 'i' )
69 /* determine whether the next four characters following are */
72 /* XXX: Add code to deal with ligatures, i.e. glyph names like */
73 /* `uniXXXXYYYYZZZZ'... */
77 const char* p = glyph_name + 3;
80 for ( count = 4; count > 0; count--, p++ )
86 d = (unsigned char)c - '0';
89 d = (unsigned char)c - 'A';
96 /* Exit if a non-uppercase hexadecimal character was found */
97 /* -- this also catches character codes below `0' since such */
98 /* negative numbers cast to `unsigned int' are far too big. */
102 value = ( value << 4 ) + d;
105 /* there must be exactly four hex digits */
111 return (FT_UInt32)( value | VARIANT_BIT );
115 /* If the name begins with `u', followed by four to six uppercase */
116 /* hexadecimal digits, it is a hard-coded unicode character code. */
117 if ( glyph_name[0] == 'u' )
121 const char* p = glyph_name + 1;
124 for ( count = 6; count > 0; count--, p++ )
130 d = (unsigned char)c - '0';
133 d = (unsigned char)c - 'A';
143 value = ( value << 4 ) + d;
151 return (FT_UInt32)( value | VARIANT_BIT );
155 /* Look for a non-initial dot in the glyph name in order to */
156 /* find variants like `A.swash', `e.final', etc. */
158 const char* p = glyph_name;
159 const char* dot = NULL;
164 if ( *p == '.' && p > glyph_name )
171 /* now look up the glyph in the Adobe Glyph List */
173 return (FT_UInt32)ft_get_adobe_glyph_index( glyph_name, p );
175 return (FT_UInt32)( ft_get_adobe_glyph_index( glyph_name, dot ) |
181 /* ft_qsort callback to sort the unicode map */
182 FT_CALLBACK_DEF( int )
183 compare_uni_maps( const void* a,
186 PS_UniMap* map1 = (PS_UniMap*)a;
187 PS_UniMap* map2 = (PS_UniMap*)b;
188 FT_UInt32 unicode1 = BASE_GLYPH( map1->unicode );
189 FT_UInt32 unicode2 = BASE_GLYPH( map2->unicode );
192 /* sort base glyphs before glyph variants */
193 if ( unicode1 == unicode2 )
195 if ( map1->unicode > map2->unicode )
197 else if ( map1->unicode < map2->unicode )
204 if ( unicode1 > unicode2 )
206 else if ( unicode1 < unicode2 )
214 /* support for extra glyphs not handled (well) in AGL; */
215 /* we add extra mappings for them if necessary */
217 #define EXTRA_GLYPH_LIST_SIZE 10
219 static const FT_UInt32 ft_extra_glyph_unicodes[EXTRA_GLYPH_LIST_SIZE] =
235 static const char ft_extra_glyph_names[] =
237 'D','e','l','t','a',0,
238 'O','m','e','g','a',0,
239 'f','r','a','c','t','i','o','n',0,
240 'h','y','p','h','e','n',0,
241 'm','a','c','r','o','n',0,
243 'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0,
244 's','p','a','c','e',0,
245 'T','c','o','m','m','a','a','c','c','e','n','t',0,
246 't','c','o','m','m','a','a','c','c','e','n','t',0
250 ft_extra_glyph_name_offsets[EXTRA_GLYPH_LIST_SIZE] =
266 ps_check_extra_glyph_name( const char* gname,
268 FT_UInt* extra_glyphs,
274 for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
276 if ( ft_strcmp( ft_extra_glyph_names +
277 ft_extra_glyph_name_offsets[n], gname ) == 0 )
279 if ( states[n] == 0 )
281 /* mark this extra glyph as a candidate for the cmap */
283 extra_glyphs[n] = glyph;
293 ps_check_extra_glyph_unicode( FT_UInt32 uni_char,
299 for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
301 if ( uni_char == ft_extra_glyph_unicodes[n] )
303 /* disable this extra glyph from being added to the cmap */
312 /* Build a table that maps Unicode values to glyph indices. */
314 ps_unicodes_init( FT_Memory memory,
317 PS_GetGlyphNameFunc get_glyph_name,
318 PS_FreeGlyphNameFunc free_glyph_name,
319 FT_Pointer glyph_data )
323 FT_UInt extra_glyph_list_states[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
324 FT_UInt extra_glyphs[EXTRA_GLYPH_LIST_SIZE];
327 /* we first allocate the table */
331 if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) )
341 for ( n = 0; n < num_glyphs; n++ )
343 const char* gname = get_glyph_name( glyph_data, n );
348 ps_check_extra_glyph_name( gname, n,
349 extra_glyphs, extra_glyph_list_states );
350 uni_char = ps_unicode_value( gname );
352 if ( BASE_GLYPH( uni_char ) != 0 )
354 ps_check_extra_glyph_unicode( uni_char,
355 extra_glyph_list_states );
356 map->unicode = uni_char;
357 map->glyph_index = n;
361 if ( free_glyph_name )
362 free_glyph_name( glyph_data, gname );
366 for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
368 if ( extra_glyph_list_states[n] == 1 )
370 /* This glyph name has an additional representation. */
371 /* Add it to the cmap. */
373 map->unicode = ft_extra_glyph_unicodes[n];
374 map->glyph_index = extra_glyphs[n];
379 /* now compress the table a bit */
380 count = (FT_UInt)( map - table->maps );
384 /* No unicode chars here! */
385 FT_FREE( table->maps );
387 error = FT_THROW( No_Unicode_Glyph_Name );
391 /* Reallocate if the number of used entries is much smaller. */
392 if ( count < num_glyphs / 2 )
394 (void)FT_RENEW_ARRAY( table->maps,
395 num_glyphs + EXTRA_GLYPH_LIST_SIZE,
400 /* Sort the table in increasing order of unicode values, */
401 /* taking care of glyph variants. */
402 ft_qsort( table->maps, count, sizeof ( PS_UniMap ),
406 table->num_maps = count;
414 ps_unicodes_char_index( PS_Unicodes table,
417 PS_UniMap *min, *max, *mid, *result = NULL;
420 /* Perform a binary search on the table. */
423 max = min + table->num_maps - 1;
427 FT_UInt32 base_glyph;
430 mid = min + ( ( max - min ) >> 1 );
432 if ( mid->unicode == unicode )
438 base_glyph = BASE_GLYPH( mid->unicode );
440 if ( base_glyph == unicode )
441 result = mid; /* remember match but continue search for base glyph */
446 if ( base_glyph < unicode )
453 return result->glyph_index;
460 ps_unicodes_char_next( PS_Unicodes table,
464 FT_UInt32 char_code = *unicode + 1;
469 FT_UInt max = table->num_maps;
472 FT_UInt32 base_glyph;
477 mid = min + ( ( max - min ) >> 1 );
478 map = table->maps + mid;
480 if ( map->unicode == char_code )
482 result = map->glyph_index;
486 base_glyph = BASE_GLYPH( map->unicode );
488 if ( base_glyph == char_code )
489 result = map->glyph_index;
491 if ( base_glyph < char_code )
498 goto Exit; /* we have a variant glyph */
500 /* we didn't find it; check whether we have a map just above it */
503 if ( min < table->num_maps )
505 map = table->maps + min;
506 result = map->glyph_index;
507 char_code = BASE_GLYPH( map->unicode );
512 *unicode = char_code;
517 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
521 ps_get_macintosh_name( FT_UInt name_index )
523 if ( name_index >= FT_NUM_MAC_NAMES )
526 return ft_standard_glyph_names + ft_mac_names[name_index];
531 ps_get_standard_strings( FT_UInt sid )
533 if ( sid >= FT_NUM_SID_NAMES )
536 return ft_standard_glyph_names + ft_sid_names[sid];
540 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
542 FT_DEFINE_SERVICE_PSCMAPSREC(
545 (PS_Unicode_ValueFunc) ps_unicode_value, /* unicode_value */
546 (PS_Unicodes_InitFunc) ps_unicodes_init, /* unicodes_init */
547 (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index, /* unicodes_char_index */
548 (PS_Unicodes_CharNextFunc) ps_unicodes_char_next, /* unicodes_char_next */
550 (PS_Macintosh_NameFunc) ps_get_macintosh_name, /* macintosh_name */
551 (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings */
553 t1_standard_encoding, /* adobe_std_encoding */
554 t1_expert_encoding /* adobe_expert_encoding */
559 FT_DEFINE_SERVICE_PSCMAPSREC(
562 NULL, /* unicode_value */
563 NULL, /* unicodes_init */
564 NULL, /* unicodes_char_index */
565 NULL, /* unicodes_char_next */
567 (PS_Macintosh_NameFunc) ps_get_macintosh_name, /* macintosh_name */
568 (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings */
570 t1_standard_encoding, /* adobe_std_encoding */
571 t1_expert_encoding /* adobe_expert_encoding */
574 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
577 FT_DEFINE_SERVICEDESCREC1(
580 FT_SERVICE_ID_POSTSCRIPT_CMAPS, &pscmaps_interface )
584 psnames_get_service( FT_Module module,
585 const char* service_id )
589 return ft_service_list_lookup( pscmaps_services, service_id );
592 #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
595 #ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
596 #define PUT_PS_NAMES_SERVICE( a ) NULL
598 #define PUT_PS_NAMES_SERVICE( a ) a
602 psnames_module_class,
604 0, /* this is not a font driver, nor a renderer */
605 sizeof ( FT_ModuleRec ),
607 "psnames", /* driver name */
608 0x10000L, /* driver version */
609 0x20000L, /* driver requires FreeType 2 or above */
611 PUT_PS_NAMES_SERVICE(
612 (void*)&pscmaps_interface ), /* module specific interface */
614 (FT_Module_Constructor)NULL, /* module_init */
615 (FT_Module_Destructor) NULL, /* module_done */
616 (FT_Module_Requester) PUT_PS_NAMES_SERVICE( psnames_get_service ) /* get_interface */