sync with trunk r46493
[reactos.git] / lib / 3rdparty / freetype / src / sfnt / sfobjs.c
1 /***************************************************************************/
2 /* */
3 /* sfobjs.c */
4 /* */
5 /* SFNT object management (base). */
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 "sfobjs.h"
21 #include "ttload.h"
22 #include "ttcmap.h"
23 #include "ttkern.h"
24 #include FT_INTERNAL_SFNT_H
25 #include FT_INTERNAL_DEBUG_H
26 #include FT_TRUETYPE_IDS_H
27 #include FT_TRUETYPE_TAGS_H
28 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
29 #include "sferrors.h"
30
31 #ifdef TT_CONFIG_OPTION_BDF
32 #include "ttbdf.h"
33 #endif
34
35
36 /*************************************************************************/
37 /* */
38 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
39 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
40 /* messages during execution. */
41 /* */
42 #undef FT_COMPONENT
43 #define FT_COMPONENT trace_sfobjs
44
45
46
47 /* convert a UTF-16 name entry to ASCII */
48 static FT_String*
49 tt_name_entry_ascii_from_utf16( TT_NameEntry entry,
50 FT_Memory memory )
51 {
52 FT_String* string;
53 FT_UInt len, code, n;
54 FT_Byte* read = (FT_Byte*)entry->string;
55 FT_Error error;
56
57
58 len = (FT_UInt)entry->stringLength / 2;
59
60 if ( FT_NEW_ARRAY( string, len + 1 ) )
61 return NULL;
62
63 for ( n = 0; n < len; n++ )
64 {
65 code = FT_NEXT_USHORT( read );
66 if ( code < 32 || code > 127 )
67 code = '?';
68
69 string[n] = (char)code;
70 }
71
72 string[len] = 0;
73
74 return string;
75 }
76
77
78 /* convert an Apple Roman or symbol name entry to ASCII */
79 static FT_String*
80 tt_name_entry_ascii_from_other( TT_NameEntry entry,
81 FT_Memory memory )
82 {
83 FT_String* string;
84 FT_UInt len, code, n;
85 FT_Byte* read = (FT_Byte*)entry->string;
86 FT_Error error;
87
88
89 len = (FT_UInt)entry->stringLength;
90
91 if ( FT_NEW_ARRAY( string, len + 1 ) )
92 return NULL;
93
94 for ( n = 0; n < len; n++ )
95 {
96 code = *read++;
97 if ( code < 32 || code > 127 )
98 code = '?';
99
100 string[n] = (char)code;
101 }
102
103 string[len] = 0;
104
105 return string;
106 }
107
108
109 typedef FT_String* (*TT_NameEntry_ConvertFunc)( TT_NameEntry entry,
110 FT_Memory memory );
111
112
113 /*************************************************************************/
114 /* */
115 /* <Function> */
116 /* tt_face_get_name */
117 /* */
118 /* <Description> */
119 /* Returns a given ENGLISH name record in ASCII. */
120 /* */
121 /* <Input> */
122 /* face :: A handle to the source face object. */
123 /* */
124 /* nameid :: The name id of the name record to return. */
125 /* */
126 /* <Return> */
127 /* Character string. NULL if no name is present. */
128 /* */
129 static FT_String*
130 tt_face_get_name( TT_Face face,
131 FT_UShort nameid )
132 {
133 FT_Memory memory = face->root.memory;
134 FT_String* result = NULL;
135 FT_UShort n;
136 TT_NameEntryRec* rec;
137 FT_Int found_apple = -1;
138 FT_Int found_apple_roman = -1;
139 FT_Int found_apple_english = -1;
140 FT_Int found_win = -1;
141 FT_Int found_unicode = -1;
142
143 FT_Bool is_english = 0;
144
145 TT_NameEntry_ConvertFunc convert;
146
147
148 rec = face->name_table.names;
149 for ( n = 0; n < face->num_names; n++, rec++ )
150 {
151 /* According to the OpenType 1.3 specification, only Microsoft or */
152 /* Apple platform IDs might be used in the `name' table. The */
153 /* `Unicode' platform is reserved for the `cmap' table, and the */
154 /* `Iso' one is deprecated. */
155 /* */
156 /* However, the Apple TrueType specification doesn't say the same */
157 /* thing and goes to suggest that all Unicode `name' table entries */
158 /* should be coded in UTF-16 (in big-endian format I suppose). */
159 /* */
160 if ( rec->nameID == nameid && rec->stringLength > 0 )
161 {
162 switch ( rec->platformID )
163 {
164 case TT_PLATFORM_APPLE_UNICODE:
165 case TT_PLATFORM_ISO:
166 /* there is `languageID' to check there. We should use this */
167 /* field only as a last solution when nothing else is */
168 /* available. */
169 /* */
170 found_unicode = n;
171 break;
172
173 case TT_PLATFORM_MACINTOSH:
174 /* This is a bit special because some fonts will use either */
175 /* an English language id, or a Roman encoding id, to indicate */
176 /* the English version of its font name. */
177 /* */
178 if ( rec->languageID == TT_MAC_LANGID_ENGLISH )
179 found_apple_english = n;
180 else if ( rec->encodingID == TT_MAC_ID_ROMAN )
181 found_apple_roman = n;
182 break;
183
184 case TT_PLATFORM_MICROSOFT:
185 /* we only take a non-English name when there is nothing */
186 /* else available in the font */
187 /* */
188 if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 )
189 {
190 switch ( rec->encodingID )
191 {
192 case TT_MS_ID_SYMBOL_CS:
193 case TT_MS_ID_UNICODE_CS:
194 case TT_MS_ID_UCS_4:
195 is_english = FT_BOOL( ( rec->languageID & 0x3FF ) == 0x009 );
196 found_win = n;
197 break;
198
199 default:
200 ;
201 }
202 }
203 break;
204
205 default:
206 ;
207 }
208 }
209 }
210
211 found_apple = found_apple_roman;
212 if ( found_apple_english >= 0 )
213 found_apple = found_apple_english;
214
215 /* some fonts contain invalid Unicode or Macintosh formatted entries; */
216 /* we will thus favor names encoded in Windows formats if available */
217 /* (provided it is an English name) */
218 /* */
219 convert = NULL;
220 if ( found_win >= 0 && !( found_apple >= 0 && !is_english ) )
221 {
222 rec = face->name_table.names + found_win;
223 switch ( rec->encodingID )
224 {
225 /* all Unicode strings are encoded using UTF-16BE */
226 case TT_MS_ID_UNICODE_CS:
227 case TT_MS_ID_SYMBOL_CS:
228 convert = tt_name_entry_ascii_from_utf16;
229 break;
230
231 case TT_MS_ID_UCS_4:
232 /* Apparently, if this value is found in a name table entry, it is */
233 /* documented as `full Unicode repertoire'. Experience with the */
234 /* MsGothic font shipped with Windows Vista shows that this really */
235 /* means UTF-16 encoded names (UCS-4 values are only used within */
236 /* charmaps). */
237 convert = tt_name_entry_ascii_from_utf16;
238 break;
239
240 default:
241 ;
242 }
243 }
244 else if ( found_apple >= 0 )
245 {
246 rec = face->name_table.names + found_apple;
247 convert = tt_name_entry_ascii_from_other;
248 }
249 else if ( found_unicode >= 0 )
250 {
251 rec = face->name_table.names + found_unicode;
252 convert = tt_name_entry_ascii_from_utf16;
253 }
254
255 if ( rec && convert )
256 {
257 if ( rec->string == NULL )
258 {
259 FT_Error error = SFNT_Err_Ok;
260 FT_Stream stream = face->name_table.stream;
261
262 FT_UNUSED( error );
263
264
265 if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) ||
266 FT_STREAM_SEEK( rec->stringOffset ) ||
267 FT_STREAM_READ( rec->string, rec->stringLength ) )
268 {
269 FT_FREE( rec->string );
270 rec->stringLength = 0;
271 result = NULL;
272 goto Exit;
273 }
274 }
275
276 result = convert( rec, memory );
277 }
278
279 Exit:
280 return result;
281 }
282
283
284 static FT_Encoding
285 sfnt_find_encoding( int platform_id,
286 int encoding_id )
287 {
288 typedef struct TEncoding
289 {
290 int platform_id;
291 int encoding_id;
292 FT_Encoding encoding;
293
294 } TEncoding;
295
296 static
297 const TEncoding tt_encodings[] =
298 {
299 { TT_PLATFORM_ISO, -1, FT_ENCODING_UNICODE },
300
301 { TT_PLATFORM_APPLE_UNICODE, -1, FT_ENCODING_UNICODE },
302
303 { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, FT_ENCODING_APPLE_ROMAN },
304
305 { TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS, FT_ENCODING_MS_SYMBOL },
306 { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, FT_ENCODING_UNICODE },
307 { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE },
308 { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, FT_ENCODING_SJIS },
309 { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, FT_ENCODING_GB2312 },
310 { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, FT_ENCODING_BIG5 },
311 { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, FT_ENCODING_WANSUNG },
312 { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, FT_ENCODING_JOHAB }
313 };
314
315 const TEncoding *cur, *limit;
316
317
318 cur = tt_encodings;
319 limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );
320
321 for ( ; cur < limit; cur++ )
322 {
323 if ( cur->platform_id == platform_id )
324 {
325 if ( cur->encoding_id == encoding_id ||
326 cur->encoding_id == -1 )
327 return cur->encoding;
328 }
329 }
330
331 return FT_ENCODING_NONE;
332 }
333
334
335 /* Fill in face->ttc_header. If the font is not a TTC, it is */
336 /* synthesized into a TTC with one offset table. */
337 static FT_Error
338 sfnt_open_font( FT_Stream stream,
339 TT_Face face )
340 {
341 FT_Memory memory = stream->memory;
342 FT_Error error;
343 FT_ULong tag, offset;
344
345 static const FT_Frame_Field ttc_header_fields[] =
346 {
347 #undef FT_STRUCTURE
348 #define FT_STRUCTURE TTC_HeaderRec
349
350 FT_FRAME_START( 8 ),
351 FT_FRAME_LONG( version ),
352 FT_FRAME_LONG( count ),
353 FT_FRAME_END
354 };
355
356
357 face->ttc_header.tag = 0;
358 face->ttc_header.version = 0;
359 face->ttc_header.count = 0;
360
361 offset = FT_STREAM_POS();
362
363 if ( FT_READ_ULONG( tag ) )
364 return error;
365
366 if ( tag != 0x00010000UL &&
367 tag != TTAG_ttcf &&
368 tag != FT_MAKE_TAG( 'O', 'T', 'T', 'O' ) &&
369 tag != TTAG_true &&
370 tag != 0x00020000UL )
371 return SFNT_Err_Unknown_File_Format;
372
373 face->ttc_header.tag = TTAG_ttcf;
374
375 if ( tag == TTAG_ttcf )
376 {
377 FT_Int n;
378
379
380 FT_TRACE3(( "sfnt_open_font: file is a collection\n" ));
381
382 if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )
383 return error;
384
385 /* now read the offsets of each font in the file */
386 if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) )
387 return error;
388
389 if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) )
390 return error;
391
392 for ( n = 0; n < face->ttc_header.count; n++ )
393 face->ttc_header.offsets[n] = FT_GET_ULONG();
394
395 FT_FRAME_EXIT();
396 }
397 else
398 {
399 FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" ));
400
401 face->ttc_header.version = 1 << 16;
402 face->ttc_header.count = 1;
403
404 if ( FT_NEW( face->ttc_header.offsets) )
405 return error;
406
407 face->ttc_header.offsets[0] = offset;
408 }
409
410 return error;
411 }
412
413
414 FT_LOCAL_DEF( FT_Error )
415 sfnt_init_face( FT_Stream stream,
416 TT_Face face,
417 FT_Int face_index,
418 FT_Int num_params,
419 FT_Parameter* params )
420 {
421 FT_Error error;
422 FT_Library library = face->root.driver->root.library;
423 SFNT_Service sfnt;
424
425
426 /* for now, parameters are unused */
427 FT_UNUSED( num_params );
428 FT_UNUSED( params );
429
430
431 sfnt = (SFNT_Service)face->sfnt;
432 if ( !sfnt )
433 {
434 sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
435 if ( !sfnt )
436 return SFNT_Err_Invalid_File_Format;
437
438 face->sfnt = sfnt;
439 face->goto_table = sfnt->goto_table;
440 }
441
442 FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS );
443
444 error = sfnt_open_font( stream, face );
445 if ( error )
446 return error;
447
448 FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index ));
449
450 if ( face_index < 0 )
451 face_index = 0;
452
453 if ( face_index >= face->ttc_header.count )
454 return SFNT_Err_Bad_Argument;
455
456 if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) )
457 return error;
458
459 /* check that we have a valid TrueType file */
460 error = sfnt->load_font_dir( face, stream );
461 if ( error )
462 return error;
463
464 face->root.num_faces = face->ttc_header.count;
465
466 return error;
467 }
468
469
470 #define LOAD_( x ) \
471 do { \
472 FT_TRACE2(( "`" #x "' " )); \
473 FT_TRACE3(( "-->\n" )); \
474 \
475 error = sfnt->load_##x( face, stream ); \
476 \
477 FT_TRACE2(( "%s\n", ( !error ) \
478 ? "loaded" \
479 : ( error == SFNT_Err_Table_Missing ) \
480 ? "missing" \
481 : "failed to load" )); \
482 FT_TRACE3(( "\n" )); \
483 } while ( 0 )
484
485 #define LOADM_( x, vertical ) \
486 do { \
487 FT_TRACE2(( "`%s" #x "' ", \
488 vertical ? "vertical " : "" )); \
489 FT_TRACE3(( "-->\n" )); \
490 \
491 error = sfnt->load_##x( face, stream, vertical ); \
492 \
493 FT_TRACE2(( "%s\n", ( !error ) \
494 ? "loaded" \
495 : ( error == SFNT_Err_Table_Missing ) \
496 ? "missing" \
497 : "failed to load" )); \
498 FT_TRACE3(( "\n" )); \
499 } while ( 0 )
500
501
502 FT_LOCAL_DEF( FT_Error )
503 sfnt_load_face( FT_Stream stream,
504 TT_Face face,
505 FT_Int face_index,
506 FT_Int num_params,
507 FT_Parameter* params )
508 {
509 FT_Error error, psnames_error;
510 FT_Bool has_outline;
511 FT_Bool is_apple_sbit;
512
513 SFNT_Service sfnt = (SFNT_Service)face->sfnt;
514
515 FT_UNUSED( face_index );
516 FT_UNUSED( num_params );
517 FT_UNUSED( params );
518
519
520 /* Load tables */
521
522 /* We now support two SFNT-based bitmapped font formats. They */
523 /* are recognized easily as they do not include a `glyf' */
524 /* table. */
525 /* */
526 /* The first format comes from Apple, and uses a table named */
527 /* `bhed' instead of `head' to store the font header (using */
528 /* the same format). It also doesn't include horizontal and */
529 /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */
530 /* missing). */
531 /* */
532 /* The other format comes from Microsoft, and is used with */
533 /* WinCE/PocketPC. It looks like a standard TTF, except that */
534 /* it doesn't contain outlines. */
535 /* */
536
537 FT_TRACE2(( "sfnt_load_face: %08p\n\n", face ));
538
539 /* do we have outlines in there? */
540 #ifdef FT_CONFIG_OPTION_INCREMENTAL
541 has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 ||
542 tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
543 tt_face_lookup_table( face, TTAG_CFF ) != 0 );
544 #else
545 has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
546 tt_face_lookup_table( face, TTAG_CFF ) != 0 );
547 #endif
548
549 is_apple_sbit = 0;
550
551 /* if this font doesn't contain outlines, we try to load */
552 /* a `bhed' table */
553 if ( !has_outline && sfnt->load_bhed )
554 {
555 LOAD_( bhed );
556 is_apple_sbit = FT_BOOL( !error );
557 }
558
559 /* load the font header (`head' table) if this isn't an Apple */
560 /* sbit font file */
561 if ( !is_apple_sbit )
562 {
563 LOAD_( head );
564 if ( error )
565 goto Exit;
566 }
567
568 if ( face->header.Units_Per_EM == 0 )
569 {
570 error = SFNT_Err_Invalid_Table;
571
572 goto Exit;
573 }
574
575 /* the following tables are often not present in embedded TrueType */
576 /* fonts within PDF documents, so don't check for them. */
577 LOAD_( maxp );
578 LOAD_( cmap );
579
580 /* the following tables are optional in PCL fonts -- */
581 /* don't check for errors */
582 LOAD_( name );
583 LOAD_( post );
584 psnames_error = error;
585
586 /* do not load the metrics headers and tables if this is an Apple */
587 /* sbit font file */
588 if ( !is_apple_sbit )
589 {
590 /* load the `hhea' and `hmtx' tables */
591 LOADM_( hhea, 0 );
592 if ( !error )
593 {
594 LOADM_( hmtx, 0 );
595 if ( error == SFNT_Err_Table_Missing )
596 {
597 error = SFNT_Err_Hmtx_Table_Missing;
598
599 #ifdef FT_CONFIG_OPTION_INCREMENTAL
600 /* If this is an incrementally loaded font and there are */
601 /* overriding metrics, tolerate a missing `hmtx' table. */
602 if ( face->root.internal->incremental_interface &&
603 face->root.internal->incremental_interface->funcs->
604 get_glyph_metrics )
605 {
606 face->horizontal.number_Of_HMetrics = 0;
607 error = SFNT_Err_Ok;
608 }
609 #endif
610 }
611 }
612 else if ( error == SFNT_Err_Table_Missing )
613 {
614 /* No `hhea' table necessary for SFNT Mac fonts. */
615 if ( face->format_tag == TTAG_true )
616 {
617 FT_TRACE2(( "This is an SFNT Mac font.\n" ));
618 has_outline = 0;
619 error = SFNT_Err_Ok;
620 }
621 else
622 {
623 error = SFNT_Err_Horiz_Header_Missing;
624
625 #ifdef FT_CONFIG_OPTION_INCREMENTAL
626 /* If this is an incrementally loaded font and there are */
627 /* overriding metrics, tolerate a missing `hhea' table. */
628 if ( face->root.internal->incremental_interface &&
629 face->root.internal->incremental_interface->funcs->
630 get_glyph_metrics )
631 {
632 face->horizontal.number_Of_HMetrics = 0;
633 error = SFNT_Err_Ok;
634 }
635 #endif
636
637 }
638 }
639
640 if ( error )
641 goto Exit;
642
643 /* try to load the `vhea' and `vmtx' tables */
644 LOADM_( hhea, 1 );
645 if ( !error )
646 {
647 LOADM_( hmtx, 1 );
648 if ( !error )
649 face->vertical_info = 1;
650 }
651
652 if ( error && error != SFNT_Err_Table_Missing )
653 goto Exit;
654
655 LOAD_( os2 );
656 if ( error )
657 {
658 if ( error != SFNT_Err_Table_Missing )
659 goto Exit;
660
661 face->os2.version = 0xFFFFU;
662 }
663
664 }
665
666 /* the optional tables */
667
668 /* embedded bitmap support. */
669 if ( sfnt->load_eblc )
670 {
671 LOAD_( eblc );
672 if ( error )
673 {
674 /* return an error if this font file has no outlines */
675 if ( error == SFNT_Err_Table_Missing && has_outline )
676 error = SFNT_Err_Ok;
677 else
678 goto Exit;
679 }
680 }
681
682 LOAD_( pclt );
683 if ( error )
684 {
685 if ( error != SFNT_Err_Table_Missing )
686 goto Exit;
687
688 face->pclt.Version = 0;
689 }
690
691 /* consider the kerning and gasp tables as optional */
692 LOAD_( gasp );
693 LOAD_( kern );
694
695 error = SFNT_Err_Ok;
696
697 face->root.num_glyphs = face->max_profile.numGlyphs;
698
699 face->root.family_name = tt_face_get_name( face,
700 TT_NAME_ID_PREFERRED_FAMILY );
701 if ( !face->root.family_name )
702 face->root.family_name = tt_face_get_name( face,
703 TT_NAME_ID_FONT_FAMILY );
704
705 face->root.style_name = tt_face_get_name( face,
706 TT_NAME_ID_PREFERRED_SUBFAMILY );
707 if ( !face->root.style_name )
708 face->root.style_name = tt_face_get_name( face,
709 TT_NAME_ID_FONT_SUBFAMILY );
710
711 /* now set up root fields */
712 {
713 FT_Face root = &face->root;
714 FT_Int32 flags = root->face_flags;
715
716
717 /*********************************************************************/
718 /* */
719 /* Compute face flags. */
720 /* */
721 if ( has_outline == TRUE )
722 flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */
723
724 /* The sfnt driver only supports bitmap fonts natively, thus we */
725 /* don't set FT_FACE_FLAG_HINTER. */
726 flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */
727 FT_FACE_FLAG_HORIZONTAL; /* horizontal data */
728
729 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
730 if ( psnames_error == SFNT_Err_Ok &&
731 face->postscript.FormatType != 0x00030000L )
732 flags |= FT_FACE_FLAG_GLYPH_NAMES;
733 #endif
734
735 /* fixed width font? */
736 if ( face->postscript.isFixedPitch )
737 flags |= FT_FACE_FLAG_FIXED_WIDTH;
738
739 /* vertical information? */
740 if ( face->vertical_info )
741 flags |= FT_FACE_FLAG_VERTICAL;
742
743 /* kerning available ? */
744 if ( TT_FACE_HAS_KERNING( face ) )
745 flags |= FT_FACE_FLAG_KERNING;
746
747 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
748 /* Don't bother to load the tables unless somebody asks for them. */
749 /* No need to do work which will (probably) not be used. */
750 if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 &&
751 tt_face_lookup_table( face, TTAG_fvar ) != 0 &&
752 tt_face_lookup_table( face, TTAG_gvar ) != 0 )
753 flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
754 #endif
755
756 root->face_flags = flags;
757
758 /*********************************************************************/
759 /* */
760 /* Compute style flags. */
761 /* */
762 flags = 0;
763 if ( has_outline == TRUE && face->os2.version != 0xFFFFU )
764 {
765 /* we have an OS/2 table; use the `fsSelection' field */
766 if ( face->os2.fsSelection & 1 )
767 flags |= FT_STYLE_FLAG_ITALIC;
768
769 if ( face->os2.fsSelection & 32 )
770 flags |= FT_STYLE_FLAG_BOLD;
771 }
772 else
773 {
774 /* this is an old Mac font, use the header field */
775 if ( face->header.Mac_Style & 1 )
776 flags |= FT_STYLE_FLAG_BOLD;
777
778 if ( face->header.Mac_Style & 2 )
779 flags |= FT_STYLE_FLAG_ITALIC;
780 }
781
782 root->style_flags = flags;
783
784 /*********************************************************************/
785 /* */
786 /* Polish the charmaps. */
787 /* */
788 /* Try to set the charmap encoding according to the platform & */
789 /* encoding ID of each charmap. */
790 /* */
791
792 tt_face_build_cmaps( face ); /* ignore errors */
793
794
795 /* set the encoding fields */
796 {
797 FT_Int m;
798
799
800 for ( m = 0; m < root->num_charmaps; m++ )
801 {
802 FT_CharMap charmap = root->charmaps[m];
803
804
805 charmap->encoding = sfnt_find_encoding( charmap->platform_id,
806 charmap->encoding_id );
807
808 #if 0
809 if ( root->charmap == NULL &&
810 charmap->encoding == FT_ENCODING_UNICODE )
811 {
812 /* set 'root->charmap' to the first Unicode encoding we find */
813 root->charmap = charmap;
814 }
815 #endif
816 }
817 }
818
819
820 /*********************************************************************/
821 /* */
822 /* Set up metrics. */
823 /* */
824 if ( has_outline == TRUE )
825 {
826 /* XXX What about if outline header is missing */
827 /* (e.g. sfnt wrapped bitmap)? */
828 root->bbox.xMin = face->header.xMin;
829 root->bbox.yMin = face->header.yMin;
830 root->bbox.xMax = face->header.xMax;
831 root->bbox.yMax = face->header.yMax;
832 root->units_per_EM = face->header.Units_Per_EM;
833
834
835 /* XXX: Computing the ascender/descender/height is very different */
836 /* from what the specification tells you. Apparently, we */
837 /* must be careful because */
838 /* */
839 /* - not all fonts have an OS/2 table; in this case, we take */
840 /* the values in the horizontal header. However, these */
841 /* values very often are not reliable. */
842 /* */
843 /* - otherwise, the correct typographic values are in the */
844 /* sTypoAscender, sTypoDescender & sTypoLineGap fields. */
845 /* */
846 /* However, certain fonts have these fields set to 0. */
847 /* Rather, they have usWinAscent & usWinDescent correctly */
848 /* set (but with different values). */
849 /* */
850 /* As an example, Arial Narrow is implemented through four */
851 /* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
852 /* */
853 /* Strangely, all fonts have the same values in their */
854 /* sTypoXXX fields, except ARIALNB which sets them to 0. */
855 /* */
856 /* On the other hand, they all have different */
857 /* usWinAscent/Descent values -- as a conclusion, the OS/2 */
858 /* table cannot be used to compute the text height reliably! */
859 /* */
860
861 /* The ascender/descender/height are computed from the OS/2 table */
862 /* when found. Otherwise, they're taken from the horizontal */
863 /* header. */
864 /* */
865
866 root->ascender = face->horizontal.Ascender;
867 root->descender = face->horizontal.Descender;
868
869 root->height = (FT_Short)( root->ascender - root->descender +
870 face->horizontal.Line_Gap );
871
872 #if 0
873 /* if the line_gap is 0, we add an extra 15% to the text height -- */
874 /* this computation is based on various versions of Times New Roman */
875 if ( face->horizontal.Line_Gap == 0 )
876 root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 );
877 #endif
878
879 #if 0
880
881 /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
882 /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF */
883 if ( face->os2.version != 0xFFFFU && root->ascender )
884 {
885 FT_Int height;
886
887
888 root->ascender = face->os2.sTypoAscender;
889 root->descender = -face->os2.sTypoDescender;
890
891 height = root->ascender + root->descender + face->os2.sTypoLineGap;
892 if ( height > root->height )
893 root->height = height;
894 }
895
896 #endif /* 0 */
897
898 root->max_advance_width = face->horizontal.advance_Width_Max;
899
900 root->max_advance_height = (FT_Short)( face->vertical_info
901 ? face->vertical.advance_Height_Max
902 : root->height );
903
904 root->underline_position = face->postscript.underlinePosition;
905 root->underline_thickness = face->postscript.underlineThickness;
906 }
907
908 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
909
910 /*
911 * Now allocate the root array of FT_Bitmap_Size records and
912 * populate them. Unfortunately, it isn't possible to indicate bit
913 * depths in the FT_Bitmap_Size record. This is a design error.
914 */
915 {
916 FT_UInt i, count;
917
918
919 #if !defined FT_CONFIG_OPTION_OLD_INTERNALS
920 count = face->sbit_num_strikes;
921 #else
922 count = (FT_UInt)face->num_sbit_strikes;
923 #endif
924
925 if ( count > 0 )
926 {
927 FT_Memory memory = face->root.stream->memory;
928 FT_UShort em_size = face->header.Units_Per_EM;
929 FT_Short avgwidth = face->os2.xAvgCharWidth;
930 FT_Size_Metrics metrics;
931
932
933 if ( em_size == 0 || face->os2.version == 0xFFFFU )
934 {
935 avgwidth = 0;
936 em_size = 1;
937 }
938
939 if ( FT_NEW_ARRAY( root->available_sizes, count ) )
940 goto Exit;
941
942 for ( i = 0; i < count; i++ )
943 {
944 FT_Bitmap_Size* bsize = root->available_sizes + i;
945
946
947 error = sfnt->load_strike_metrics( face, i, &metrics );
948 if ( error )
949 goto Exit;
950
951 bsize->height = (FT_Short)( metrics.height >> 6 );
952 bsize->width = (FT_Short)(
953 ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
954
955 bsize->x_ppem = metrics.x_ppem << 6;
956 bsize->y_ppem = metrics.y_ppem << 6;
957
958 /* assume 72dpi */
959 bsize->size = metrics.y_ppem << 6;
960 }
961
962 root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
963 root->num_fixed_sizes = (FT_Int)count;
964 }
965 }
966
967 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
968
969 }
970
971 Exit:
972 FT_TRACE2(( "sfnt_load_face: done\n" ));
973
974 return error;
975 }
976
977
978 #undef LOAD_
979 #undef LOADM_
980
981
982 FT_LOCAL_DEF( void )
983 sfnt_done_face( TT_Face face )
984 {
985 FT_Memory memory = face->root.memory;
986 SFNT_Service sfnt = (SFNT_Service)face->sfnt;
987
988
989 if ( sfnt )
990 {
991 /* destroy the postscript names table if it is loaded */
992 if ( sfnt->free_psnames )
993 sfnt->free_psnames( face );
994
995 /* destroy the embedded bitmaps table if it is loaded */
996 if ( sfnt->free_eblc )
997 sfnt->free_eblc( face );
998 }
999
1000 #ifdef TT_CONFIG_OPTION_BDF
1001 /* freeing the embedded BDF properties */
1002 tt_face_free_bdf_props( face );
1003 #endif
1004
1005 /* freeing the kerning table */
1006 tt_face_done_kern( face );
1007
1008 /* freeing the collection table */
1009 FT_FREE( face->ttc_header.offsets );
1010 face->ttc_header.count = 0;
1011
1012 /* freeing table directory */
1013 FT_FREE( face->dir_tables );
1014 face->num_tables = 0;
1015
1016 {
1017 FT_Stream stream = FT_FACE_STREAM( face );
1018
1019
1020 /* simply release the 'cmap' table frame */
1021 FT_FRAME_RELEASE( face->cmap_table );
1022 face->cmap_size = 0;
1023 }
1024
1025 /* freeing the horizontal metrics */
1026 #if !defined FT_CONFIG_OPTION_OLD_INTERNALS
1027 {
1028 FT_Stream stream = FT_FACE_STREAM( face );
1029
1030
1031 FT_FRAME_RELEASE( face->horz_metrics );
1032 FT_FRAME_RELEASE( face->vert_metrics );
1033 face->horz_metrics_size = 0;
1034 face->vert_metrics_size = 0;
1035 }
1036 #else
1037 FT_FREE( face->horizontal.long_metrics );
1038 FT_FREE( face->horizontal.short_metrics );
1039 #endif
1040
1041 /* freeing the vertical ones, if any */
1042 if ( face->vertical_info )
1043 {
1044 FT_FREE( face->vertical.long_metrics );
1045 FT_FREE( face->vertical.short_metrics );
1046 face->vertical_info = 0;
1047 }
1048
1049 /* freeing the gasp table */
1050 FT_FREE( face->gasp.gaspRanges );
1051 face->gasp.numRanges = 0;
1052
1053 /* freeing the name table */
1054 sfnt->free_name( face );
1055
1056 /* freeing family and style name */
1057 FT_FREE( face->root.family_name );
1058 FT_FREE( face->root.style_name );
1059
1060 /* freeing sbit size table */
1061 FT_FREE( face->root.available_sizes );
1062 face->root.num_fixed_sizes = 0;
1063
1064 FT_FREE( face->postscript_name );
1065
1066 face->sfnt = 0;
1067 }
1068
1069
1070 /* END */