update for HEAD-2003050101
[reactos.git] / lib / freetype / src / psnames / psmodule.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  psmodule.c                                                             */
4 /*                                                                         */
5 /*    PSNames module implementation (body).                                */
6 /*                                                                         */
7 /*  Copyright 1996-2001, 2002 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
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', etc.                        */
38   /*                                                                     */
39   static FT_UInt32
40   ps_unicode_value( const char*  glyph_name )
41   {
42     FT_Int  n;
43     char    first = glyph_name[0];
44     char    temp[64];
45
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         if ( d >= 16 )
82           break;
83
84         value = ( value << 4 ) + d;
85       }
86       if ( count == 0 )
87         return value;
88     }
89
90     /* look for a non-initial dot in the glyph name in order to */
91     /* sort-out variants like `A.swash', `e.final', etc.        */
92     {
93       const char*  p;
94       int          len;
95
96
97       p = glyph_name;
98
99       while ( *p && *p != '.' )
100         p++;
101
102       len = (int)( p - glyph_name );
103
104       if ( *p && len < 64 )
105       {
106         ft_strncpy( temp, glyph_name, len );
107         temp[len]  = 0;
108         glyph_name = temp;
109       }
110     }
111
112     /* now, look up the glyph in the Adobe Glyph List */
113     for ( n = 0; n < NUM_ADOBE_GLYPHS; n++ )
114     {
115       const char*  name = sid_standard_names[n];
116
117
118       if ( first == name[0] && ft_strcmp( glyph_name, name ) == 0 )
119         return ps_names_to_unicode[n];
120     }
121
122     /* not found, there is probably no Unicode value for this glyph name */
123     return 0;
124   }
125
126
127   /* ft_qsort callback to sort the unicode map */
128   FT_CALLBACK_DEF( int )
129   compare_uni_maps( const void*  a,
130                     const void*  b )
131   {
132     PS_UniMap*  map1 = (PS_UniMap*)a;
133     PS_UniMap*  map2 = (PS_UniMap*)b;
134
135
136     return ( map1->unicode - map2->unicode );
137   }
138
139
140   /* Builds a table that maps Unicode values to glyph indices */
141   static FT_Error
142   ps_build_unicode_table( FT_Memory     memory,
143                           FT_UInt       num_glyphs,
144                           const char**  glyph_names,
145                           PS_Unicodes*  table )
146   {
147     FT_Error  error;
148
149
150     /* we first allocate the table */
151     table->num_maps = 0;
152     table->maps     = 0;
153
154     if ( !FT_NEW_ARRAY( table->maps, num_glyphs ) )
155     {
156       FT_UInt     n;
157       FT_UInt     count;
158       PS_UniMap*  map;
159       FT_UInt32   uni_char;
160
161
162       map = table->maps;
163
164       for ( n = 0; n < num_glyphs; n++ )
165       {
166         const char*  gname = glyph_names[n];
167
168
169         if ( gname )
170         {
171           uni_char = ps_unicode_value( gname );
172
173           if ( uni_char != 0 && uni_char != 0xFFFF )
174           {
175             map->unicode     = uni_char;
176             map->glyph_index = n;
177             map++;
178           }
179         }
180       }
181
182       /* now, compress the table a bit */
183       count = (FT_UInt)( map - table->maps );
184
185       if ( count > 0 && FT_REALLOC( table->maps,
186                                     num_glyphs * sizeof ( PS_UniMap ),
187                                     count * sizeof ( PS_UniMap ) ) )
188         count = 0;
189
190       if ( count == 0 )
191       {
192         FT_FREE( table->maps );
193         if ( !error )
194           error = PSnames_Err_Invalid_Argument;  /* no unicode chars here! */
195       }
196       else
197         /* sort the table in increasing order of unicode values */
198         ft_qsort( table->maps, count, sizeof ( PS_UniMap ), compare_uni_maps );
199
200       table->num_maps = count;
201     }
202
203     return error;
204   }
205
206
207   static FT_UInt
208   ps_lookup_unicode( PS_Unicodes*  table,
209                      FT_ULong      unicode )
210   {
211     PS_UniMap  *min, *max, *mid;
212
213
214     /* perform a binary search on the table */
215
216     min = table->maps;
217     max = min + table->num_maps - 1;
218
219     while ( min <= max )
220     {
221       mid = min + ( max - min ) / 2;
222       if ( mid->unicode == unicode )
223         return mid->glyph_index;
224
225       if ( min == max )
226         break;
227
228       if ( mid->unicode < unicode )
229         min = mid + 1;
230       else
231         max = mid - 1;
232     }
233
234     return 0xFFFF;
235   }
236
237
238   static FT_ULong
239   ps_next_unicode( PS_Unicodes*  table,
240                    FT_ULong      unicode )
241   {
242     PS_UniMap  *min, *max, *mid;
243
244
245     unicode++;
246     /* perform a binary search on the table */
247
248     min = table->maps;
249     max = min + table->num_maps - 1;
250
251     while ( min <= max )
252     {
253       mid = min + ( max - min ) / 2;
254       if ( mid->unicode == unicode )
255         return unicode;
256
257       if ( min == max )
258         break;
259
260       if ( mid->unicode < unicode )
261         min = mid + 1;
262       else
263         max = mid - 1;
264     }
265
266     if ( max < table->maps )
267       max = table->maps;
268
269     while ( max < table->maps + table->num_maps )
270     {
271       if ( unicode < max->unicode )
272         return max->unicode;
273       max++;
274     }
275
276     return 0;
277   }
278
279
280 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
281
282
283   static const char*
284   ps_get_macintosh_name( FT_UInt  name_index )
285   {
286     if ( name_index >= 258 )
287       name_index = 0;
288
289     return ps_glyph_names[mac_standard_names[name_index]];
290   }
291
292
293   static const char*
294   ps_get_standard_strings( FT_UInt  sid )
295   {
296     return ( sid < NUM_SID_GLYPHS ? sid_standard_names[sid] : 0 );
297   }
298
299
300   static
301   const PSNames_Interface  psnames_interface =
302   {
303 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
304
305     (PS_Unicode_Value_Func)    ps_unicode_value,
306     (PS_Build_Unicodes_Func)   ps_build_unicode_table,
307     (PS_Lookup_Unicode_Func)   ps_lookup_unicode,
308
309 #else
310
311     0,
312     0,
313     0,
314
315 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
316
317     (PS_Macintosh_Name_Func)    ps_get_macintosh_name,
318     (PS_Adobe_Std_Strings_Func) ps_get_standard_strings,
319
320     t1_standard_encoding,
321     t1_expert_encoding,
322
323 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
324     (PS_Next_Unicode_Func)     ps_next_unicode
325 #else
326     0
327 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
328
329   };
330
331
332 #endif /* !FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES */
333
334
335   FT_CALLBACK_TABLE_DEF
336   const FT_Module_Class  psnames_module_class =
337   {
338     0,  /* this is not a font driver, nor a renderer */
339     sizeof ( FT_ModuleRec ),
340
341     "psnames",  /* driver name                         */
342     0x10000L,   /* driver version                      */
343     0x20000L,   /* driver requires FreeType 2 or above */
344
345 #ifdef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
346     0,
347 #else
348     (void*)&psnames_interface,   /* module specific interface */
349 #endif
350
351     (FT_Module_Constructor)0,
352     (FT_Module_Destructor) 0,
353     (FT_Module_Requester)  0
354   };
355
356
357 /* END */