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