The BIG graph update
[rrdtool.git] / libraries / freetype-2.0.5 / psmodule.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  psmodule.c                                                             */
4 /*                                                                         */
5 /*    PSNames module implementation (body).                                */
6 /*                                                                         */
7 /*  Copyright 1996-2001 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_POSTSCRIPT_NAMES_H
21 #include FT_INTERNAL_OBJECTS_H
22
23 #include "psmodule.h"
24 #include "pstables.h"
25
26 #include "psnamerr.h"
27
28 #include <stdlib.h>     /* for qsort()             */
29 #include <string.h>     /* for strcmp(), strncpy() */
30
31
32 #ifndef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
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 FT_ULong
43   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 + 3;
65
66
67       for ( count = 4; count > 0; count--, p++ )
68       {
69         char           c = *p;
70         unsigned int   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     /* look for a non-initial dot in the glyph name in order to */
94     /* sort-out variants like `A.swash', `e.final', etc.        */
95     {
96       const char*  p;
97       int          len;
98
99
100       p = glyph_name;
101
102       while ( *p && *p != '.' )
103         p++;
104
105       len = (int)( p - glyph_name );
106
107       if ( *p && len < 64 )
108       {
109         strncpy( temp, glyph_name, len );
110         temp[len]  = 0;
111         glyph_name = temp;
112       }
113     }
114
115     /* now, look up the glyph in the Adobe Glyph List */
116     for ( n = 0; n < NUM_ADOBE_GLYPHS; n++ )
117     {
118       const char*  name = sid_standard_names[n];
119
120
121       if ( first == name[0] && strcmp( glyph_name, name ) == 0 )
122         return ps_names_to_unicode[n];
123     }
124
125     /* not found, there is probably no Unicode value for this glyph name */
126     return 0;
127   }
128
129
130   /* qsort callback to sort the unicode map */
131   FT_CALLBACK_DEF( int )
132   compare_uni_maps( const void*  a,
133                     const void*  b )
134   {
135     PS_UniMap*  map1 = (PS_UniMap*)a;
136     PS_UniMap*  map2 = (PS_UniMap*)b;
137
138
139     return ( map1->unicode - map2->unicode );
140   }
141
142
143   /* Builds a table that maps Unicode values to glyph indices */
144   static FT_Error
145   PS_Build_Unicode_Table( FT_Memory     memory,
146                           FT_UInt       num_glyphs,
147                           const char**  glyph_names,
148                           PS_Unicodes*  table )
149   {
150     FT_Error  error;
151
152
153     /* we first allocate the table */
154     table->num_maps = 0;
155     table->maps     = 0;
156
157     if ( !ALLOC_ARRAY( table->maps, num_glyphs, PS_UniMap ) )
158     {
159       FT_UInt     n;
160       FT_UInt     count;
161       PS_UniMap*  map;
162       FT_ULong    uni_char;
163
164
165       map = table->maps;
166
167       for ( n = 0; n < num_glyphs; n++ )
168       {
169         const char*  gname = glyph_names[n];
170
171
172         if ( gname )
173         {
174           uni_char = PS_Unicode_Value( gname );
175
176           if ( uni_char != 0 && uni_char != 0xFFFF )
177           {
178             map->unicode     = uni_char;
179             map->glyph_index = n;
180             map++;
181           }
182         }
183       }
184
185       /* now, compress the table a bit */
186       count = (FT_UInt)( map - table->maps );
187
188       if ( count > 0 && REALLOC( table->maps,
189                                  num_glyphs * sizeof ( PS_UniMap ),
190                                  count * sizeof ( PS_UniMap ) ) )
191         count = 0;
192
193       if ( count == 0 )
194       {
195         FREE( table->maps );
196         if ( !error )
197           error = PSnames_Err_Invalid_Argument;  /* no unicode chars here! */
198       }
199       else
200         /* sort the table in increasing order of unicode values */
201         qsort( table->maps, count, sizeof ( PS_UniMap ), compare_uni_maps );
202
203       table->num_maps = count;
204     }
205
206     return error;
207   }
208
209
210   static FT_UInt
211   PS_Lookup_Unicode( PS_Unicodes*  table,
212                      FT_ULong      unicode )
213   {
214     PS_UniMap  *min, *max, *mid;
215
216
217     /* perform a binary search on the table */
218
219     min = table->maps;
220     max = min + table->num_maps - 1;
221
222     while ( min <= max )
223     {
224       mid = min + ( max - min ) / 2;
225       if ( mid->unicode == unicode )
226         return mid->glyph_index;
227
228       if ( min == max )
229         break;
230
231       if ( mid->unicode < unicode )
232         min = mid + 1;
233       else
234         max = mid - 1;
235     }
236
237     return 0xFFFF;
238   }
239
240
241 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
242
243
244   static const char*
245   PS_Macintosh_Name( FT_UInt  name_index )
246   {
247     if ( name_index >= 258 )
248       name_index = 0;
249
250     return ps_glyph_names[mac_standard_names[name_index]];
251   }
252
253
254   static const char*
255   PS_Standard_Strings( FT_UInt  sid )
256   {
257     return ( sid < NUM_SID_GLYPHS ? sid_standard_names[sid] : 0 );
258   }
259
260
261   static
262   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   FT_CALLBACK_TABLE_DEF
290   const FT_Module_Class  psnames_module_class =
291   {
292     0,  /* this is not a font driver, nor a renderer */
293     sizeof( FT_ModuleRec ),
294
295     "psnames",  /* driver name                         */
296     0x10000L,   /* driver version                      */
297     0x20000L,   /* driver requires FreeType 2 or above */
298
299 #ifdef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
300     0,
301 #else
302     (void*)&psnames_interface,   /* module specific interface */
303 #endif
304
305     (FT_Module_Constructor)0,
306     (FT_Module_Destructor) 0,
307     (FT_Module_Requester)  0
308   };
309
310
311 /* END */