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

Last change on this file since 200 was 200, checked in by Eugene Romanenko, 15 years ago

PDF plugin: update freetype to 2.3.1 release

File size: 11.8 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  psmodule.c                                                             */
4/*                                                                         */
5/*    PSNames module implementation (body).                                */
6/*                                                                         */
7/*  Copyright 1996-2001, 2002, 2003, 2005, 2006, 2007 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#ifndef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
30
31
32#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
33
34
35#define VARIANT_BIT         ( 1L << 31 )
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  /* Build a table that maps Unicode values to glyph indices. */
184  static FT_Error
185  ps_unicodes_init( FT_Memory             memory,
186                    PS_Unicodes           table,
187                    FT_UInt               num_glyphs,
188                    PS_GetGlyphNameFunc   get_glyph_name,
189                    PS_FreeGlyphNameFunc  free_glyph_name,
190                    FT_Pointer            glyph_data )
191  {
192    FT_Error  error;
193
194
195    /* we first allocate the table */
196    table->num_maps = 0;
197    table->maps     = 0;
198
199    if ( !FT_NEW_ARRAY( table->maps, num_glyphs ) )
200    {
201      FT_UInt     n;
202      FT_UInt     count;
203      PS_UniMap*  map;
204      FT_UInt32   uni_char;
205
206
207      map = table->maps;
208
209      for ( n = 0; n < num_glyphs; n++ )
210      {
211        const char*  gname = get_glyph_name( glyph_data, n );
212
213
214        if ( gname )
215        {
216          uni_char = ps_unicode_value( gname );
217
218          if ( BASE_GLYPH( uni_char ) != 0 )
219          {
220            map->unicode     = uni_char;
221            map->glyph_index = n;
222            map++;
223          }
224
225          if ( free_glyph_name )
226            free_glyph_name( glyph_data, gname );
227        }
228      }
229
230      /* now compress the table a bit */
231      count = (FT_UInt)( map - table->maps );
232
233      if ( count == 0 )
234      {
235        FT_FREE( table->maps );
236        if ( !error )
237          error = PSnames_Err_Invalid_Argument;  /* No unicode chars here! */
238      }
239      else {
240        /* Reallocate if the number of used entries is much smaller. */
241        if ( count < num_glyphs / 2 )
242        {
243          (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );
244          error = PSnames_Err_Ok;
245        }
246
247        /* Sort the table in increasing order of unicode values, */
248        /* taking care of glyph variants.                        */
249        ft_qsort( table->maps, count, sizeof ( PS_UniMap ),
250                  compare_uni_maps );
251      }
252
253      table->num_maps = count;
254    }
255
256    return error;
257  }
258
259
260  static FT_UInt
261  ps_unicodes_char_index( PS_Unicodes  table,
262                          FT_UInt32    unicode )
263  {
264    PS_UniMap  *min, *max, *mid, *result = NULL;
265
266
267    /* Perform a binary search on the table. */
268
269    min = table->maps;
270    max = min + table->num_maps - 1;
271
272    while ( min <= max )
273    {
274      FT_UInt32  base_glyph;
275
276
277      mid = min + ( ( max - min ) >> 1 );
278
279      if ( mid->unicode == unicode )
280      {
281        result = mid;
282        break;
283      }
284
285      base_glyph = BASE_GLYPH( mid->unicode );
286
287      if ( base_glyph == unicode )
288        result = mid; /* remember match but continue search for base glyph */
289
290      if ( min == max )
291        break;
292
293      if ( base_glyph < unicode )
294        min = mid + 1;
295      else
296        max = mid - 1;
297    }
298
299    if ( result )
300      return result->glyph_index;
301    else
302      return 0;
303  }
304
305
306  static FT_ULong
307  ps_unicodes_char_next( PS_Unicodes  table,
308                         FT_UInt32   *unicode )
309  {
310    FT_UInt    result    = 0;
311    FT_UInt32  char_code = *unicode + 1;
312
313
314    {
315      FT_UInt     min = 0;
316      FT_UInt     max = table->num_maps;
317      FT_UInt     mid;
318      PS_UniMap*  map;
319      FT_UInt32   base_glyph;
320
321
322      while ( min < max )
323      {
324        mid = min + ( ( max - min ) >> 1 );
325        map = table->maps + mid;
326
327        if ( map->unicode == char_code )
328        {
329          result = map->glyph_index;
330          goto Exit;
331        }
332
333        base_glyph = BASE_GLYPH( map->unicode );
334
335        if ( base_glyph == char_code )
336          result = map->glyph_index;
337
338        if ( base_glyph < char_code )
339          min = mid + 1;
340        else
341          max = mid;
342      }
343
344      if ( result )
345        goto Exit;               /* we have a variant glyph */
346
347      /* we didn't find it; check whether we have a map just above it */
348      char_code = 0;
349
350      if ( min < table->num_maps )
351      {
352        map       = table->maps + min;
353        result    = map->glyph_index;
354        char_code = BASE_GLYPH( map->unicode );
355      }
356    }
357
358  Exit:
359    *unicode = char_code;
360    return result;
361  }
362
363
364#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
365
366
367  static const char*
368  ps_get_macintosh_name( FT_UInt  name_index )
369  {
370    if ( name_index >= FT_NUM_MAC_NAMES )
371      name_index = 0;
372
373    return ft_standard_glyph_names + ft_mac_names[name_index];
374  }
375
376
377  static const char*
378  ps_get_standard_strings( FT_UInt  sid )
379  {
380    if ( sid >= FT_NUM_SID_NAMES )
381      return 0;
382
383    return ft_standard_glyph_names + ft_sid_names[sid];
384  }
385
386
387  static
388  const FT_Service_PsCMapsRec  pscmaps_interface =
389  {
390#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
391
392    (PS_Unicode_ValueFunc)     ps_unicode_value,
393    (PS_Unicodes_InitFunc)     ps_unicodes_init,
394    (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,
395    (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,
396
397#else
398
399    0,
400    0,
401    0,
402    0,
403
404#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
405
406    (PS_Macintosh_NameFunc)    ps_get_macintosh_name,
407    (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
408
409    t1_standard_encoding,
410    t1_expert_encoding
411  };
412
413
414  static const FT_ServiceDescRec  pscmaps_services[] =
415  {
416    { FT_SERVICE_ID_POSTSCRIPT_CMAPS, &pscmaps_interface },
417    { NULL, NULL }
418  };
419
420
421  static FT_Pointer
422  psnames_get_service( FT_Module    module,
423                       const char*  service_id )
424  {
425    FT_UNUSED( module );
426
427    return ft_service_list_lookup( pscmaps_services, service_id );
428  }
429
430#endif /* !FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES */
431
432
433
434  FT_CALLBACK_TABLE_DEF
435  const FT_Module_Class  psnames_module_class =
436  {
437    0,  /* this is not a font driver, nor a renderer */
438    sizeof ( FT_ModuleRec ),
439
440    "psnames",  /* driver name                         */
441    0x10000L,   /* driver version                      */
442    0x20000L,   /* driver requires FreeType 2 or above */
443
444#ifdef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
445    0,
446    (FT_Module_Constructor)0,
447    (FT_Module_Destructor) 0,
448    (FT_Module_Requester)  0
449#else
450    (void*)&pscmaps_interface,   /* module specific interface */
451    (FT_Module_Constructor)0,
452    (FT_Module_Destructor) 0,
453    (FT_Module_Requester)  psnames_get_service
454#endif
455  };
456
457
458/* END */
Note: See TracBrowser for help on using the repository browser.