source: trunk/poppler/freetype-2.1.10/src/psnames/psmodule.c @ 2

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

First import

File size: 9.5 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  psmodule.c                                                             */
4/*                                                                         */
5/*    PSNames module implementation (body).                                */
6/*                                                                         */
7/*  Copyright 1996-2001, 2002, 2003, 2005 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  /* Return the Unicode value corresponding to a given glyph.  Note that */
36  /* we do deal with glyph variants by detecting a non-initial dot in    */
37  /* the name, as in `A.swash' or `e.final'.                             */
38  /*                                                                     */
39  static FT_UInt32
40  ps_unicode_value( const char*  glyph_name )
41  {
42    /* If the name begins with `uni', then the glyph name may be a */
43    /* hard-coded unicode character code.                          */
44    if ( glyph_name[0] == 'u' &&
45         glyph_name[1] == 'n' &&
46         glyph_name[2] == 'i' )
47    {
48      /* determine whether the next four characters following are */
49      /* hexadecimal.                                             */
50
51      /* XXX: Add code to deal with ligatures, i.e. glyph names like */
52      /*      `uniXXXXYYYYZZZZ'...                                   */
53
54      FT_Int       count;
55      FT_ULong     value = 0;
56      const char*  p     = glyph_name + 3;
57
58
59      for ( count = 4; count > 0; count--, p++ )
60      {
61        char          c = *p;
62        unsigned int  d;
63
64
65        d = (unsigned char)c - '0';
66        if ( d >= 10 )
67        {
68          d = (unsigned char)c - 'A';
69          if ( d >= 6 )
70            d = 16;
71          else
72            d += 10;
73        }
74
75        /* exit if a non-uppercase hexadecimal character was found */
76        if ( d >= 16 )
77          break;
78
79        value = ( value << 4 ) + d;
80      }
81
82      /* there must be exactly four hex digits */
83      if ( ( *p == '\0' || *p == '.' ) && count == 0 )
84        return value;
85    }
86
87    /* If the name begins with `u', followed by four to six uppercase */
88    /* hexadicimal digits, it is a hard-coded unicode character code. */
89    if ( glyph_name[0] == 'u' )
90    {
91      FT_Int       count;
92      FT_ULong     value = 0;
93      const char*  p     = glyph_name + 1;
94
95
96      for ( count = 6; count > 0; count--, p++ )
97      {
98        char          c = *p;
99        unsigned int  d;
100
101
102        d = (unsigned char)c - '0';
103        if ( d >= 10 )
104        {
105          d = (unsigned char)c - 'A';
106          if ( d >= 6 )
107            d = 16;
108          else
109            d += 10;
110        }
111
112        if ( d >= 16 )
113          break;
114
115        value = ( value << 4 ) + d;
116      }
117
118      if ( ( *p == '\0' || *p == '.' ) && count <= 2 )
119        return value;
120    }
121
122    /* look for a non-initial dot in the glyph name in order to */
123    /* sort-out variants like `A.swash', `e.final', etc.        */
124    {
125      const char*  p   = glyph_name;
126      const char*  dot = NULL;
127
128
129      for ( ; *p; p++ )
130      {
131        if ( *p == '.' && p > glyph_name && !dot )
132          dot = p;
133      }
134
135      if ( !dot )
136        dot = p;
137
138      /* now, look up the glyph in the Adobe Glyph List */
139      return ft_get_adobe_glyph_index( glyph_name, dot );
140    }
141  }
142
143
144  /* ft_qsort callback to sort the unicode map */
145  FT_CALLBACK_DEF( int )
146  compare_uni_maps( const void*  a,
147                    const void*  b )
148  {
149    PS_UniMap*  map1 = (PS_UniMap*)a;
150    PS_UniMap*  map2 = (PS_UniMap*)b;
151
152
153    return ( map1->unicode - map2->unicode );
154  }
155
156
157  /* Builds a table that maps Unicode values to glyph indices */
158  static FT_Error
159  ps_unicodes_init( FT_Memory     memory,
160                    FT_UInt       num_glyphs,
161                    const char**  glyph_names,
162                    PS_Unicodes*  table )
163  {
164    FT_Error  error;
165
166
167    /* we first allocate the table */
168    table->num_maps = 0;
169    table->maps     = 0;
170
171    if ( !FT_NEW_ARRAY( table->maps, num_glyphs ) )
172    {
173      FT_UInt     n;
174      FT_UInt     count;
175      PS_UniMap*  map;
176      FT_UInt32   uni_char;
177
178
179      map = table->maps;
180
181      for ( n = 0; n < num_glyphs; n++ )
182      {
183        const char*  gname = glyph_names[n];
184
185
186        if ( gname )
187        {
188          uni_char = ps_unicode_value( gname );
189
190          if ( uni_char != 0 && uni_char != 0xFFFFL )
191          {
192            map->unicode     = (FT_UInt)uni_char;
193            map->glyph_index = n;
194            map++;
195          }
196        }
197      }
198
199      /* now, compress the table a bit */
200      count = (FT_UInt)( map - table->maps );
201
202      if ( count > 0 && FT_REALLOC( table->maps,
203                                    num_glyphs * sizeof ( PS_UniMap ),
204                                    count * sizeof ( PS_UniMap ) ) )
205        count = 0;
206
207      if ( count == 0 )
208      {
209        FT_FREE( table->maps );
210        if ( !error )
211          error = PSnames_Err_Invalid_Argument;  /* no unicode chars here! */
212      }
213      else
214        /* sort the table in increasing order of unicode values */
215        ft_qsort( table->maps, count, sizeof ( PS_UniMap ), compare_uni_maps );
216
217      table->num_maps = count;
218    }
219
220    return error;
221  }
222
223
224  static FT_UInt
225  ps_unicodes_char_index( PS_Unicodes*  table,
226                          FT_ULong      unicode )
227  {
228    PS_UniMap  *min, *max, *mid;
229
230
231    /* perform a binary search on the table */
232
233    min = table->maps;
234    max = min + table->num_maps - 1;
235
236    while ( min <= max )
237    {
238      mid = min + ( max - min ) / 2;
239      if ( mid->unicode == unicode )
240        return mid->glyph_index;
241
242      if ( min == max )
243        break;
244
245      if ( mid->unicode < unicode )
246        min = mid + 1;
247      else
248        max = mid - 1;
249    }
250
251    return 0xFFFFU;
252  }
253
254
255  static FT_ULong
256  ps_unicodes_char_next( PS_Unicodes*  table,
257                         FT_ULong      unicode )
258  {
259    PS_UniMap  *min, *max, *mid;
260
261
262    unicode++;
263    /* perform a binary search on the table */
264
265    min = table->maps;
266    max = min + table->num_maps - 1;
267
268    while ( min <= max )
269    {
270      mid = min + ( max - min ) / 2;
271      if ( mid->unicode == unicode )
272        return unicode;
273
274      if ( min == max )
275        break;
276
277      if ( mid->unicode < unicode )
278        min = mid + 1;
279      else
280        max = mid - 1;
281    }
282
283    if ( max < table->maps )
284      max = table->maps;
285
286    while ( max < table->maps + table->num_maps )
287    {
288      if ( unicode < max->unicode )
289        return max->unicode;
290      max++;
291    }
292
293    return 0;
294  }
295
296
297#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
298
299
300  static const char*
301  ps_get_macintosh_name( FT_UInt  name_index )
302  {
303    if ( name_index >= FT_NUM_MAC_NAMES )
304      name_index = 0;
305
306    return ft_standard_glyph_names + ft_mac_names[name_index];
307  }
308
309
310  static const char*
311  ps_get_standard_strings( FT_UInt  sid )
312  {
313    if ( sid >= FT_NUM_SID_NAMES )
314      return 0;
315
316    return ft_standard_glyph_names + ft_sid_names[sid];
317  }
318
319
320  static
321  const FT_Service_PsCMapsRec  pscmaps_interface =
322  {
323#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
324
325    (PS_Unicode_ValueFunc)     ps_unicode_value,
326    (PS_Unicodes_InitFunc)     ps_unicodes_init,
327    (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,
328    (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,
329
330#else
331
332    0,
333    0,
334    0,
335    0,
336
337#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
338
339    (PS_Macintosh_Name_Func)   ps_get_macintosh_name,
340    (PS_Adobe_Std_Strings_Func)ps_get_standard_strings,
341
342    t1_standard_encoding,
343    t1_expert_encoding
344  };
345
346
347  static const FT_ServiceDescRec  pscmaps_services[] =
348  {
349    { FT_SERVICE_ID_POSTSCRIPT_CMAPS, &pscmaps_interface },
350    { NULL, NULL }
351  };
352
353
354  static FT_Pointer
355  psnames_get_service( FT_Module    module,
356                       const char*  service_id )
357  {
358    FT_UNUSED( module );
359
360    return ft_service_list_lookup( pscmaps_services, service_id );
361  }
362
363#endif /* !FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES */
364
365
366
367  FT_CALLBACK_TABLE_DEF
368  const FT_Module_Class  psnames_module_class =
369  {
370    0,  /* this is not a font driver, nor a renderer */
371    sizeof ( FT_ModuleRec ),
372
373    "psnames",  /* driver name                         */
374    0x10000L,   /* driver version                      */
375    0x20000L,   /* driver requires FreeType 2 or above */
376
377#ifdef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
378    0,
379    (FT_Module_Constructor)0,
380    (FT_Module_Destructor) 0,
381    (FT_Module_Requester)  0
382#else
383    (void*)&pscmaps_interface,   /* module specific interface */
384    (FT_Module_Constructor)0,
385    (FT_Module_Destructor) 0,
386    (FT_Module_Requester)  psnames_get_service
387#endif
388  };
389
390
391/* END */
Note: See TracBrowser for help on using the repository browser.