• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************/
2 /*                                                                         */
3 /*  psmodule.c                                                             */
4 /*                                                                         */
5 /*    PSNames module implementation (body).                                */
6 /*                                                                         */
7 /*  Copyright 1996-2018 by                                                 */
8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9 /*                                                                         */
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.                                        */
15 /*                                                                         */
16 /***************************************************************************/
17 
18 
19 #include <ft2build.h>
20 #include FT_INTERNAL_DEBUG_H
21 #include FT_INTERNAL_OBJECTS_H
22 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
23 
24 #include "psmodule.h"
25 
26   /*
27    *  The file `pstables.h' with its arrays and its function
28    *  `ft_get_adobe_glyph_index' is useful for other projects also (for
29    *  example, `pdfium' is using it).  However, if used as a C++ header,
30    *  including it in two different source files makes it necessary to use
31    *  `extern const' for the declaration of its arrays, otherwise the data
32    *  would be duplicated as mandated by the C++ standard.
33    *
34    *  For this reason, we use `DEFINE_PS_TABLES' to guard the function
35    *  definitions, and `DEFINE_PS_TABLES_DATA' to provide both proper array
36    *  declarations and definitions.
37    */
38 #include "pstables.h"
39 #define  DEFINE_PS_TABLES
40 #define  DEFINE_PS_TABLES_DATA
41 #include "pstables.h"
42 
43 #include "psnamerr.h"
44 #include "pspic.h"
45 
46 
47 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
48 
49 
50 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
51 
52 
53 #define VARIANT_BIT         0x80000000UL
54 #define BASE_GLYPH( code )  ( (FT_UInt32)( (code) & ~VARIANT_BIT ) )
55 
56 
57   /* Return the Unicode value corresponding to a given glyph.  Note that */
58   /* we do deal with glyph variants by detecting a non-initial dot in    */
59   /* the name, as in `A.swash' or `e.final'; in this case, the           */
60   /* VARIANT_BIT is set in the return value.                             */
61   /*                                                                     */
62   static FT_UInt32
ps_unicode_value(const char * glyph_name)63   ps_unicode_value( const char*  glyph_name )
64   {
65     /* If the name begins with `uni', then the glyph name may be a */
66     /* hard-coded unicode character code.                          */
67     if ( glyph_name[0] == 'u' &&
68          glyph_name[1] == 'n' &&
69          glyph_name[2] == 'i' )
70     {
71       /* determine whether the next four characters following are */
72       /* hexadecimal.                                             */
73 
74       /* XXX: Add code to deal with ligatures, i.e. glyph names like */
75       /*      `uniXXXXYYYYZZZZ'...                                   */
76 
77       FT_Int       count;
78       FT_UInt32    value = 0;
79       const char*  p     = glyph_name + 3;
80 
81 
82       for ( count = 4; count > 0; count--, p++ )
83       {
84         char          c = *p;
85         unsigned int  d;
86 
87 
88         d = (unsigned char)c - '0';
89         if ( d >= 10 )
90         {
91           d = (unsigned char)c - 'A';
92           if ( d >= 6 )
93             d = 16;
94           else
95             d += 10;
96         }
97 
98         /* Exit if a non-uppercase hexadecimal character was found   */
99         /* -- this also catches character codes below `0' since such */
100         /* negative numbers cast to `unsigned int' are far too big.  */
101         if ( d >= 16 )
102           break;
103 
104         value = ( value << 4 ) + d;
105       }
106 
107       /* there must be exactly four hex digits */
108       if ( count == 0 )
109       {
110         if ( *p == '\0' )
111           return value;
112         if ( *p == '.' )
113           return (FT_UInt32)( value | VARIANT_BIT );
114       }
115     }
116 
117     /* If the name begins with `u', followed by four to six uppercase */
118     /* hexadecimal digits, it is a hard-coded unicode character code. */
119     if ( glyph_name[0] == 'u' )
120     {
121       FT_Int       count;
122       FT_UInt32    value = 0;
123       const char*  p     = glyph_name + 1;
124 
125 
126       for ( count = 6; count > 0; count--, p++ )
127       {
128         char          c = *p;
129         unsigned int  d;
130 
131 
132         d = (unsigned char)c - '0';
133         if ( d >= 10 )
134         {
135           d = (unsigned char)c - 'A';
136           if ( d >= 6 )
137             d = 16;
138           else
139             d += 10;
140         }
141 
142         if ( d >= 16 )
143           break;
144 
145         value = ( value << 4 ) + d;
146       }
147 
148       if ( count <= 2 )
149       {
150         if ( *p == '\0' )
151           return value;
152         if ( *p == '.' )
153           return (FT_UInt32)( value | VARIANT_BIT );
154       }
155     }
156 
157     /* Look for a non-initial dot in the glyph name in order to */
158     /* find variants like `A.swash', `e.final', etc.            */
159     {
160       const char*  p   = glyph_name;
161       const char*  dot = NULL;
162 
163 
164       for ( ; *p; p++ )
165       {
166         if ( *p == '.' && p > glyph_name )
167         {
168           dot = p;
169           break;
170         }
171       }
172 
173       /* now look up the glyph in the Adobe Glyph List */
174       if ( !dot )
175         return (FT_UInt32)ft_get_adobe_glyph_index( glyph_name, p );
176       else
177         return (FT_UInt32)( ft_get_adobe_glyph_index( glyph_name, dot ) |
178                             VARIANT_BIT );
179     }
180   }
181 
182 
183   /* ft_qsort callback to sort the unicode map */
184   FT_CALLBACK_DEF( int )
compare_uni_maps(const void * a,const void * b)185   compare_uni_maps( const void*  a,
186                     const void*  b )
187   {
188     PS_UniMap*  map1 = (PS_UniMap*)a;
189     PS_UniMap*  map2 = (PS_UniMap*)b;
190     FT_UInt32   unicode1 = BASE_GLYPH( map1->unicode );
191     FT_UInt32   unicode2 = BASE_GLYPH( map2->unicode );
192 
193 
194     /* sort base glyphs before glyph variants */
195     if ( unicode1 == unicode2 )
196     {
197       if ( map1->unicode > map2->unicode )
198         return 1;
199       else if ( map1->unicode < map2->unicode )
200         return -1;
201       else
202         return 0;
203     }
204     else
205     {
206       if ( unicode1 > unicode2 )
207         return 1;
208       else if ( unicode1 < unicode2 )
209         return -1;
210       else
211         return 0;
212     }
213   }
214 
215 
216   /* support for extra glyphs not handled (well) in AGL; */
217   /* we add extra mappings for them if necessary         */
218 
219 #define EXTRA_GLYPH_LIST_SIZE  10
220 
221   static const FT_UInt32  ft_extra_glyph_unicodes[EXTRA_GLYPH_LIST_SIZE] =
222   {
223     /* WGL 4 */
224     0x0394,
225     0x03A9,
226     0x2215,
227     0x00AD,
228     0x02C9,
229     0x03BC,
230     0x2219,
231     0x00A0,
232     /* Romanian */
233     0x021A,
234     0x021B
235   };
236 
237   static const char  ft_extra_glyph_names[] =
238   {
239     'D','e','l','t','a',0,
240     'O','m','e','g','a',0,
241     'f','r','a','c','t','i','o','n',0,
242     'h','y','p','h','e','n',0,
243     'm','a','c','r','o','n',0,
244     'm','u',0,
245     'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0,
246     's','p','a','c','e',0,
247     'T','c','o','m','m','a','a','c','c','e','n','t',0,
248     't','c','o','m','m','a','a','c','c','e','n','t',0
249   };
250 
251   static const FT_Int
252   ft_extra_glyph_name_offsets[EXTRA_GLYPH_LIST_SIZE] =
253   {
254      0,
255      6,
256     12,
257     21,
258     28,
259     35,
260     38,
261     53,
262     59,
263     72
264   };
265 
266 
267   static void
ps_check_extra_glyph_name(const char * gname,FT_UInt glyph,FT_UInt * extra_glyphs,FT_UInt * states)268   ps_check_extra_glyph_name( const char*  gname,
269                              FT_UInt      glyph,
270                              FT_UInt*     extra_glyphs,
271                              FT_UInt     *states )
272   {
273     FT_UInt  n;
274 
275 
276     for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
277     {
278       if ( ft_strcmp( ft_extra_glyph_names +
279                         ft_extra_glyph_name_offsets[n], gname ) == 0 )
280       {
281         if ( states[n] == 0 )
282         {
283           /* mark this extra glyph as a candidate for the cmap */
284           states[n]     = 1;
285           extra_glyphs[n] = glyph;
286         }
287 
288         return;
289       }
290     }
291   }
292 
293 
294   static void
ps_check_extra_glyph_unicode(FT_UInt32 uni_char,FT_UInt * states)295   ps_check_extra_glyph_unicode( FT_UInt32  uni_char,
296                                 FT_UInt   *states )
297   {
298     FT_UInt  n;
299 
300 
301     for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
302     {
303       if ( uni_char == ft_extra_glyph_unicodes[n] )
304       {
305         /* disable this extra glyph from being added to the cmap */
306         states[n] = 2;
307 
308         return;
309       }
310     }
311   }
312 
313 
314   /* Build a table that maps Unicode values to glyph indices. */
315   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)316   ps_unicodes_init( FT_Memory             memory,
317                     PS_Unicodes           table,
318                     FT_UInt               num_glyphs,
319                     PS_GetGlyphNameFunc   get_glyph_name,
320                     PS_FreeGlyphNameFunc  free_glyph_name,
321                     FT_Pointer            glyph_data )
322   {
323     FT_Error  error;
324 
325     FT_UInt  extra_glyph_list_states[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
326     FT_UInt  extra_glyphs[EXTRA_GLYPH_LIST_SIZE];
327 
328 
329     /* we first allocate the table */
330     table->num_maps = 0;
331     table->maps     = NULL;
332 
333     if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) )
334     {
335       FT_UInt     n;
336       FT_UInt     count;
337       PS_UniMap*  map;
338       FT_UInt32   uni_char;
339 
340 
341       map = table->maps;
342 
343       for ( n = 0; n < num_glyphs; n++ )
344       {
345         const char*  gname = get_glyph_name( glyph_data, n );
346 
347 
348         if ( gname )
349         {
350           ps_check_extra_glyph_name( gname, n,
351                                      extra_glyphs, extra_glyph_list_states );
352           uni_char = ps_unicode_value( gname );
353 
354           if ( BASE_GLYPH( uni_char ) != 0 )
355           {
356             ps_check_extra_glyph_unicode( uni_char,
357                                           extra_glyph_list_states );
358             map->unicode     = uni_char;
359             map->glyph_index = n;
360             map++;
361           }
362 
363           if ( free_glyph_name )
364             free_glyph_name( glyph_data, gname );
365         }
366       }
367 
368       for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
369       {
370         if ( extra_glyph_list_states[n] == 1 )
371         {
372           /* This glyph name has an additional representation. */
373           /* Add it to the cmap.                               */
374 
375           map->unicode     = ft_extra_glyph_unicodes[n];
376           map->glyph_index = extra_glyphs[n];
377           map++;
378         }
379       }
380 
381       /* now compress the table a bit */
382       count = (FT_UInt)( map - table->maps );
383 
384       if ( count == 0 )
385       {
386         /* No unicode chars here! */
387         FT_FREE( table->maps );
388         if ( !error )
389           error = FT_THROW( No_Unicode_Glyph_Name );
390       }
391       else
392       {
393         /* Reallocate if the number of used entries is much smaller. */
394         if ( count < num_glyphs / 2 )
395         {
396           (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );
397           error = FT_Err_Ok;
398         }
399 
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 ),
403                   compare_uni_maps );
404       }
405 
406       table->num_maps = count;
407     }
408 
409     return error;
410   }
411 
412 
413   static FT_UInt
ps_unicodes_char_index(PS_Unicodes table,FT_UInt32 unicode)414   ps_unicodes_char_index( PS_Unicodes  table,
415                           FT_UInt32    unicode )
416   {
417     PS_UniMap  *min, *max, *mid, *result = NULL;
418 
419 
420     /* Perform a binary search on the table. */
421 
422     min = table->maps;
423     max = min + table->num_maps - 1;
424 
425     while ( min <= max )
426     {
427       FT_UInt32  base_glyph;
428 
429 
430       mid = min + ( ( max - min ) >> 1 );
431 
432       if ( mid->unicode == unicode )
433       {
434         result = mid;
435         break;
436       }
437 
438       base_glyph = BASE_GLYPH( mid->unicode );
439 
440       if ( base_glyph == unicode )
441         result = mid; /* remember match but continue search for base glyph */
442 
443       if ( min == max )
444         break;
445 
446       if ( base_glyph < unicode )
447         min = mid + 1;
448       else
449         max = mid - 1;
450     }
451 
452     if ( result )
453       return result->glyph_index;
454     else
455       return 0;
456   }
457 
458 
459   static FT_UInt32
ps_unicodes_char_next(PS_Unicodes table,FT_UInt32 * unicode)460   ps_unicodes_char_next( PS_Unicodes  table,
461                          FT_UInt32   *unicode )
462   {
463     FT_UInt    result    = 0;
464     FT_UInt32  char_code = *unicode + 1;
465 
466 
467     {
468       FT_UInt     min = 0;
469       FT_UInt     max = table->num_maps;
470       FT_UInt     mid;
471       PS_UniMap*  map;
472       FT_UInt32   base_glyph;
473 
474 
475       while ( min < max )
476       {
477         mid = min + ( ( max - min ) >> 1 );
478         map = table->maps + mid;
479 
480         if ( map->unicode == char_code )
481         {
482           result = map->glyph_index;
483           goto Exit;
484         }
485 
486         base_glyph = BASE_GLYPH( map->unicode );
487 
488         if ( base_glyph == char_code )
489           result = map->glyph_index;
490 
491         if ( base_glyph < char_code )
492           min = mid + 1;
493         else
494           max = mid;
495       }
496 
497       if ( result )
498         goto Exit;               /* we have a variant glyph */
499 
500       /* we didn't find it; check whether we have a map just above it */
501       char_code = 0;
502 
503       if ( min < table->num_maps )
504       {
505         map       = table->maps + min;
506         result    = map->glyph_index;
507         char_code = BASE_GLYPH( map->unicode );
508       }
509     }
510 
511   Exit:
512     *unicode = char_code;
513     return result;
514   }
515 
516 
517 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
518 
519 
520   static const char*
ps_get_macintosh_name(FT_UInt name_index)521   ps_get_macintosh_name( FT_UInt  name_index )
522   {
523     if ( name_index >= FT_NUM_MAC_NAMES )
524       name_index = 0;
525 
526     return ft_standard_glyph_names + ft_mac_names[name_index];
527   }
528 
529 
530   static const char*
ps_get_standard_strings(FT_UInt sid)531   ps_get_standard_strings( FT_UInt  sid )
532   {
533     if ( sid >= FT_NUM_SID_NAMES )
534       return 0;
535 
536     return ft_standard_glyph_names + ft_sid_names[sid];
537   }
538 
539 
540 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
541 
542   FT_DEFINE_SERVICE_PSCMAPSREC(
543     pscmaps_interface,
544 
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    */
549 
550     (PS_Macintosh_NameFunc)    ps_get_macintosh_name,   /* macintosh_name        */
551     (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings     */
552 
553     t1_standard_encoding,                               /* adobe_std_encoding    */
554     t1_expert_encoding                                  /* adobe_expert_encoding */
555   )
556 
557 #else
558 
559   FT_DEFINE_SERVICE_PSCMAPSREC(
560     pscmaps_interface,
561 
562     NULL,                                               /* unicode_value         */
563     NULL,                                               /* unicodes_init         */
564     NULL,                                               /* unicodes_char_index   */
565     NULL,                                               /* unicodes_char_next    */
566 
567     (PS_Macintosh_NameFunc)    ps_get_macintosh_name,   /* macintosh_name        */
568     (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings     */
569 
570     t1_standard_encoding,                               /* adobe_std_encoding    */
571     t1_expert_encoding                                  /* adobe_expert_encoding */
572   )
573 
574 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
575 
576 
577   FT_DEFINE_SERVICEDESCREC1(
578     pscmaps_services,
579 
580     FT_SERVICE_ID_POSTSCRIPT_CMAPS, &PSCMAPS_INTERFACE_GET )
581 
582 
583   static FT_Pointer
psnames_get_service(FT_Module module,const char * service_id)584   psnames_get_service( FT_Module    module,
585                        const char*  service_id )
586   {
587     /* PSCMAPS_SERVICES_GET dereferences `library' in PIC mode */
588 #ifdef FT_CONFIG_OPTION_PIC
589     FT_Library  library;
590 
591 
592     if ( !module )
593       return NULL;
594     library = module->library;
595     if ( !library )
596       return NULL;
597 #else
598     FT_UNUSED( module );
599 #endif
600 
601     return ft_service_list_lookup( PSCMAPS_SERVICES_GET, service_id );
602   }
603 
604 #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
605 
606 
607 #ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
608 #define PUT_PS_NAMES_SERVICE( a )  NULL
609 #else
610 #define PUT_PS_NAMES_SERVICE( a )  a
611 #endif
612 
613   FT_DEFINE_MODULE(
614     psnames_module_class,
615 
616     0,  /* this is not a font driver, nor a renderer */
617     sizeof ( FT_ModuleRec ),
618 
619     "psnames",  /* driver name                         */
620     0x10000L,   /* driver version                      */
621     0x20000L,   /* driver requires FreeType 2 or above */
622 
623     PUT_PS_NAMES_SERVICE(
624       (void*)&PSCMAPS_INTERFACE_GET ),   /* module specific interface */
625 
626     (FT_Module_Constructor)NULL,                                       /* module_init   */
627     (FT_Module_Destructor) NULL,                                       /* module_done   */
628     (FT_Module_Requester)  PUT_PS_NAMES_SERVICE( psnames_get_service ) /* get_interface */
629   )
630 
631 
632 /* END */
633