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

Last change on this file since 251 was 251, checked in by Eugene Romanenko, 13 years ago

PDF plugin: freetype library updated to version 2.3.5

File size: 14.2 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      return map1->unicode - map2->unicode;
178    else
179      return unicode1 - unicode2;
180  }
181
182
183  /* support for old WGL4 fonts */
184
185#define WGL_EXTRA_LIST_SIZE  8
186
187  static const FT_UInt32  ft_wgl_extra_unicodes[WGL_EXTRA_LIST_SIZE] =
188  {
189    0x0394,
190    0x03A9,
191    0x2215,
192    0x00AD,
193    0x02C9,
194    0x03BC,
195    0x2219,
196    0x00A0
197  };
198
199  static const char  ft_wgl_extra_glyph_names[] =
200  {
201    'D','e','l','t','a',0,
202    'O','m','e','g','a',0,
203    'f','r','a','c','t','i','o','n',0,
204    'h','y','p','h','e','n',0,
205    'm','a','c','r','o','n',0,
206    'm','u',0,
207    'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0,
208    's','p','a','c','e',0
209  };
210
211  static const FT_Int
212  ft_wgl_extra_glyph_name_offsets[WGL_EXTRA_LIST_SIZE] =
213  {
214     0,
215     6,
216    12,
217    21,
218    28,
219    35,
220    38,
221    53
222  };
223
224
225  static void
226  ps_check_wgl_name( const char*  gname,
227                     FT_UInt      glyph,
228                     FT_UInt*     wgl_glyphs,
229                     FT_UInt     *states )
230  {
231    FT_UInt  n;
232
233
234    for ( n = 0; n < WGL_EXTRA_LIST_SIZE; n++ )
235    {
236      if ( ft_strcmp( ft_wgl_extra_glyph_names +
237                        ft_wgl_extra_glyph_name_offsets[n], gname ) == 0 )
238      {
239        if ( states[n] == 0 )
240        {
241          /* mark this WGL extra glyph as a candidate for the cmap */
242          states[n]     = 1;
243          wgl_glyphs[n] = glyph;
244        }
245
246        return;
247      }
248    }
249  }
250
251
252  static void
253  ps_check_wgl_unicode( FT_UInt32  uni_char,
254                        FT_UInt   *states )
255  {
256    FT_UInt  n;
257
258
259    for ( n = 0; n < WGL_EXTRA_LIST_SIZE; n++ )
260    {
261      if ( uni_char == ft_wgl_extra_unicodes[n] )
262      {
263        /* disable this WGL extra glyph from being added to the cmap */
264        states[n] = 2;
265
266        return;
267      }
268    }
269  }
270
271
272  /* Build a table that maps Unicode values to glyph indices. */
273  static FT_Error
274  ps_unicodes_init( FT_Memory             memory,
275                    PS_Unicodes           table,
276                    FT_UInt               num_glyphs,
277                    PS_GetGlyphNameFunc   get_glyph_name,
278                    PS_FreeGlyphNameFunc  free_glyph_name,
279                    FT_Pointer            glyph_data )
280  {
281    FT_Error  error;
282
283    FT_UInt  wgl_list_states[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
284    FT_UInt  wgl_glyphs[WGL_EXTRA_LIST_SIZE];
285
286
287    /* we first allocate the table */
288    table->num_maps = 0;
289    table->maps     = 0;
290
291    if ( !FT_NEW_ARRAY( table->maps, num_glyphs + WGL_EXTRA_LIST_SIZE ) )
292    {
293      FT_UInt     n;
294      FT_UInt     count;
295      PS_UniMap*  map;
296      FT_UInt32   uni_char;
297
298
299      map = table->maps;
300
301      for ( n = 0; n < num_glyphs; n++ )
302      {
303        const char*  gname = get_glyph_name( glyph_data, n );
304
305
306        if ( gname )
307        {
308          ps_check_wgl_name( gname, n, wgl_glyphs, wgl_list_states );
309          uni_char = ps_unicode_value( gname );
310
311          if ( BASE_GLYPH( uni_char ) != 0 )
312          {
313            ps_check_wgl_unicode( uni_char, wgl_list_states );
314            map->unicode     = uni_char;
315            map->glyph_index = n;
316            map++;
317          }
318
319          if ( free_glyph_name )
320            free_glyph_name( glyph_data, gname );
321        }
322      }
323
324      for ( n = 0; n < WGL_EXTRA_LIST_SIZE; n++ )
325      {
326        if ( wgl_list_states[n] == 1 )
327        {
328          /* This glyph name has an additional WGL4 representation. */
329          /* Add it to the cmap.                                    */
330
331          map->unicode     = ft_wgl_extra_unicodes[n];
332          map->glyph_index = wgl_glyphs[n];
333          map++;
334        }
335      }
336
337      /* now compress the table a bit */
338      count = (FT_UInt)( map - table->maps );
339
340      if ( count == 0 )
341      {
342        FT_FREE( table->maps );
343        if ( !error )
344          error = PSnames_Err_Invalid_Argument;  /* No unicode chars here! */
345      }
346      else {
347        /* Reallocate if the number of used entries is much smaller. */
348        if ( count < num_glyphs / 2 )
349        {
350          (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );
351          error = PSnames_Err_Ok;
352        }
353
354        /* Sort the table in increasing order of unicode values, */
355        /* taking care of glyph variants.                        */
356        ft_qsort( table->maps, count, sizeof ( PS_UniMap ),
357                  compare_uni_maps );
358      }
359
360      table->num_maps = count;
361    }
362
363    return error;
364  }
365
366
367  static FT_UInt
368  ps_unicodes_char_index( PS_Unicodes  table,
369                          FT_UInt32    unicode )
370  {
371    PS_UniMap  *min, *max, *mid, *result = NULL;
372
373
374    /* Perform a binary search on the table. */
375
376    min = table->maps;
377    max = min + table->num_maps - 1;
378
379    while ( min <= max )
380    {
381      FT_UInt32  base_glyph;
382
383
384      mid = min + ( ( max - min ) >> 1 );
385
386      if ( mid->unicode == unicode )
387      {
388        result = mid;
389        break;
390      }
391
392      base_glyph = BASE_GLYPH( mid->unicode );
393
394      if ( base_glyph == unicode )
395        result = mid; /* remember match but continue search for base glyph */
396
397      if ( min == max )
398        break;
399
400      if ( base_glyph < unicode )
401        min = mid + 1;
402      else
403        max = mid - 1;
404    }
405
406    if ( result )
407      return result->glyph_index;
408    else
409      return 0;
410  }
411
412
413  static FT_ULong
414  ps_unicodes_char_next( PS_Unicodes  table,
415                         FT_UInt32   *unicode )
416  {
417    FT_UInt    result    = 0;
418    FT_UInt32  char_code = *unicode + 1;
419
420
421    {
422      FT_UInt     min = 0;
423      FT_UInt     max = table->num_maps;
424      FT_UInt     mid;
425      PS_UniMap*  map;
426      FT_UInt32   base_glyph;
427
428
429      while ( min < max )
430      {
431        mid = min + ( ( max - min ) >> 1 );
432        map = table->maps + mid;
433
434        if ( map->unicode == char_code )
435        {
436          result = map->glyph_index;
437          goto Exit;
438        }
439
440        base_glyph = BASE_GLYPH( map->unicode );
441
442        if ( base_glyph == char_code )
443          result = map->glyph_index;
444
445        if ( base_glyph < char_code )
446          min = mid + 1;
447        else
448          max = mid;
449      }
450
451      if ( result )
452        goto Exit;               /* we have a variant glyph */
453
454      /* we didn't find it; check whether we have a map just above it */
455      char_code = 0;
456
457      if ( min < table->num_maps )
458      {
459        map       = table->maps + min;
460        result    = map->glyph_index;
461        char_code = BASE_GLYPH( map->unicode );
462      }
463    }
464
465  Exit:
466    *unicode = char_code;
467    return result;
468  }
469
470
471#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
472
473
474  static const char*
475  ps_get_macintosh_name( FT_UInt  name_index )
476  {
477    if ( name_index >= FT_NUM_MAC_NAMES )
478      name_index = 0;
479
480    return ft_standard_glyph_names + ft_mac_names[name_index];
481  }
482
483
484  static const char*
485  ps_get_standard_strings( FT_UInt  sid )
486  {
487    if ( sid >= FT_NUM_SID_NAMES )
488      return 0;
489
490    return ft_standard_glyph_names + ft_sid_names[sid];
491  }
492
493
494  static
495  const FT_Service_PsCMapsRec  pscmaps_interface =
496  {
497#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
498
499    (PS_Unicode_ValueFunc)     ps_unicode_value,
500    (PS_Unicodes_InitFunc)     ps_unicodes_init,
501    (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,
502    (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,
503
504#else
505
506    0,
507    0,
508    0,
509    0,
510
511#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
512
513    (PS_Macintosh_NameFunc)    ps_get_macintosh_name,
514    (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
515
516    t1_standard_encoding,
517    t1_expert_encoding
518  };
519
520
521  static const FT_ServiceDescRec  pscmaps_services[] =
522  {
523    { FT_SERVICE_ID_POSTSCRIPT_CMAPS, &pscmaps_interface },
524    { NULL, NULL }
525  };
526
527
528  static FT_Pointer
529  psnames_get_service( FT_Module    module,
530                       const char*  service_id )
531  {
532    FT_UNUSED( module );
533
534    return ft_service_list_lookup( pscmaps_services, service_id );
535  }
536
537#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
538
539
540
541  FT_CALLBACK_TABLE_DEF
542  const FT_Module_Class  psnames_module_class =
543  {
544    0,  /* this is not a font driver, nor a renderer */
545    sizeof ( FT_ModuleRec ),
546
547    "psnames",  /* driver name                         */
548    0x10000L,   /* driver version                      */
549    0x20000L,   /* driver requires FreeType 2 or above */
550
551#ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
552    0,
553    (FT_Module_Constructor)0,
554    (FT_Module_Destructor) 0,
555    (FT_Module_Requester)  0
556#else
557    (void*)&pscmaps_interface,   /* module specific interface */
558    (FT_Module_Constructor)0,
559    (FT_Module_Destructor) 0,
560    (FT_Module_Requester)  psnames_get_service
561#endif
562  };
563
564
565/* END */
Note: See TracBrowser for help on using the repository browser.