blob: 55ab5dfce08408a4e92407df98376e2e2c6f8f59 [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>
David Turnera90663f2000-07-08 00:41:13 +000021
Werner Lemberg7fa51b52000-07-08 19:51:42 +000022
David Turnera90663f2000-07-08 00:41:13 +000023#ifdef FT_FLAT_COMPILE
Werner Lemberg7fa51b52000-07-08 19:51:42 +000024
David Turnera90663f2000-07-08 00:41:13 +000025#include "psmodule.h"
26#include "pstables.h"
Werner Lemberg7fa51b52000-07-08 19:51:42 +000027
David Turnera90663f2000-07-08 00:41:13 +000028#else
Werner Lemberg7fa51b52000-07-08 19:51:42 +000029
David Turnera90663f2000-07-08 00:41:13 +000030#include <psnames/psmodule.h>
31#include <psnames/pstables.h>
Werner Lemberg7fa51b52000-07-08 19:51:42 +000032
David Turnera90663f2000-07-08 00:41:13 +000033#endif
Werner Lemberga929ba92000-06-25 06:47:11 +000034
Werner Lemberg7fa51b52000-07-08 19:51:42 +000035
Werner Lemberga8bbc262000-07-01 14:06:46 +000036#include <stdlib.h> /* for qsort() */
Werner Lemberga929ba92000-06-25 06:47:11 +000037#include <string.h> /* for strcmp(), strncpy() */
38
David Turneraa4c28f2000-06-22 00:27:15 +000039
40#ifndef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
41
Werner Lemberga929ba92000-06-25 06:47:11 +000042
David Turneraa4c28f2000-06-22 00:27:15 +000043
Werner Lemberga929ba92000-06-25 06:47:11 +000044
David Turneraa4c28f2000-06-22 00:27:15 +000045#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
Werner Lemberga929ba92000-06-25 06:47:11 +000046
47
48 /* return the Unicode value corresponding to a given glyph. Note that */
49 /* we do deal with glyph variants by detecting a non-initial dot in */
50 /* the name, as in `A.swash' or `e.final', etc. */
51 /* */
David Turneraa4c28f2000-06-22 00:27:15 +000052 static
Werner Lemberga929ba92000-06-25 06:47:11 +000053 FT_ULong PS_Unicode_Value( const char* glyph_name )
David Turneraa4c28f2000-06-22 00:27:15 +000054 {
55 FT_Int n;
56 char first = glyph_name[0];
57 char temp[64];
58
Werner Lemberga929ba92000-06-25 06:47:11 +000059
60 /* if the name begins with `uni', then the glyph name may be a */
61 /* hard-coded unicode character code. */
David Turneraa4c28f2000-06-22 00:27:15 +000062 if ( glyph_name[0] == 'u' &&
63 glyph_name[1] == 'n' &&
64 glyph_name[2] == 'i' )
65 {
Werner Lemberga8bbc262000-07-01 14:06:46 +000066 /* determine whether the next four characters following are */
67 /* hexadecimal. */
68
69 /* XXX: Add code to deal with ligatures, i.e. glyph names like */
70 /* `uniXXXXYYYYZZZZ'... */
71
Werner Lemberga929ba92000-06-25 06:47:11 +000072 FT_Int count;
73 FT_ULong value = 0;
74 const char* p = glyph_name + 4;
David Turneraa4c28f2000-06-22 00:27:15 +000075
Werner Lemberga929ba92000-06-25 06:47:11 +000076
77 for ( count = 4; count > 0; count--, p++ )
David Turneraa4c28f2000-06-22 00:27:15 +000078 {
79 char c = *p;
80 unsigned char d;
81
Werner Lemberga929ba92000-06-25 06:47:11 +000082
83 d = (unsigned char)c - '0';
84 if ( d >= 10 )
David Turneraa4c28f2000-06-22 00:27:15 +000085 {
86 d = (unsigned char)c - 'A';
87 if ( d >= 6 )
88 d = 16;
89 else
90 d += 10;
91 }
Werner Lemberga8bbc262000-07-01 14:06:46 +000092
93 /* exit if a non-uppercase hexadecimal character was found */
Werner Lemberga929ba92000-06-25 06:47:11 +000094 if ( d >= 16 )
David Turneraa4c28f2000-06-22 00:27:15 +000095 break;
96
Werner Lemberga929ba92000-06-25 06:47:11 +000097 value = ( value << 4 ) + d;
Werner Lemberga8bbc262000-07-01 14:06:46 +000098
Werner Lemberga929ba92000-06-25 06:47:11 +000099 if ( count == 0 )
David Turneraa4c28f2000-06-22 00:27:15 +0000100 return value;
101 }
102 }
103
104 /* look for a non-initial dot in the glyph name in order to */
Werner Lemberga929ba92000-06-25 06:47:11 +0000105 /* sort-out variants like `A.swash', `e.final', etc. */
David Turneraa4c28f2000-06-22 00:27:15 +0000106 {
107 const char* p;
108 int len;
109
Werner Lemberga929ba92000-06-25 06:47:11 +0000110
David Turneraa4c28f2000-06-22 00:27:15 +0000111 p = glyph_name;
Werner Lemberga8bbc262000-07-01 14:06:46 +0000112
Werner Lemberga929ba92000-06-25 06:47:11 +0000113 while ( *p && *p != '.' )
114 p++;
Werner Lemberga8bbc262000-07-01 14:06:46 +0000115
Werner Lemberga929ba92000-06-25 06:47:11 +0000116 len = p - glyph_name;
David Turneraa4c28f2000-06-22 00:27:15 +0000117
118 if ( *p && len < 64 )
119 {
120 strncpy( temp, glyph_name, len );
121 temp[len] = 0;
122 glyph_name = temp;
123 }
124 }
125
Werner Lemberga8bbc262000-07-01 14:06:46 +0000126 /* now, look up the glyph in the Adobe Glyph List */
David Turneraa4c28f2000-06-22 00:27:15 +0000127 for ( n = 0; n < NUM_ADOBE_GLYPHS; n++ )
128 {
129 const char* name = t1_standard_glyphs[n];
130
Werner Lemberga929ba92000-06-25 06:47:11 +0000131
David Turneraa4c28f2000-06-22 00:27:15 +0000132 if ( first == name[0] && strcmp( glyph_name, name ) == 0 )
133 return names_to_unicode[n];
134 }
Werner Lemberga929ba92000-06-25 06:47:11 +0000135
David Turneraa4c28f2000-06-22 00:27:15 +0000136 /* not found, there is probably no Unicode value for this glyph name */
137 return 0;
138 }
139
140
Werner Lemberga929ba92000-06-25 06:47:11 +0000141 /* qsort callback to sort the unicode map */
David Turneraa4c28f2000-06-22 00:27:15 +0000142 static
Werner Lemberga929ba92000-06-25 06:47:11 +0000143 int compare_uni_maps( const void* a,
144 const void* b )
David Turneraa4c28f2000-06-22 00:27:15 +0000145 {
146 PS_UniMap* map1 = (PS_UniMap*)a;
147 PS_UniMap* map2 = (PS_UniMap*)b;
148
Werner Lemberga929ba92000-06-25 06:47:11 +0000149
David Turnere0bba322000-07-01 19:33:40 +0000150 return ( map1->unicode - map2->unicode );
David Turneraa4c28f2000-06-22 00:27:15 +0000151 }
152
153
Werner Lemberga929ba92000-06-25 06:47:11 +0000154 /* Builds a table that maps Unicode values to glyph indices */
David Turneraa4c28f2000-06-22 00:27:15 +0000155 static
156 FT_Error PS_Build_Unicode_Table( FT_Memory memory,
157 FT_UInt num_glyphs,
158 const char** glyph_names,
Werner Lemberga929ba92000-06-25 06:47:11 +0000159 PS_Unicodes* table )
David Turneraa4c28f2000-06-22 00:27:15 +0000160 {
161 FT_Error error;
162
Werner Lemberga929ba92000-06-25 06:47:11 +0000163
David Turneraa4c28f2000-06-22 00:27:15 +0000164 /* we first allocate the table */
165 table->num_maps = 0;
166 table->maps = 0;
167
168 if ( !ALLOC_ARRAY( table->maps, num_glyphs, PS_UniMap ) )
169 {
170 FT_UInt n;
171 FT_UInt count;
172 PS_UniMap* map;
173 FT_ULong uni_char;
174
Werner Lemberga929ba92000-06-25 06:47:11 +0000175
David Turneraa4c28f2000-06-22 00:27:15 +0000176 map = table->maps;
Werner Lemberga8bbc262000-07-01 14:06:46 +0000177
David Turneraa4c28f2000-06-22 00:27:15 +0000178 for ( n = 0; n < num_glyphs; n++ )
179 {
180 const char* gname = glyph_names[n];
Werner Lemberga929ba92000-06-25 06:47:11 +0000181
182
183 if ( gname )
David Turneraa4c28f2000-06-22 00:27:15 +0000184 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000185 uni_char = PS_Unicode_Value( gname );
Werner Lemberga8bbc262000-07-01 14:06:46 +0000186
Werner Lemberga929ba92000-06-25 06:47:11 +0000187 if ( uni_char && uni_char != 0xFFFF )
David Turneraa4c28f2000-06-22 00:27:15 +0000188 {
189 map->unicode = uni_char;
190 map->glyph_index = n;
191 map++;
192 }
193 }
194 }
195
196 /* now, compress the table a bit */
197 count = map - table->maps;
Werner Lemberga8bbc262000-07-01 14:06:46 +0000198
David Turneraa4c28f2000-06-22 00:27:15 +0000199 if ( count > 0 && REALLOC( table->maps,
Werner Lemberga929ba92000-06-25 06:47:11 +0000200 num_glyphs * sizeof ( PS_UniMap ),
201 count * sizeof ( PS_UniMap ) ) )
David Turneraa4c28f2000-06-22 00:27:15 +0000202 count = 0;
David Turneraa4c28f2000-06-22 00:27:15 +0000203
Werner Lemberga929ba92000-06-25 06:47:11 +0000204 if ( count == 0 )
David Turneraa4c28f2000-06-22 00:27:15 +0000205 {
206 FREE( table->maps );
Werner Lemberga929ba92000-06-25 06:47:11 +0000207 if ( !error )
208 error = FT_Err_Invalid_Argument; /* no unicode chars here! */
David Turneraa4c28f2000-06-22 00:27:15 +0000209 }
210 else
211 /* sort the table in increasing order of unicode values */
Werner Lemberga929ba92000-06-25 06:47:11 +0000212 qsort( table->maps, count, sizeof ( PS_UniMap ), compare_uni_maps );
David Turneraa4c28f2000-06-22 00:27:15 +0000213
214 table->num_maps = count;
215 }
Werner Lemberga929ba92000-06-25 06:47:11 +0000216
David Turneraa4c28f2000-06-22 00:27:15 +0000217 return error;
218 }
219
Werner Lemberga929ba92000-06-25 06:47:11 +0000220
David Turneraa4c28f2000-06-22 00:27:15 +0000221 static
222 FT_UInt PS_Lookup_Unicode( PS_Unicodes* table,
223 FT_ULong unicode )
224 {
225 PS_UniMap *min, *max, *mid;
Werner Lemberga929ba92000-06-25 06:47:11 +0000226
227
David Turneraa4c28f2000-06-22 00:27:15 +0000228 /* perform a binary search on the table */
Werner Lemberga8bbc262000-07-01 14:06:46 +0000229
David Turneraa4c28f2000-06-22 00:27:15 +0000230 min = table->maps;
231 max = min + table->num_maps - 1;
232
Werner Lemberga929ba92000-06-25 06:47:11 +0000233 while ( min <= max )
David Turneraa4c28f2000-06-22 00:27:15 +0000234 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000235 mid = min + ( max - min ) / 2;
David Turneraa4c28f2000-06-22 00:27:15 +0000236 if ( mid->unicode == unicode )
237 return mid->glyph_index;
238
Werner Lemberga929ba92000-06-25 06:47:11 +0000239 if ( min == max )
David Turneraa4c28f2000-06-22 00:27:15 +0000240 break;
241
Werner Lemberga929ba92000-06-25 06:47:11 +0000242 if ( mid->unicode < unicode )
243 min = mid + 1;
244 else
245 max = mid - 1;
David Turneraa4c28f2000-06-22 00:27:15 +0000246 }
247
248 return 0xFFFF;
249 }
250
David Turneraa4c28f2000-06-22 00:27:15 +0000251
Werner Lemberga929ba92000-06-25 06:47:11 +0000252#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
David Turneraa4c28f2000-06-22 00:27:15 +0000253
254
255 static
256 const char* PS_Macintosh_Name( FT_UInt name_index )
257 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000258 if ( name_index >= 258 )
David Turneraa4c28f2000-06-22 00:27:15 +0000259 name_index = 0;
260
Werner Lemberga929ba92000-06-25 06:47:11 +0000261 return standard_glyph_names[mac_standard_names[name_index]];
David Turneraa4c28f2000-06-22 00:27:15 +0000262 }
263
264
David Turneraa4c28f2000-06-22 00:27:15 +0000265 static
266 const char* PS_Standard_Strings( FT_UInt sid )
267 {
Werner Lemberga929ba92000-06-25 06:47:11 +0000268 return ( sid < NUM_STD_GLYPHS ? t1_standard_glyphs[sid] : 0 );
David Turneraa4c28f2000-06-22 00:27:15 +0000269 }
270
271
Werner Lemberga929ba92000-06-25 06:47:11 +0000272 static const PSNames_Interface psnames_interface =
David Turneraa4c28f2000-06-22 00:27:15 +0000273 {
274#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
David Turneraa4c28f2000-06-22 00:27:15 +0000275
Werner Lemberga929ba92000-06-25 06:47:11 +0000276 (PS_Unicode_Value_Func) PS_Unicode_Value,
277 (PS_Build_Unicodes_Func) PS_Build_Unicode_Table,
278 (PS_Lookup_Unicode_Func) PS_Lookup_Unicode,
279
280#else
281
282 0,
283 0,
284 0,
285
286#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
287
288 (PS_Macintosh_Name_Func) PS_Macintosh_Name,
289 (PS_Adobe_Std_Strings_Func)PS_Standard_Strings,
David Turneraa4c28f2000-06-22 00:27:15 +0000290
291 t1_standard_encoding,
292 t1_expert_encoding
293 };
294
David Turneraa4c28f2000-06-22 00:27:15 +0000295
Werner Lemberga929ba92000-06-25 06:47:11 +0000296#endif /* !FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES */
David Turneraa4c28f2000-06-22 00:27:15 +0000297
298
299 const FT_Module_Class psnames_module_class =
300 {
301 0, /* this is not a font driver, nor a renderer */
Werner Lemberga929ba92000-06-25 06:47:11 +0000302 sizeof( FT_ModuleRec ),
David Turneraa4c28f2000-06-22 00:27:15 +0000303
304 "psnames", /* driver name */
Werner Lemberga8bbc262000-07-01 14:06:46 +0000305 0x10000L, /* driver version */
306 0x20000L, /* driver requires FreeType 2 or above */
David Turneraa4c28f2000-06-22 00:27:15 +0000307
308#ifdef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
309 0,
310#else
311 (void*)&psnames_interface, /* module specific interface */
312#endif
Werner Lembergfbeb41d2000-07-02 00:27:53 +0000313
Werner Lemberga929ba92000-06-25 06:47:11 +0000314 (FT_Module_Constructor)0,
315 (FT_Module_Destructor) 0,
316 (FT_Module_Requester) 0
David Turneraa4c28f2000-06-22 00:27:15 +0000317 };
318
Werner Lemberga929ba92000-06-25 06:47:11 +0000319
320/* END */