psmodule.c revision fbeb41d93d84b6f6dfa2ec8a8b43bafe0fe7696c
1/***************************************************************************/
2/*                                                                         */
3/*  psmodule.c                                                             */
4/*                                                                         */
5/*    PSNames module implementation (body).                                */
6/*                                                                         */
7/*  Copyright 1996-2000 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 <freetype/internal/psnames.h>
20#include <freetype/internal/ftobjs.h>
21#include <psmodule.h>
22
23#include <stdlib.h>     /* for qsort()             */
24#include <string.h>     /* for strcmp(), strncpy() */
25
26
27#ifndef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
28
29
30  /* see the Python script `freetype2/docs/glnames.py' which is used */
31  /* to generate the following file                                  */
32#include <pstables.h>
33
34
35#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
36
37
38  /* return the Unicode value corresponding to a given glyph.  Note that */
39  /* we do deal with glyph variants by detecting a non-initial dot in    */
40  /* the name, as in `A.swash' or `e.final', etc.                        */
41  /*                                                                     */
42  static
43  FT_ULong  PS_Unicode_Value( const char*  glyph_name )
44  {
45    FT_Int  n;
46    char    first = glyph_name[0];
47    char    temp[64];
48
49
50    /* if the name begins with `uni', then the glyph name may be a */
51    /* hard-coded unicode character code.                          */
52    if ( glyph_name[0] == 'u' &&
53         glyph_name[1] == 'n' &&
54         glyph_name[2] == 'i' )
55    {
56      /* determine whether the next four characters following are */
57      /* hexadecimal.                                             */
58
59      /* XXX: Add code to deal with ligatures, i.e. glyph names like */
60      /*      `uniXXXXYYYYZZZZ'...                                   */
61
62      FT_Int       count;
63      FT_ULong     value = 0;
64      const char*  p     = glyph_name + 4;
65
66
67      for ( count = 4; count > 0; count--, p++ )
68      {
69        char           c = *p;
70        unsigned char  d;
71
72
73        d = (unsigned char)c - '0';
74        if ( d >= 10 )
75        {
76          d = (unsigned char)c - 'A';
77          if ( d >= 6 )
78            d = 16;
79          else
80            d += 10;
81        }
82
83        /* exit if a non-uppercase hexadecimal character was found */
84        if ( d >= 16 )
85          break;
86
87        value = ( value << 4 ) + d;
88
89        if ( count == 0 )
90          return value;
91      }
92    }
93
94    /* look for a non-initial dot in the glyph name in order to */
95    /* sort-out variants like `A.swash', `e.final', etc.        */
96    {
97      const char*  p;
98      int          len;
99
100
101      p = glyph_name;
102
103      while ( *p && *p != '.' )
104        p++;
105
106      len = p - glyph_name;
107
108      if ( *p && len < 64 )
109      {
110        strncpy( temp, glyph_name, len );
111        temp[len]  = 0;
112        glyph_name = temp;
113      }
114    }
115
116    /* now, look up the glyph in the Adobe Glyph List */
117    for ( n = 0; n < NUM_ADOBE_GLYPHS; n++ )
118    {
119      const char*  name = t1_standard_glyphs[n];
120
121
122      if ( first == name[0] && strcmp( glyph_name, name ) == 0 )
123        return names_to_unicode[n];
124    }
125
126    /* not found, there is probably no Unicode value for this glyph name */
127    return 0;
128  }
129
130
131  /* qsort callback to sort the unicode map */
132  static
133  int  compare_uni_maps( const void*  a,
134                         const void*  b )
135  {
136    PS_UniMap*  map1 = (PS_UniMap*)a;
137    PS_UniMap*  map2 = (PS_UniMap*)b;
138
139
140    return ( map1->unicode - map2->unicode );
141  }
142
143
144  /* Builds a table that maps Unicode values to glyph indices */
145  static
146  FT_Error  PS_Build_Unicode_Table( FT_Memory     memory,
147                                    FT_UInt       num_glyphs,
148                                    const char**  glyph_names,
149                                    PS_Unicodes*  table )
150  {
151    FT_Error  error;
152
153
154    /* we first allocate the table */
155    table->num_maps = 0;
156    table->maps     = 0;
157
158    if ( !ALLOC_ARRAY( table->maps, num_glyphs, PS_UniMap ) )
159    {
160      FT_UInt     n;
161      FT_UInt     count;
162      PS_UniMap*  map;
163      FT_ULong    uni_char;
164
165
166      map = table->maps;
167
168      for ( n = 0; n < num_glyphs; n++ )
169      {
170        const char*  gname = glyph_names[n];
171
172
173        if ( gname )
174        {
175          uni_char = PS_Unicode_Value( gname );
176
177          if ( uni_char && uni_char != 0xFFFF )
178          {
179            map->unicode     = uni_char;
180            map->glyph_index = n;
181            map++;
182          }
183        }
184      }
185
186      /* now, compress the table a bit */
187      count = map - table->maps;
188
189      if ( count > 0 && REALLOC( table->maps,
190                                 num_glyphs * sizeof ( PS_UniMap ),
191                                 count * sizeof ( PS_UniMap ) ) )
192        count = 0;
193
194      if ( count == 0 )
195      {
196        FREE( table->maps );
197        if ( !error )
198          error = FT_Err_Invalid_Argument;  /* no unicode chars here! */
199      }
200      else
201        /* sort the table in increasing order of unicode values */
202        qsort( table->maps, count, sizeof ( PS_UniMap ), compare_uni_maps );
203
204      table->num_maps = count;
205    }
206
207    return error;
208  }
209
210
211  static
212  FT_UInt  PS_Lookup_Unicode( PS_Unicodes*  table,
213                              FT_ULong      unicode )
214  {
215    PS_UniMap  *min, *max, *mid;
216
217
218    /* perform a binary search on the table */
219
220    min = table->maps;
221    max = min + table->num_maps - 1;
222
223    while ( min <= max )
224    {
225      mid = min + ( max - min ) / 2;
226      if ( mid->unicode == unicode )
227        return mid->glyph_index;
228
229      if ( min == max )
230        break;
231
232      if ( mid->unicode < unicode )
233        min = mid + 1;
234      else
235        max = mid - 1;
236    }
237
238    return 0xFFFF;
239  }
240
241
242#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
243
244
245  static
246  const char*  PS_Macintosh_Name( FT_UInt  name_index )
247  {
248    if ( name_index >= 258 )
249      name_index = 0;
250
251    return standard_glyph_names[mac_standard_names[name_index]];
252  }
253
254
255  static
256  const char*  PS_Standard_Strings( FT_UInt  sid )
257  {
258    return ( sid < NUM_STD_GLYPHS ? t1_standard_glyphs[sid] : 0 );
259  }
260
261
262  static const PSNames_Interface  psnames_interface =
263  {
264#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
265
266    (PS_Unicode_Value_Func)    PS_Unicode_Value,
267    (PS_Build_Unicodes_Func)   PS_Build_Unicode_Table,
268    (PS_Lookup_Unicode_Func)   PS_Lookup_Unicode,
269
270#else
271
272    0,
273    0,
274    0,
275
276#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
277
278    (PS_Macintosh_Name_Func)   PS_Macintosh_Name,
279    (PS_Adobe_Std_Strings_Func)PS_Standard_Strings,
280
281    t1_standard_encoding,
282    t1_expert_encoding
283  };
284
285
286#endif /* !FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES */
287
288
289  const FT_Module_Class  psnames_module_class =
290  {
291    0,  /* this is not a font driver, nor a renderer */
292    sizeof( FT_ModuleRec ),
293
294    "psnames",  /* driver name                         */
295    0x10000L,   /* driver version                      */
296    0x20000L,   /* driver requires FreeType 2 or above */
297
298#ifdef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
299    0,
300#else
301    (void*)&psnames_interface,   /* module specific interface */
302#endif
303
304    (FT_Module_Constructor)0,
305    (FT_Module_Destructor) 0,
306    (FT_Module_Requester)  0
307  };
308
309
310/* END */
311