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 /* */
FXFT_unicode_from_adobe_name(const char * glyph_name)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_)
xyq_search_node(char * glyph_name,int name_offset,int table_offset,FT_UInt32 unicode)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
FXFT_adobe_name_from_unicode(char * glyph_name,FT_UInt32 unicode)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 )
compare_uni_maps(const void * a,const void * b)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
ps_check_extra_glyph_name(const char * gname,FT_UInt glyph,FT_UInt * extra_glyphs,FT_UInt * states)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
ps_check_extra_glyph_unicode(FT_UInt32 uni_char,FT_UInt * states)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
ps_unicodes_init(FT_Memory memory,PS_Unicodes table,FT_UInt num_glyphs,PS_GetGlyphNameFunc get_glyph_name,PS_FreeGlyphNameFunc free_glyph_name,FT_Pointer glyph_data)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
ps_unicodes_char_index(PS_Unicodes table,FT_UInt32 unicode)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
ps_unicodes_char_next(PS_Unicodes table,FT_UInt32 * unicode)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*
ps_get_macintosh_name(FT_UInt name_index)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*
ps_get_standard_strings(FT_UInt sid)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
psnames_get_service(FT_Module module,const char * service_id)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