OLD | NEW |
| (Empty) |
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 /* */ | |
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 static int xyq_search_node(char* glyph_name, int name_offset, int table_offset,
FT_UInt32 unicode) | |
172 { | |
173 int i, count; | |
174 | |
175 // copy letters | |
176 while (1) { | |
177 glyph_name[name_offset] = ft_adobe_glyph_list[table_offset] & 0x
7f; | |
178 name_offset ++; | |
179 table_offset ++; | |
180 if (!(ft_adobe_glyph_list[table_offset-1] & 0x80)) break; | |
181 } | |
182 glyph_name[name_offset] = 0; | |
183 | |
184 // get child count | |
185 count = ft_adobe_glyph_list[table_offset] & 0x7f; | |
186 | |
187 // check if we have value for this node | |
188 if (ft_adobe_glyph_list[table_offset] & 0x80) { | |
189 unsigned short thiscode = ft_adobe_glyph_list[table_offset+1] *
256 + ft_adobe_glyph_list[table_offset+2]; | |
190 if (thiscode == unicode) // found it! | |
191 return 1; | |
192 table_offset += 3; | |
193 } else | |
194 table_offset ++; | |
195 | |
196 // now search in sub-nodes | |
197 if (count == 0) return 0; | |
198 for (i = 0; i < count; i ++) { | |
199 int child_offset = ft_adobe_glyph_list[table_offset+i*2] * 256 +
ft_adobe_glyph_list[table_offset+i*2+1]; | |
200 if (xyq_search_node(glyph_name, name_offset, child_offset, unico
de)) | |
201 // found in child | |
202 return 1; | |
203 } | |
204 return 0; | |
205 } | |
206 | |
207 // XYQ: function for searching Unicode in the glyph list | |
208 void FXFT_adobe_name_from_unicode(char* glyph_name, FT_UInt32 unicode) | |
209 { | |
210 int i, count; | |
211 | |
212 // start from top level node | |
213 count = ft_adobe_glyph_list[1]; | |
214 for (i = 0; i < count; i ++) { | |
215 int child_offset = ft_adobe_glyph_list[i*2+2] * 256 + ft_adobe_g
lyph_list[i*2+3]; | |
216 if (xyq_search_node(glyph_name, 0, child_offset, unicode)) | |
217 return; | |
218 } | |
219 | |
220 // failed, clear the buffer | |
221 glyph_name[0] = 0; | |
222 } | |
223 | |
224 /* ft_qsort callback to sort the unicode map */ | |
225 FT_CALLBACK_DEF( int ) | |
226 compare_uni_maps( const void* a, | |
227 const void* b ) | |
228 { | |
229 PS_UniMap* map1 = (PS_UniMap*)a; | |
230 PS_UniMap* map2 = (PS_UniMap*)b; | |
231 FT_UInt32 unicode1 = BASE_GLYPH( map1->unicode ); | |
232 FT_UInt32 unicode2 = BASE_GLYPH( map2->unicode ); | |
233 | |
234 | |
235 /* sort base glyphs before glyph variants */ | |
236 if ( unicode1 == unicode2 ) | |
237 { | |
238 if ( map1->unicode > map2->unicode ) | |
239 return 1; | |
240 else if ( map1->unicode < map2->unicode ) | |
241 return -1; | |
242 else | |
243 return 0; | |
244 } | |
245 else | |
246 { | |
247 if ( unicode1 > unicode2 ) | |
248 return 1; | |
249 else if ( unicode1 < unicode2 ) | |
250 return -1; | |
251 else | |
252 return 0; | |
253 } | |
254 } | |
255 | |
256 | |
257 /* support for extra glyphs not handled (well) in AGL; */ | |
258 /* we add extra mappings for them if necessary */ | |
259 | |
260 #define EXTRA_GLYPH_LIST_SIZE 10 | |
261 | |
262 static const FT_UInt32 ft_extra_glyph_unicodes[EXTRA_GLYPH_LIST_SIZE] = | |
263 { | |
264 /* WGL 4 */ | |
265 0x0394, | |
266 0x03A9, | |
267 0x2215, | |
268 0x00AD, | |
269 0x02C9, | |
270 0x03BC, | |
271 0x2219, | |
272 0x00A0, | |
273 /* Romanian */ | |
274 0x021A, | |
275 0x021B | |
276 }; | |
277 | |
278 static const char ft_extra_glyph_names[] = | |
279 { | |
280 'D','e','l','t','a',0, | |
281 'O','m','e','g','a',0, | |
282 'f','r','a','c','t','i','o','n',0, | |
283 'h','y','p','h','e','n',0, | |
284 'm','a','c','r','o','n',0, | |
285 'm','u',0, | |
286 'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0, | |
287 's','p','a','c','e',0, | |
288 'T','c','o','m','m','a','a','c','c','e','n','t',0, | |
289 't','c','o','m','m','a','a','c','c','e','n','t',0 | |
290 }; | |
291 | |
292 static const FT_Int | |
293 ft_extra_glyph_name_offsets[EXTRA_GLYPH_LIST_SIZE] = | |
294 { | |
295 0, | |
296 6, | |
297 12, | |
298 21, | |
299 28, | |
300 35, | |
301 38, | |
302 53, | |
303 59, | |
304 72 | |
305 }; | |
306 | |
307 | |
308 static void | |
309 ps_check_extra_glyph_name( const char* gname, | |
310 FT_UInt glyph, | |
311 FT_UInt* extra_glyphs, | |
312 FT_UInt *states ) | |
313 { | |
314 FT_UInt n; | |
315 | |
316 | |
317 for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ ) | |
318 { | |
319 if ( ft_strcmp( ft_extra_glyph_names + | |
320 ft_extra_glyph_name_offsets[n], gname ) == 0 ) | |
321 { | |
322 if ( states[n] == 0 ) | |
323 { | |
324 /* mark this extra glyph as a candidate for the cmap */ | |
325 states[n] = 1; | |
326 extra_glyphs[n] = glyph; | |
327 } | |
328 | |
329 return; | |
330 } | |
331 } | |
332 } | |
333 | |
334 | |
335 static void | |
336 ps_check_extra_glyph_unicode( FT_UInt32 uni_char, | |
337 FT_UInt *states ) | |
338 { | |
339 FT_UInt n; | |
340 | |
341 | |
342 for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ ) | |
343 { | |
344 if ( uni_char == ft_extra_glyph_unicodes[n] ) | |
345 { | |
346 /* disable this extra glyph from being added to the cmap */ | |
347 states[n] = 2; | |
348 | |
349 return; | |
350 } | |
351 } | |
352 } | |
353 | |
354 | |
355 /* Build a table that maps Unicode values to glyph indices. */ | |
356 static FT_Error | |
357 ps_unicodes_init( FT_Memory memory, | |
358 PS_Unicodes table, | |
359 FT_UInt num_glyphs, | |
360 PS_GetGlyphNameFunc get_glyph_name, | |
361 PS_FreeGlyphNameFunc free_glyph_name, | |
362 FT_Pointer glyph_data ) | |
363 { | |
364 FT_Error error; | |
365 | |
366 FT_UInt extra_glyph_list_states[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | |
367 FT_UInt extra_glyphs[EXTRA_GLYPH_LIST_SIZE]; | |
368 | |
369 | |
370 /* we first allocate the table */ | |
371 table->num_maps = 0; | |
372 table->maps = 0; | |
373 | |
374 if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) ) | |
375 { | |
376 FT_UInt n; | |
377 FT_UInt count; | |
378 PS_UniMap* map; | |
379 FT_UInt32 uni_char; | |
380 | |
381 | |
382 map = table->maps; | |
383 | |
384 for ( n = 0; n < num_glyphs; n++ ) | |
385 { | |
386 const char* gname = get_glyph_name( glyph_data, n ); | |
387 | |
388 | |
389 if ( gname ) | |
390 { | |
391 ps_check_extra_glyph_name( gname, n, | |
392 extra_glyphs, extra_glyph_list_states ); | |
393 uni_char = FXFT_unicode_from_adobe_name( gname ); | |
394 | |
395 if ( BASE_GLYPH( uni_char ) != 0 ) | |
396 { | |
397 ps_check_extra_glyph_unicode( uni_char, | |
398 extra_glyph_list_states ); | |
399 map->unicode = uni_char; | |
400 map->glyph_index = n; | |
401 map++; | |
402 } | |
403 | |
404 if ( free_glyph_name ) | |
405 free_glyph_name( glyph_data, gname ); | |
406 } | |
407 } | |
408 | |
409 for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ ) | |
410 { | |
411 if ( extra_glyph_list_states[n] == 1 ) | |
412 { | |
413 /* This glyph name has an additional representation. */ | |
414 /* Add it to the cmap. */ | |
415 | |
416 map->unicode = ft_extra_glyph_unicodes[n]; | |
417 map->glyph_index = extra_glyphs[n]; | |
418 map++; | |
419 } | |
420 } | |
421 | |
422 /* now compress the table a bit */ | |
423 count = (FT_UInt)( map - table->maps ); | |
424 | |
425 if ( count == 0 ) | |
426 { | |
427 /* No unicode chars here! */ | |
428 FT_FREE( table->maps ); | |
429 if ( !error ) | |
430 error = FT_THROW( No_Unicode_Glyph_Name ); | |
431 } | |
432 else | |
433 { | |
434 /* Reallocate if the number of used entries is much smaller. */ | |
435 if ( count < num_glyphs / 2 ) | |
436 { | |
437 (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count ); | |
438 error = FT_Err_Ok; | |
439 } | |
440 | |
441 /* Sort the table in increasing order of unicode values, */ | |
442 /* taking care of glyph variants. */ | |
443 ft_qsort( table->maps, count, sizeof ( PS_UniMap ), | |
444 compare_uni_maps ); | |
445 } | |
446 | |
447 table->num_maps = count; | |
448 } | |
449 | |
450 return error; | |
451 } | |
452 | |
453 | |
454 static FT_UInt | |
455 ps_unicodes_char_index( PS_Unicodes table, | |
456 FT_UInt32 unicode ) | |
457 { | |
458 PS_UniMap *min, *max, *mid, *result = NULL; | |
459 | |
460 | |
461 /* Perform a binary search on the table. */ | |
462 | |
463 min = table->maps; | |
464 max = min + table->num_maps - 1; | |
465 | |
466 while ( min <= max ) | |
467 { | |
468 FT_UInt32 base_glyph; | |
469 | |
470 | |
471 mid = min + ( ( max - min ) >> 1 ); | |
472 | |
473 if ( mid->unicode == unicode ) | |
474 { | |
475 result = mid; | |
476 break; | |
477 } | |
478 | |
479 base_glyph = BASE_GLYPH( mid->unicode ); | |
480 | |
481 if ( base_glyph == unicode ) | |
482 result = mid; /* remember match but continue search for base glyph */ | |
483 | |
484 if ( min == max ) | |
485 break; | |
486 | |
487 if ( base_glyph < unicode ) | |
488 min = mid + 1; | |
489 else | |
490 max = mid - 1; | |
491 } | |
492 | |
493 if ( result ) | |
494 return result->glyph_index; | |
495 else | |
496 return 0; | |
497 } | |
498 | |
499 | |
500 static FT_UInt32 | |
501 ps_unicodes_char_next( PS_Unicodes table, | |
502 FT_UInt32 *unicode ) | |
503 { | |
504 FT_UInt result = 0; | |
505 FT_UInt32 char_code = *unicode + 1; | |
506 | |
507 | |
508 { | |
509 FT_UInt min = 0; | |
510 FT_UInt max = table->num_maps; | |
511 FT_UInt mid; | |
512 PS_UniMap* map; | |
513 FT_UInt32 base_glyph; | |
514 | |
515 | |
516 while ( min < max ) | |
517 { | |
518 mid = min + ( ( max - min ) >> 1 ); | |
519 map = table->maps + mid; | |
520 | |
521 if ( map->unicode == char_code ) | |
522 { | |
523 result = map->glyph_index; | |
524 goto Exit; | |
525 } | |
526 | |
527 base_glyph = BASE_GLYPH( map->unicode ); | |
528 | |
529 if ( base_glyph == char_code ) | |
530 result = map->glyph_index; | |
531 | |
532 if ( base_glyph < char_code ) | |
533 min = mid + 1; | |
534 else | |
535 max = mid; | |
536 } | |
537 | |
538 if ( result ) | |
539 goto Exit; /* we have a variant glyph */ | |
540 | |
541 /* we didn't find it; check whether we have a map just above it */ | |
542 char_code = 0; | |
543 | |
544 if ( min < table->num_maps ) | |
545 { | |
546 map = table->maps + min; | |
547 result = map->glyph_index; | |
548 char_code = BASE_GLYPH( map->unicode ); | |
549 } | |
550 } | |
551 | |
552 Exit: | |
553 *unicode = char_code; | |
554 return result; | |
555 } | |
556 | |
557 | |
558 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ | |
559 | |
560 | |
561 static const char* | |
562 ps_get_macintosh_name( FT_UInt name_index ) | |
563 { | |
564 if ( name_index >= FT_NUM_MAC_NAMES ) | |
565 name_index = 0; | |
566 | |
567 return ft_standard_glyph_names + ft_mac_names[name_index]; | |
568 } | |
569 | |
570 | |
571 static const char* | |
572 ps_get_standard_strings( FT_UInt sid ) | |
573 { | |
574 if ( sid >= FT_NUM_SID_NAMES ) | |
575 return 0; | |
576 | |
577 return ft_standard_glyph_names + ft_sid_names[sid]; | |
578 } | |
579 | |
580 | |
581 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST | |
582 | |
583 FT_DEFINE_SERVICE_PSCMAPSREC( | |
584 pscmaps_interface, | |
585 (PS_Unicode_ValueFunc) FXFT_unicode_from_adobe_name, | |
586 (PS_Unicodes_InitFunc) ps_unicodes_init, | |
587 (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index, | |
588 (PS_Unicodes_CharNextFunc) ps_unicodes_char_next, | |
589 | |
590 (PS_Macintosh_NameFunc) ps_get_macintosh_name, | |
591 (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, | |
592 | |
593 t1_standard_encoding, | |
594 t1_expert_encoding ) | |
595 | |
596 #else | |
597 | |
598 FT_DEFINE_SERVICE_PSCMAPSREC( | |
599 pscmaps_interface, | |
600 NULL, | |
601 NULL, | |
602 NULL, | |
603 NULL, | |
604 | |
605 (PS_Macintosh_NameFunc) ps_get_macintosh_name, | |
606 (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, | |
607 | |
608 t1_standard_encoding, | |
609 t1_expert_encoding ) | |
610 | |
611 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ | |
612 | |
613 | |
614 FT_DEFINE_SERVICEDESCREC1( | |
615 pscmaps_services, | |
616 FT_SERVICE_ID_POSTSCRIPT_CMAPS, &PSCMAPS_INTERFACE_GET ) | |
617 | |
618 | |
619 static FT_Pointer | |
620 psnames_get_service( FT_Module module, | |
621 const char* service_id ) | |
622 { | |
623 /* PSCMAPS_SERVICES_GET derefers `library' in PIC mode */ | |
624 #ifdef FT_CONFIG_OPTION_PIC | |
625 FT_Library library; | |
626 | |
627 | |
628 if ( !module ) | |
629 return NULL; | |
630 library = module->library; | |
631 if ( !library ) | |
632 return NULL; | |
633 #else | |
634 FT_UNUSED( module ); | |
635 #endif | |
636 | |
637 return ft_service_list_lookup( PSCMAPS_SERVICES_GET, service_id ); | |
638 } | |
639 | |
640 #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ | |
641 | |
642 | |
643 #ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES | |
644 #define PUT_PS_NAMES_SERVICE( a ) NULL | |
645 #else | |
646 #define PUT_PS_NAMES_SERVICE( a ) a | |
647 #endif | |
648 | |
649 FT_DEFINE_MODULE( | |
650 psnames_module_class, | |
651 | |
652 0, /* this is not a font driver, nor a renderer */ | |
653 sizeof ( FT_ModuleRec ), | |
654 | |
655 "psnames", /* driver name */ | |
656 0x10000L, /* driver version */ | |
657 0x20000L, /* driver requires FreeType 2 or above */ | |
658 | |
659 PUT_PS_NAMES_SERVICE( | |
660 (void*)&PSCMAPS_INTERFACE_GET ), /* module specific interface */ | |
661 (FT_Module_Constructor)NULL, | |
662 (FT_Module_Destructor) NULL, | |
663 (FT_Module_Requester) PUT_PS_NAMES_SERVICE( psnames_get_service ) ) | |
664 | |
665 | |
666 /* END */ | |
667 #endif | |
668 | |
OLD | NEW |