Sync with trunk (aka 'I want my virtualbox mouse integration too')
[reactos.git] / lib / 3rdparty / freetype / src / sfnt / sfdriver.c
1 /***************************************************************************/
2 /* */
3 /* sfdriver.c */
4 /* */
5 /* High-level SFNT driver interface (body). */
6 /* */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 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_SFNT_H
21 #include FT_INTERNAL_OBJECTS_H
22
23 #include "sfdriver.h"
24 #include "ttload.h"
25 #include "sfobjs.h"
26
27 #include "sferrors.h"
28
29 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
30 #include "ttsbit.h"
31 #endif
32
33 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
34 #include "ttpost.h"
35 #endif
36
37 #ifdef TT_CONFIG_OPTION_BDF
38 #include "ttbdf.h"
39 #include FT_SERVICE_BDF_H
40 #endif
41
42 #include "ttcmap.h"
43 #include "ttkern.h"
44 #include "ttmtx.h"
45
46 #include FT_SERVICE_GLYPH_DICT_H
47 #include FT_SERVICE_POSTSCRIPT_NAME_H
48 #include FT_SERVICE_SFNT_H
49 #include FT_SERVICE_TT_CMAP_H
50
51
52 /*
53 * SFNT TABLE SERVICE
54 *
55 */
56
57 static void*
58 get_sfnt_table( TT_Face face,
59 FT_Sfnt_Tag tag )
60 {
61 void* table;
62
63
64 switch ( tag )
65 {
66 case ft_sfnt_head:
67 table = &face->header;
68 break;
69
70 case ft_sfnt_hhea:
71 table = &face->horizontal;
72 break;
73
74 case ft_sfnt_vhea:
75 table = face->vertical_info ? &face->vertical : 0;
76 break;
77
78 case ft_sfnt_os2:
79 table = face->os2.version == 0xFFFFU ? 0 : &face->os2;
80 break;
81
82 case ft_sfnt_post:
83 table = &face->postscript;
84 break;
85
86 case ft_sfnt_maxp:
87 table = &face->max_profile;
88 break;
89
90 case ft_sfnt_pclt:
91 table = face->pclt.Version ? &face->pclt : 0;
92 break;
93
94 default:
95 table = 0;
96 }
97
98 return table;
99 }
100
101
102 static FT_Error
103 sfnt_table_info( TT_Face face,
104 FT_UInt idx,
105 FT_ULong *tag,
106 FT_ULong *length )
107 {
108 if ( !tag || !length )
109 return SFNT_Err_Invalid_Argument;
110
111 if ( idx >= face->num_tables )
112 return SFNT_Err_Table_Missing;
113
114 *tag = face->dir_tables[idx].Tag;
115 *length = face->dir_tables[idx].Length;
116
117 return SFNT_Err_Ok;
118 }
119
120
121 static const FT_Service_SFNT_TableRec sfnt_service_sfnt_table =
122 {
123 (FT_SFNT_TableLoadFunc)tt_face_load_any,
124 (FT_SFNT_TableGetFunc) get_sfnt_table,
125 (FT_SFNT_TableInfoFunc)sfnt_table_info
126 };
127
128
129 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
130
131 /*
132 * GLYPH DICT SERVICE
133 *
134 */
135
136 static FT_Error
137 sfnt_get_glyph_name( TT_Face face,
138 FT_UInt glyph_index,
139 FT_Pointer buffer,
140 FT_UInt buffer_max )
141 {
142 FT_String* gname;
143 FT_Error error;
144
145
146 error = tt_face_get_ps_name( face, glyph_index, &gname );
147 if ( !error )
148 FT_STRCPYN( buffer, gname, buffer_max );
149
150 return error;
151 }
152
153
154 static const FT_Service_GlyphDictRec sfnt_service_glyph_dict =
155 {
156 (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name,
157 (FT_GlyphDict_NameIndexFunc)NULL
158 };
159
160 #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
161
162
163 /*
164 * POSTSCRIPT NAME SERVICE
165 *
166 */
167
168 static const char*
169 sfnt_get_ps_name( TT_Face face )
170 {
171 FT_Int n, found_win, found_apple;
172 const char* result = NULL;
173
174
175 /* shouldn't happen, but just in case to avoid memory leaks */
176 if ( face->postscript_name )
177 return face->postscript_name;
178
179 /* scan the name table to see whether we have a Postscript name here, */
180 /* either in Macintosh or Windows platform encodings */
181 found_win = -1;
182 found_apple = -1;
183
184 for ( n = 0; n < face->num_names; n++ )
185 {
186 TT_NameEntryRec* name = face->name_table.names + n;
187
188
189 if ( name->nameID == 6 && name->stringLength > 0 )
190 {
191 if ( name->platformID == 3 &&
192 name->encodingID == 1 &&
193 name->languageID == 0x409 )
194 found_win = n;
195
196 if ( name->platformID == 1 &&
197 name->encodingID == 0 &&
198 name->languageID == 0 )
199 found_apple = n;
200 }
201 }
202
203 if ( found_win != -1 )
204 {
205 FT_Memory memory = face->root.memory;
206 TT_NameEntryRec* name = face->name_table.names + found_win;
207 FT_UInt len = name->stringLength / 2;
208 FT_Error error = SFNT_Err_Ok;
209
210 FT_UNUSED( error );
211
212
213 if ( !FT_ALLOC( result, name->stringLength + 1 ) )
214 {
215 FT_Stream stream = face->name_table.stream;
216 FT_String* r = (FT_String*)result;
217 FT_Byte* p = (FT_Byte*)name->string;
218
219
220 if ( FT_STREAM_SEEK( name->stringOffset ) ||
221 FT_FRAME_ENTER( name->stringLength ) )
222 {
223 FT_FREE( result );
224 name->stringLength = 0;
225 name->stringOffset = 0;
226 FT_FREE( name->string );
227
228 goto Exit;
229 }
230
231 p = (FT_Byte*)stream->cursor;
232
233 for ( ; len > 0; len--, p += 2 )
234 {
235 if ( p[0] == 0 && p[1] >= 32 && p[1] < 128 )
236 *r++ = p[1];
237 }
238 *r = '\0';
239
240 FT_FRAME_EXIT();
241 }
242 goto Exit;
243 }
244
245 if ( found_apple != -1 )
246 {
247 FT_Memory memory = face->root.memory;
248 TT_NameEntryRec* name = face->name_table.names + found_apple;
249 FT_UInt len = name->stringLength;
250 FT_Error error = SFNT_Err_Ok;
251
252 FT_UNUSED( error );
253
254
255 if ( !FT_ALLOC( result, len + 1 ) )
256 {
257 FT_Stream stream = face->name_table.stream;
258
259
260 if ( FT_STREAM_SEEK( name->stringOffset ) ||
261 FT_STREAM_READ( result, len ) )
262 {
263 name->stringOffset = 0;
264 name->stringLength = 0;
265 FT_FREE( name->string );
266 FT_FREE( result );
267 goto Exit;
268 }
269 ((char*)result)[len] = '\0';
270 }
271 }
272
273 Exit:
274 face->postscript_name = result;
275 return result;
276 }
277
278 static const FT_Service_PsFontNameRec sfnt_service_ps_name =
279 {
280 (FT_PsName_GetFunc)sfnt_get_ps_name
281 };
282
283
284 /*
285 * TT CMAP INFO
286 */
287 static const FT_Service_TTCMapsRec tt_service_get_cmap_info =
288 {
289 (TT_CMap_Info_GetFunc)tt_get_cmap_info
290 };
291
292
293 #ifdef TT_CONFIG_OPTION_BDF
294
295 static FT_Error
296 sfnt_get_charset_id( TT_Face face,
297 const char* *acharset_encoding,
298 const char* *acharset_registry )
299 {
300 BDF_PropertyRec encoding, registry;
301 FT_Error error;
302
303
304 /* XXX: I don't know whether this is correct, since
305 * tt_face_find_bdf_prop only returns something correct if we have
306 * previously selected a size that is listed in the BDF table.
307 * Should we change the BDF table format to include single offsets
308 * for `CHARSET_REGISTRY' and `CHARSET_ENCODING'?
309 */
310 error = tt_face_find_bdf_prop( face, "CHARSET_REGISTRY", &registry );
311 if ( !error )
312 {
313 error = tt_face_find_bdf_prop( face, "CHARSET_ENCODING", &encoding );
314 if ( !error )
315 {
316 if ( registry.type == BDF_PROPERTY_TYPE_ATOM &&
317 encoding.type == BDF_PROPERTY_TYPE_ATOM )
318 {
319 *acharset_encoding = encoding.u.atom;
320 *acharset_registry = registry.u.atom;
321 }
322 else
323 error = FT_Err_Invalid_Argument;
324 }
325 }
326
327 return error;
328 }
329
330
331 static const FT_Service_BDFRec sfnt_service_bdf =
332 {
333 (FT_BDF_GetCharsetIdFunc) sfnt_get_charset_id,
334 (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop,
335 };
336
337 #endif /* TT_CONFIG_OPTION_BDF */
338
339
340 /*
341 * SERVICE LIST
342 */
343
344 static const FT_ServiceDescRec sfnt_services[] =
345 {
346 { FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table },
347 { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name },
348 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
349 { FT_SERVICE_ID_GLYPH_DICT, &sfnt_service_glyph_dict },
350 #endif
351 #ifdef TT_CONFIG_OPTION_BDF
352 { FT_SERVICE_ID_BDF, &sfnt_service_bdf },
353 #endif
354 { FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info },
355
356 { NULL, NULL }
357 };
358
359
360 FT_CALLBACK_DEF( FT_Module_Interface )
361 sfnt_get_interface( FT_Module module,
362 const char* module_interface )
363 {
364 FT_UNUSED( module );
365
366 return ft_service_list_lookup( sfnt_services, module_interface );
367 }
368
369
370 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
371
372 FT_CALLBACK_DEF( FT_Error )
373 tt_face_load_sfnt_header_stub( TT_Face face,
374 FT_Stream stream,
375 FT_Long face_index,
376 SFNT_Header header )
377 {
378 FT_UNUSED( face );
379 FT_UNUSED( stream );
380 FT_UNUSED( face_index );
381 FT_UNUSED( header );
382
383 return FT_Err_Unimplemented_Feature;
384 }
385
386
387 FT_CALLBACK_DEF( FT_Error )
388 tt_face_load_directory_stub( TT_Face face,
389 FT_Stream stream,
390 SFNT_Header header )
391 {
392 FT_UNUSED( face );
393 FT_UNUSED( stream );
394 FT_UNUSED( header );
395
396 return FT_Err_Unimplemented_Feature;
397 }
398
399
400 FT_CALLBACK_DEF( FT_Error )
401 tt_face_load_hdmx_stub( TT_Face face,
402 FT_Stream stream )
403 {
404 FT_UNUSED( face );
405 FT_UNUSED( stream );
406
407 return FT_Err_Unimplemented_Feature;
408 }
409
410
411 FT_CALLBACK_DEF( void )
412 tt_face_free_hdmx_stub( TT_Face face )
413 {
414 FT_UNUSED( face );
415 }
416
417
418 FT_CALLBACK_DEF( FT_Error )
419 tt_face_set_sbit_strike_stub( TT_Face face,
420 FT_UInt x_ppem,
421 FT_UInt y_ppem,
422 FT_ULong* astrike_index )
423 {
424 /*
425 * We simply forge a FT_Size_Request and call the real function
426 * that does all the work.
427 *
428 * This stub might be called by libXfont in the X.Org Xserver,
429 * compiled against version 2.1.8 or newer.
430 */
431
432 FT_Size_RequestRec req;
433
434
435 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
436 req.width = (FT_F26Dot6)x_ppem;
437 req.height = (FT_F26Dot6)y_ppem;
438 req.horiResolution = 0;
439 req.vertResolution = 0;
440
441 *astrike_index = 0x7FFFFFFFUL;
442
443 return tt_face_set_sbit_strike( face, &req, astrike_index );
444 }
445
446
447 FT_CALLBACK_DEF( FT_Error )
448 tt_face_load_sbit_stub( TT_Face face,
449 FT_Stream stream )
450 {
451 FT_UNUSED( face );
452 FT_UNUSED( stream );
453
454 /*
455 * This function was originally implemented to load the sbit table.
456 * However, it has been replaced by `tt_face_load_eblc', and this stub
457 * is only there for some rogue clients which would want to call it
458 * directly (which doesn't make much sense).
459 */
460 return FT_Err_Unimplemented_Feature;
461 }
462
463
464 FT_CALLBACK_DEF( void )
465 tt_face_free_sbit_stub( TT_Face face )
466 {
467 /* nothing to do in this stub */
468 FT_UNUSED( face );
469 }
470
471
472 FT_CALLBACK_DEF( FT_Error )
473 tt_face_load_charmap_stub( TT_Face face,
474 void* cmap,
475 FT_Stream input )
476 {
477 FT_UNUSED( face );
478 FT_UNUSED( cmap );
479 FT_UNUSED( input );
480
481 return FT_Err_Unimplemented_Feature;
482 }
483
484
485 FT_CALLBACK_DEF( FT_Error )
486 tt_face_free_charmap_stub( TT_Face face,
487 void* cmap )
488 {
489 FT_UNUSED( face );
490 FT_UNUSED( cmap );
491
492 return 0;
493 }
494
495 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
496
497
498 static
499 const SFNT_Interface sfnt_interface =
500 {
501 tt_face_goto_table,
502
503 sfnt_init_face,
504 sfnt_load_face,
505 sfnt_done_face,
506 sfnt_get_interface,
507
508 tt_face_load_any,
509
510 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
511 tt_face_load_sfnt_header_stub,
512 tt_face_load_directory_stub,
513 #endif
514
515 tt_face_load_head,
516 tt_face_load_hhea,
517 tt_face_load_cmap,
518 tt_face_load_maxp,
519 tt_face_load_os2,
520 tt_face_load_post,
521
522 tt_face_load_name,
523 tt_face_free_name,
524
525 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
526 tt_face_load_hdmx_stub,
527 tt_face_free_hdmx_stub,
528 #endif
529
530 tt_face_load_kern,
531 tt_face_load_gasp,
532 tt_face_load_pclt,
533
534 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
535 /* see `ttload.h' */
536 tt_face_load_bhed,
537 #else
538 0,
539 #endif
540
541 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
542 tt_face_set_sbit_strike_stub,
543 tt_face_load_sbit_stub,
544
545 tt_find_sbit_image,
546 tt_load_sbit_metrics,
547 #endif
548
549 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
550 tt_face_load_sbit_image,
551 #else
552 0,
553 #endif
554
555 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
556 tt_face_free_sbit_stub,
557 #endif
558
559 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
560 /* see `ttpost.h' */
561 tt_face_get_ps_name,
562 tt_face_free_ps_names,
563 #else
564 0,
565 0,
566 #endif
567
568 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
569 tt_face_load_charmap_stub,
570 tt_face_free_charmap_stub,
571 #endif
572
573 /* since version 2.1.8 */
574
575 tt_face_get_kerning,
576
577 /* since version 2.2 */
578
579 tt_face_load_font_dir,
580 tt_face_load_hmtx,
581
582 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
583 /* see `ttsbit.h' and `sfnt.h' */
584 tt_face_load_eblc,
585 tt_face_free_eblc,
586
587 tt_face_set_sbit_strike,
588 tt_face_load_strike_metrics,
589 #else
590 0,
591 0,
592 0,
593 0,
594 #endif
595
596 tt_face_get_metrics
597 };
598
599
600 FT_CALLBACK_TABLE_DEF
601 const FT_Module_Class sfnt_module_class =
602 {
603 0, /* not a font driver or renderer */
604 sizeof( FT_ModuleRec ),
605
606 "sfnt", /* driver name */
607 0x10000L, /* driver version 1.0 */
608 0x20000L, /* driver requires FreeType 2.0 or higher */
609
610 (const void*)&sfnt_interface, /* module specific interface */
611
612 (FT_Module_Constructor)0,
613 (FT_Module_Destructor) 0,
614 (FT_Module_Requester) sfnt_get_interface
615 };
616
617
618 /* END */