source: trunk/poppler/freetype2/src/psnames/psmodule.c @ 262

Last change on this file since 262 was 262, checked in by Eugene Romanenko, 12 years ago

PDF plugin: freetype library updated to version 2.3.8

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