XFA: merge patch from CL 817753002
[pdfium.git] / core / src / fxge / fx_freetype / fxft2.5.01 / src / psnames / fxft_psmodule.c
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] & 0x7f;
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, unicode))
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_glyph_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