blob: ebbae1afcd116bc628099a19a13b6919a22e513b [file] [log] [blame]
Werner Lemberga929ba92000-06-25 06:47:11 +00001/***************************************************************************/
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
David Turneraa4c28f2000-06-22 00:27:15 +000019#include <freetype/internal/psnames.h>
20#include <freetype/internal/ftobjs.h>
21#include <psmodule.h>
Werner Lemberga929ba92000-06-25 06:47:11 +000022
David Turneraa4c28f2000-06-22 00:27:15 +000023#include <stdlib.h>
Werner Lemberga929ba92000-06-25 06:47:11 +000024#include <string.h> /* for strcmp(), strncpy() */
25
David Turneraa4c28f2000-06-22 00:27:15 +000026
27#ifndef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
28
Werner Lemberga929ba92000-06-25 06:47:11 +000029
30 /* see the python script `freetype2/docs/glnames.py' which is used */
31 /* to generate the following tables... */
David Turneraa4c28f2000-06-22 00:27:15 +000032#include <pstables.h>
33
Werner Lemberga929ba92000-06-25 06:47:11 +000034
David Turneraa4c28f2000-06-22 00:27:15 +000035#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
Werner Lemberga929ba92000-06-25 06:47:11 +000036
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 /* */
David Turneraa4c28f2000-06-22 00:27:15 +000042 static
Werner Lemberga929ba92000-06-25 06:47:11 +000043 FT_ULong PS_Unicode_Value( const char* glyph_name )
David Turneraa4c28f2000-06-22 00:27:15 +000044 {
45 FT_Int n;
46 char first = glyph_name[0];
47 char temp[64];
48
Werner Lemberga929ba92000-06-25 06:47:11 +000049
50 /* if the name begins with `uni', then the glyph name may be a */
51 /* hard-coded unicode character code. */
David Turneraa4c28f2000-06-22 00:27:15 +000052 if ( glyph_name[0] == 'u' &&
53 glyph_name[1] == 'n' &&
54 glyph_name[2] == 'i' )
55 {
56 /* determine wether the following characters are hexadecimal */
Werner Lemberga929ba92000-06-25 06:47:11 +000057 FT_Int count;
58 FT_ULong value = 0;
59 const char* p = glyph_name + 4;
David Turneraa4c28f2000-06-22 00:27:15 +000060
Werner Lemberga929ba92000-06-25 06:47:11 +000061
62 for ( count = 4; count > 0; count--, p++ )
David Turneraa4c28f2000-06-22 00:27:15 +000063 {
64 char c = *p;
65 unsigned char d;
66
Werner Lemberga929ba92000-06-25 06:47:11 +000067
68 d = (unsigned char)c - '0';
69 if ( d >= 10 )
David Turneraa4c28f2000-06-22 00:27:15 +000070 {
71 d = (unsigned char)c - 'A';
72 if ( d >= 6 )
73 d = 16;
74 else
75 d += 10;
76 }
Werner Lemberga929ba92000-06-25 06:47:11 +000077 /* exit if a non-uppercase-hexadecimal character was found */
78 if ( d >= 16 )
David Turneraa4c28f2000-06-22 00:27:15 +000079 break;
80
Werner Lemberga929ba92000-06-25 06:47:11 +000081 value = ( value << 4 ) + d;
82 if ( count == 0 )
David Turneraa4c28f2000-06-22 00:27:15 +000083 return value;
84 }
85 }
86
87 /* look for a non-initial dot in the glyph name in order to */
Werner Lemberga929ba92000-06-25 06:47:11 +000088 /* sort-out variants like `A.swash', `e.final', etc. */
David Turneraa4c28f2000-06-22 00:27:15 +000089 {
90 const char* p;
91 int len;
92
Werner Lemberga929ba92000-06-25 06:47:11 +000093
David Turneraa4c28f2000-06-22 00:27:15 +000094 p = glyph_name;
Werner Lemberga929ba92000-06-25 06:47:11 +000095 while ( *p && *p != '.' )
96 p++;
97 len = p - glyph_name;
David Turneraa4c28f2000-06-22 00:27:15 +000098
99 if ( *p && len < 64 )
100 {
101 strncpy( temp, glyph_name, len );
102 temp[len] = 0;
103 glyph_name = temp;
104 }
105 }
106
107 /* now, lookup the glyph in the Adobe Glyph List */
108 for ( n = 0; n < NUM_ADOBE_GLYPHS; n++ )
109 {
110 const char* name = t1_standard_glyphs[n];
111
Werner Lemberga929ba92000-06-25 06:47:11 +0000112
David Turneraa4c28f2000-06-22 00:27:15 +0000113 if ( first == name[0] && strcmp( glyph_name, name ) == 0 )
114 return names_to_unicode[n];
115 }
Werner Lemberga929ba92000-06-25 06:47:11 +0000116
David Turneraa4c28f2000-06-22 00:27:15 +0000117 /* not found, there is probably no Unicode value for this glyph name */
118 return 0;
119 }
120
121
Werner Lemberga929ba92000-06-25 06:47:11 +0000122 /* qsort callback to sort the unicode map */
David Turneraa4c28f2000-06-22 00:27:15 +0000123 static
Werner Lemberga929ba92000-06-25 06:47:11 +0000124 int compare_uni_maps( const void* a,
125 const void* b )
David Turneraa4c28f2000-06-22 00:27:15 +0000126 {
127 PS_UniMap* map1 = (PS_UniMap*)a;
128 PS_UniMap* map2 = (PS_UniMap*)b;
129
Werner Lemberga929ba92000-06-25 06:47:11 +0000130
David Turneraa4c28f2000-06-22 00:27:15 +0000131 return ( map1->unicode < map2->unicode ? -1 :
132 map1->unicode > map2->unicode ? 1 : 0 );
133 }
134
135
Werner Lemberga929ba92000-06-25 06:47:11 +0000136 /* Builds a table that maps Unicode values to glyph indices */
David Turneraa4c28f2000-06-22 00:27:15 +0000137 static
138 FT_Error PS_Build_Unicode_Table( FT_Memory memory,
139 FT_UInt num_glyphs,
140 const char** glyph_names,
Werner Lemberga929ba92000-06-25 06:47:11 +0000141 PS_Unicodes* table )
David Turneraa4c28f2000-06-22 00:27:15 +0000142 {
143 FT_Error error;
144
Werner Lemberga929ba92000-06-25 06:47:11 +0000145
David Turneraa4c28f2000-06-22 00:27:15 +0000146 /* we first allocate the table */
147 table->num_maps = 0;
148 table->maps = 0;
149
150 if ( !ALLOC_ARRAY( table->maps, num_glyphs, PS_UniMap ) )
151 {
152 FT_UInt n;
153 FT_UInt count;
154 PS_UniMap* map;
155 FT_ULong uni_char;
156
Werner Lemberga929ba92000-06-25 06:47:11 +0000157
David Turneraa4c28f2000-06-22 00:27:15 +0000158 map = table->maps;
159 for ( n = 0; n < num_glyphs; n++ )
160 {
161 const char* gname = glyph_names[n];
Werner Lemberga929ba92000-06-25 06:47:11 +0000162
163
164 if ( gname )
David Turneraa4c28f2000-06-22 00:27:15 +0000165 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000166 uni_char = PS_Unicode_Value( gname );
167 if ( uni_char && uni_char != 0xFFFF )
David Turneraa4c28f2000-06-22 00:27:15 +0000168 {
169 map->unicode = uni_char;
170 map->glyph_index = n;
171 map++;
172 }
173 }
174 }
175
176 /* now, compress the table a bit */
177 count = map - table->maps;
178 if ( count > 0 && REALLOC( table->maps,
Werner Lemberga929ba92000-06-25 06:47:11 +0000179 num_glyphs * sizeof ( PS_UniMap ),
180 count * sizeof ( PS_UniMap ) ) )
David Turneraa4c28f2000-06-22 00:27:15 +0000181 count = 0;
David Turneraa4c28f2000-06-22 00:27:15 +0000182
Werner Lemberga929ba92000-06-25 06:47:11 +0000183 if ( count == 0 )
David Turneraa4c28f2000-06-22 00:27:15 +0000184 {
185 FREE( table->maps );
Werner Lemberga929ba92000-06-25 06:47:11 +0000186 if ( !error )
187 error = FT_Err_Invalid_Argument; /* no unicode chars here! */
David Turneraa4c28f2000-06-22 00:27:15 +0000188 }
189 else
190 /* sort the table in increasing order of unicode values */
Werner Lemberga929ba92000-06-25 06:47:11 +0000191 qsort( table->maps, count, sizeof ( PS_UniMap ), compare_uni_maps );
David Turneraa4c28f2000-06-22 00:27:15 +0000192
193 table->num_maps = count;
194 }
Werner Lemberga929ba92000-06-25 06:47:11 +0000195
David Turneraa4c28f2000-06-22 00:27:15 +0000196 return error;
197 }
198
Werner Lemberga929ba92000-06-25 06:47:11 +0000199
David Turneraa4c28f2000-06-22 00:27:15 +0000200 static
201 FT_UInt PS_Lookup_Unicode( PS_Unicodes* table,
202 FT_ULong unicode )
203 {
204 PS_UniMap *min, *max, *mid;
Werner Lemberga929ba92000-06-25 06:47:11 +0000205
206
David Turneraa4c28f2000-06-22 00:27:15 +0000207 /* perform a binary search on the table */
208 min = table->maps;
209 max = min + table->num_maps - 1;
210
Werner Lemberga929ba92000-06-25 06:47:11 +0000211 while ( min <= max )
David Turneraa4c28f2000-06-22 00:27:15 +0000212 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000213 mid = min + ( max - min ) / 2;
David Turneraa4c28f2000-06-22 00:27:15 +0000214 if ( mid->unicode == unicode )
215 return mid->glyph_index;
216
Werner Lemberga929ba92000-06-25 06:47:11 +0000217 if ( min == max )
David Turneraa4c28f2000-06-22 00:27:15 +0000218 break;
219
Werner Lemberga929ba92000-06-25 06:47:11 +0000220 if ( mid->unicode < unicode )
221 min = mid + 1;
222 else
223 max = mid - 1;
David Turneraa4c28f2000-06-22 00:27:15 +0000224 }
225
226 return 0xFFFF;
227 }
228
David Turneraa4c28f2000-06-22 00:27:15 +0000229
Werner Lemberga929ba92000-06-25 06:47:11 +0000230#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
David Turneraa4c28f2000-06-22 00:27:15 +0000231
232
233 static
234 const char* PS_Macintosh_Name( FT_UInt name_index )
235 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000236 if ( name_index >= 258 )
David Turneraa4c28f2000-06-22 00:27:15 +0000237 name_index = 0;
238
Werner Lemberga929ba92000-06-25 06:47:11 +0000239 return standard_glyph_names[mac_standard_names[name_index]];
David Turneraa4c28f2000-06-22 00:27:15 +0000240 }
241
242
David Turneraa4c28f2000-06-22 00:27:15 +0000243 static
244 const char* PS_Standard_Strings( FT_UInt sid )
245 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000246 return ( sid < NUM_STD_GLYPHS ? t1_standard_glyphs[sid] : 0 );
David Turneraa4c28f2000-06-22 00:27:15 +0000247 }
248
249
Werner Lemberga929ba92000-06-25 06:47:11 +0000250 static const PSNames_Interface psnames_interface =
David Turneraa4c28f2000-06-22 00:27:15 +0000251 {
252#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
David Turneraa4c28f2000-06-22 00:27:15 +0000253
Werner Lemberga929ba92000-06-25 06:47:11 +0000254 (PS_Unicode_Value_Func) PS_Unicode_Value,
255 (PS_Build_Unicodes_Func) PS_Build_Unicode_Table,
256 (PS_Lookup_Unicode_Func) PS_Lookup_Unicode,
257
258#else
259
260 0,
261 0,
262 0,
263
264#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
265
266 (PS_Macintosh_Name_Func) PS_Macintosh_Name,
267 (PS_Adobe_Std_Strings_Func)PS_Standard_Strings,
David Turneraa4c28f2000-06-22 00:27:15 +0000268
269 t1_standard_encoding,
270 t1_expert_encoding
271 };
272
David Turneraa4c28f2000-06-22 00:27:15 +0000273
Werner Lemberga929ba92000-06-25 06:47:11 +0000274#endif /* !FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES */
David Turneraa4c28f2000-06-22 00:27:15 +0000275
276
277 const FT_Module_Class psnames_module_class =
278 {
279 0, /* this is not a font driver, nor a renderer */
Werner Lemberga929ba92000-06-25 06:47:11 +0000280 sizeof( FT_ModuleRec ),
David Turneraa4c28f2000-06-22 00:27:15 +0000281
282 "psnames", /* driver name */
283 100, /* driver version */
284 200, /* driver requires FreeType 2 or above */
285
286#ifdef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
287 0,
288#else
289 (void*)&psnames_interface, /* module specific interface */
290#endif
291
Werner Lemberga929ba92000-06-25 06:47:11 +0000292 (FT_Module_Constructor)0,
293 (FT_Module_Destructor) 0,
294 (FT_Module_Requester) 0
David Turneraa4c28f2000-06-22 00:27:15 +0000295 };
296
Werner Lemberga929ba92000-06-25 06:47:11 +0000297
298/* END */