- Merge from trunk up to r45543
[reactos.git] / lib / 3rdparty / freetype / src / psnames / psmodule.c
1 /***************************************************************************/
2 /* */
3 /* psmodule.c */
4 /* */
5 /* PSNames module implementation (body). */
6 /* */
7 /* Copyright 1996-2001, 2002, 2003, 2005, 2006, 2007 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_OBJECTS_H
21 #include FT_SERVICE_POSTSCRIPT_CMAPS_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 #define VARIANT_BIT 0x80000000UL
36 #define BASE_GLYPH( code ) ( (code) & ~VARIANT_BIT )
37
38
39 /* Return the Unicode value corresponding to a given glyph. Note that */
40 /* we do deal with glyph variants by detecting a non-initial dot in */
41 /* the name, as in `A.swash' or `e.final'; in this case, the */
42 /* VARIANT_BIT is set in the return value. */
43 /* */
44 static FT_UInt32
45 ps_unicode_value( const char* glyph_name )
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 /* -- this also catches character codes below `0' since such */
82 /* negative numbers cast to `unsigned int' are far too big. */
83 if ( d >= 16 )
84 break;
85
86 value = ( value << 4 ) + d;
87 }
88
89 /* there must be exactly four hex digits */
90 if ( count == 0 )
91 {
92 if ( *p == '\0' )
93 return value;
94 if ( *p == '.' )
95 return value | VARIANT_BIT;
96 }
97 }
98
99 /* If the name begins with `u', followed by four to six uppercase */
100 /* hexadecimal digits, it is a hard-coded unicode character code. */
101 if ( glyph_name[0] == 'u' )
102 {
103 FT_Int count;
104 FT_ULong value = 0;
105 const char* p = glyph_name + 1;
106
107
108 for ( count = 6; count > 0; count--, p++ )
109 {
110 char c = *p;
111 unsigned int d;
112
113
114 d = (unsigned char)c - '0';
115 if ( d >= 10 )
116 {
117 d = (unsigned char)c - 'A';
118 if ( d >= 6 )
119 d = 16;
120 else
121 d += 10;
122 }
123
124 if ( d >= 16 )
125 break;
126
127 value = ( value << 4 ) + d;
128 }
129
130 if ( count <= 2 )
131 {
132 if ( *p == '\0' )
133 return value;
134 if ( *p == '.' )
135 return value | VARIANT_BIT;
136 }
137 }
138
139 /* Look for a non-initial dot in the glyph name in order to */
140 /* find variants like `A.swash', `e.final', etc. */
141 {
142 const char* p = glyph_name;
143 const char* dot = NULL;
144
145
146 for ( ; *p; p++ )
147 {
148 if ( *p == '.' && p > glyph_name )
149 {
150 dot = p;
151 break;
152 }
153 }
154
155 /* now look up the glyph in the Adobe Glyph List */
156 if ( !dot )
157 return ft_get_adobe_glyph_index( glyph_name, p );
158 else
159 return ft_get_adobe_glyph_index( glyph_name, dot ) | VARIANT_BIT;
160 }
161 }
162
163
164 /* ft_qsort callback to sort the unicode map */
165 FT_CALLBACK_DEF( int )
166 compare_uni_maps( const void* a,
167 const void* b )
168 {
169 PS_UniMap* map1 = (PS_UniMap*)a;
170 PS_UniMap* map2 = (PS_UniMap*)b;
171 FT_UInt32 unicode1 = BASE_GLYPH( map1->unicode );
172 FT_UInt32 unicode2 = BASE_GLYPH( map2->unicode );
173
174
175 /* sort base glyphs before glyph variants */
176 if ( unicode1 == unicode2 )
177 return map1->unicode - map2->unicode;
178 else
179 return unicode1 - unicode2;
180 }
181
182
183 /* Build a table that maps Unicode values to glyph indices. */
184 static FT_Error
185 ps_unicodes_init( FT_Memory memory,
186 PS_Unicodes table,
187 FT_UInt num_glyphs,
188 PS_GetGlyphNameFunc get_glyph_name,
189 PS_FreeGlyphNameFunc free_glyph_name,
190 FT_Pointer glyph_data )
191 {
192 FT_Error error;
193
194
195 /* we first allocate the table */
196 table->num_maps = 0;
197 table->maps = 0;
198
199 if ( !FT_NEW_ARRAY( table->maps, num_glyphs ) )
200 {
201 FT_UInt n;
202 FT_UInt count;
203 PS_UniMap* map;
204 FT_UInt32 uni_char;
205
206
207 map = table->maps;
208
209 for ( n = 0; n < num_glyphs; n++ )
210 {
211 const char* gname = get_glyph_name( glyph_data, n );
212
213
214 if ( gname )
215 {
216 uni_char = ps_unicode_value( gname );
217
218 if ( BASE_GLYPH( uni_char ) != 0 )
219 {
220 map->unicode = uni_char;
221 map->glyph_index = n;
222 map++;
223 }
224
225 if ( free_glyph_name )
226 free_glyph_name( glyph_data, gname );
227 }
228 }
229
230 /* now compress the table a bit */
231 count = (FT_UInt)( map - table->maps );
232
233 if ( count == 0 )
234 {
235 FT_FREE( table->maps );
236 if ( !error )
237 error = PSnames_Err_Invalid_Argument; /* No unicode chars here! */
238 }
239 else {
240 /* Reallocate if the number of used entries is much smaller. */
241 if ( count < num_glyphs / 2 )
242 {
243 (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );
244 error = PSnames_Err_Ok;
245 }
246
247 /* Sort the table in increasing order of unicode values, */
248 /* taking care of glyph variants. */
249 ft_qsort( table->maps, count, sizeof ( PS_UniMap ),
250 compare_uni_maps );
251 }
252
253 table->num_maps = count;
254 }
255
256 return error;
257 }
258
259
260 static FT_UInt
261 ps_unicodes_char_index( PS_Unicodes table,
262 FT_UInt32 unicode )
263 {
264 PS_UniMap *min, *max, *mid, *result = NULL;
265
266
267 /* Perform a binary search on the table. */
268
269 min = table->maps;
270 max = min + table->num_maps - 1;
271
272 while ( min <= max )
273 {
274 FT_UInt32 base_glyph;
275
276
277 mid = min + ( ( max - min ) >> 1 );
278
279 if ( mid->unicode == unicode )
280 {
281 result = mid;
282 break;
283 }
284
285 base_glyph = BASE_GLYPH( mid->unicode );
286
287 if ( base_glyph == unicode )
288 result = mid; /* remember match but continue search for base glyph */
289
290 if ( min == max )
291 break;
292
293 if ( base_glyph < unicode )
294 min = mid + 1;
295 else
296 max = mid - 1;
297 }
298
299 if ( result )
300 return result->glyph_index;
301 else
302 return 0;
303 }
304
305
306 static FT_ULong
307 ps_unicodes_char_next( PS_Unicodes table,
308 FT_UInt32 *unicode )
309 {
310 FT_UInt result = 0;
311 FT_UInt32 char_code = *unicode + 1;
312
313
314 {
315 FT_UInt min = 0;
316 FT_UInt max = table->num_maps;
317 FT_UInt mid;
318 PS_UniMap* map;
319 FT_UInt32 base_glyph;
320
321
322 while ( min < max )
323 {
324 mid = min + ( ( max - min ) >> 1 );
325 map = table->maps + mid;
326
327 if ( map->unicode == char_code )
328 {
329 result = map->glyph_index;
330 goto Exit;
331 }
332
333 base_glyph = BASE_GLYPH( map->unicode );
334
335 if ( base_glyph == char_code )
336 result = map->glyph_index;
337
338 if ( base_glyph < char_code )
339 min = mid + 1;
340 else
341 max = mid;
342 }
343
344 if ( result )
345 goto Exit; /* we have a variant glyph */
346
347 /* we didn't find it; check whether we have a map just above it */
348 char_code = 0;
349
350 if ( min < table->num_maps )
351 {
352 map = table->maps + min;
353 result = map->glyph_index;
354 char_code = BASE_GLYPH( map->unicode );
355 }
356 }
357
358 Exit:
359 *unicode = char_code;
360 return result;
361 }
362
363
364 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
365
366
367 static const char*
368 ps_get_macintosh_name( FT_UInt name_index )
369 {
370 if ( name_index >= FT_NUM_MAC_NAMES )
371 name_index = 0;
372
373 return ft_standard_glyph_names + ft_mac_names[name_index];
374 }
375
376
377 static const char*
378 ps_get_standard_strings( FT_UInt sid )
379 {
380 if ( sid >= FT_NUM_SID_NAMES )
381 return 0;
382
383 return ft_standard_glyph_names + ft_sid_names[sid];
384 }
385
386
387 static
388 const FT_Service_PsCMapsRec pscmaps_interface =
389 {
390 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
391
392 (PS_Unicode_ValueFunc) ps_unicode_value,
393 (PS_Unicodes_InitFunc) ps_unicodes_init,
394 (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,
395 (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,
396
397 #else
398
399 0,
400 0,
401 0,
402 0,
403
404 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
405
406 (PS_Macintosh_NameFunc) ps_get_macintosh_name,
407 (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
408
409 t1_standard_encoding,
410 t1_expert_encoding
411 };
412
413
414 static const FT_ServiceDescRec pscmaps_services[] =
415 {
416 { FT_SERVICE_ID_POSTSCRIPT_CMAPS, &pscmaps_interface },
417 { NULL, NULL }
418 };
419
420
421 static FT_Pointer
422 psnames_get_service( FT_Module module,
423 const char* service_id )
424 {
425 FT_UNUSED( module );
426
427 return ft_service_list_lookup( pscmaps_services, service_id );
428 }
429
430 #endif /* !FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES */
431
432
433
434 FT_CALLBACK_TABLE_DEF
435 const FT_Module_Class psnames_module_class =
436 {
437 0, /* this is not a font driver, nor a renderer */
438 sizeof ( FT_ModuleRec ),
439
440 "psnames", /* driver name */
441 0x10000L, /* driver version */
442 0x20000L, /* driver requires FreeType 2 or above */
443
444 #ifdef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
445 0,
446 (FT_Module_Constructor)0,
447 (FT_Module_Destructor) 0,
448 (FT_Module_Requester) 0
449 #else
450 (void*)&pscmaps_interface, /* module specific interface */
451 (FT_Module_Constructor)0,
452 (FT_Module_Destructor) 0,
453 (FT_Module_Requester) psnames_get_service
454 #endif
455 };
456
457
458 /* END */