• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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