Merge 25584, 25588.
[reactos.git] / reactos / dll / 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 error = SFNT_Err_Horiz_Header_Missing;
623 }
624
625 if ( error )
626 goto Exit;
627
628 /* try to load the `vhea' and `vmtx' tables */
629 LOADM_( hhea, 1 );
630 if ( !error )
631 {
632 LOADM_( hmtx, 1 );
633 if ( !error )
634 face->vertical_info = 1;
635 }
636
637 if ( error && error != SFNT_Err_Table_Missing )
638 goto Exit;
639
640 LOAD_( os2 );
641 if ( error )
642 {
643 if ( error != SFNT_Err_Table_Missing )
644 goto Exit;
645
646 face->os2.version = 0xFFFFU;
647 }
648
649 }
650
651 /* the optional tables */
652
653 /* embedded bitmap support. */
654 if ( sfnt->load_eblc )
655 {
656 LOAD_( eblc );
657 if ( error )
658 {
659 /* return an error if this font file has no outlines */
660 if ( error == SFNT_Err_Table_Missing && has_outline )
661 error = SFNT_Err_Ok;
662 else
663 goto Exit;
664 }
665 }
666
667 LOAD_( pclt );
668 if ( error )
669 {
670 if ( error != SFNT_Err_Table_Missing )
671 goto Exit;
672
673 face->pclt.Version = 0;
674 }
675
676 /* consider the kerning and gasp tables as optional */
677 LOAD_( gasp );
678 LOAD_( kern );
679
680 error = SFNT_Err_Ok;
681
682 face->root.num_glyphs = face->max_profile.numGlyphs;
683
684 face->root.family_name = tt_face_get_name( face,
685 TT_NAME_ID_PREFERRED_FAMILY );
686 if ( !face->root.family_name )
687 face->root.family_name = tt_face_get_name( face,
688 TT_NAME_ID_FONT_FAMILY );
689
690 face->root.style_name = tt_face_get_name( face,
691 TT_NAME_ID_PREFERRED_SUBFAMILY );
692 if ( !face->root.style_name )
693 face->root.style_name = tt_face_get_name( face,
694 TT_NAME_ID_FONT_SUBFAMILY );
695
696 /* now set up root fields */
697 {
698 FT_Face root = &face->root;
699 FT_Int32 flags = root->face_flags;
700
701
702 /*********************************************************************/
703 /* */
704 /* Compute face flags. */
705 /* */
706 if ( has_outline == TRUE )
707 flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */
708
709 /* The sfnt driver only supports bitmap fonts natively, thus we */
710 /* don't set FT_FACE_FLAG_HINTER. */
711 flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */
712 FT_FACE_FLAG_HORIZONTAL; /* horizontal data */
713
714 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
715 if ( psnames_error == SFNT_Err_Ok &&
716 face->postscript.FormatType != 0x00030000L )
717 flags |= FT_FACE_FLAG_GLYPH_NAMES;
718 #endif
719
720 /* fixed width font? */
721 if ( face->postscript.isFixedPitch )
722 flags |= FT_FACE_FLAG_FIXED_WIDTH;
723
724 /* vertical information? */
725 if ( face->vertical_info )
726 flags |= FT_FACE_FLAG_VERTICAL;
727
728 /* kerning available ? */
729 if ( TT_FACE_HAS_KERNING( face ) )
730 flags |= FT_FACE_FLAG_KERNING;
731
732 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
733 /* Don't bother to load the tables unless somebody asks for them. */
734 /* No need to do work which will (probably) not be used. */
735 if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 &&
736 tt_face_lookup_table( face, TTAG_fvar ) != 0 &&
737 tt_face_lookup_table( face, TTAG_gvar ) != 0 )
738 flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
739 #endif
740
741 root->face_flags = flags;
742
743 /*********************************************************************/
744 /* */
745 /* Compute style flags. */
746 /* */
747 flags = 0;
748 if ( has_outline == TRUE && face->os2.version != 0xFFFFU )
749 {
750 /* we have an OS/2 table; use the `fsSelection' field */
751 if ( face->os2.fsSelection & 1 )
752 flags |= FT_STYLE_FLAG_ITALIC;
753
754 if ( face->os2.fsSelection & 32 )
755 flags |= FT_STYLE_FLAG_BOLD;
756 }
757 else
758 {
759 /* this is an old Mac font, use the header field */
760 if ( face->header.Mac_Style & 1 )
761 flags |= FT_STYLE_FLAG_BOLD;
762
763 if ( face->header.Mac_Style & 2 )
764 flags |= FT_STYLE_FLAG_ITALIC;
765 }
766
767 root->style_flags = flags;
768
769 /*********************************************************************/
770 /* */
771 /* Polish the charmaps. */
772 /* */
773 /* Try to set the charmap encoding according to the platform & */
774 /* encoding ID of each charmap. */
775 /* */
776
777 tt_face_build_cmaps( face ); /* ignore errors */
778
779
780 /* set the encoding fields */
781 {
782 FT_Int m;
783
784
785 for ( m = 0; m < root->num_charmaps; m++ )
786 {
787 FT_CharMap charmap = root->charmaps[m];
788
789
790 charmap->encoding = sfnt_find_encoding( charmap->platform_id,
791 charmap->encoding_id );
792
793 #if 0
794 if ( root->charmap == NULL &&
795 charmap->encoding == FT_ENCODING_UNICODE )
796 {
797 /* set 'root->charmap' to the first Unicode encoding we find */
798 root->charmap = charmap;
799 }
800 #endif
801 }
802 }
803
804
805 /*********************************************************************/
806 /* */
807 /* Set up metrics. */
808 /* */
809 if ( has_outline == TRUE )
810 {
811 /* XXX What about if outline header is missing */
812 /* (e.g. sfnt wrapped bitmap)? */
813 root->bbox.xMin = face->header.xMin;
814 root->bbox.yMin = face->header.yMin;
815 root->bbox.xMax = face->header.xMax;
816 root->bbox.yMax = face->header.yMax;
817 root->units_per_EM = face->header.Units_Per_EM;
818
819
820 /* XXX: Computing the ascender/descender/height is very different */
821 /* from what the specification tells you. Apparently, we */
822 /* must be careful because */
823 /* */
824 /* - not all fonts have an OS/2 table; in this case, we take */
825 /* the values in the horizontal header. However, these */
826 /* values very often are not reliable. */
827 /* */
828 /* - otherwise, the correct typographic values are in the */
829 /* sTypoAscender, sTypoDescender & sTypoLineGap fields. */
830 /* */
831 /* However, certains fonts have these fields set to 0. */
832 /* Rather, they have usWinAscent & usWinDescent correctly */
833 /* set (but with different values). */
834 /* */
835 /* As an example, Arial Narrow is implemented through four */
836 /* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
837 /* */
838 /* Strangely, all fonts have the same values in their */
839 /* sTypoXXX fields, except ARIALNB which sets them to 0. */
840 /* */
841 /* On the other hand, they all have different */
842 /* usWinAscent/Descent values -- as a conclusion, the OS/2 */
843 /* table cannot be used to compute the text height reliably! */
844 /* */
845
846 /* The ascender/descender/height are computed from the OS/2 table */
847 /* when found. Otherwise, they're taken from the horizontal */
848 /* header. */
849 /* */
850
851 root->ascender = face->horizontal.Ascender;
852 root->descender = face->horizontal.Descender;
853
854 root->height = (FT_Short)( root->ascender - root->descender +
855 face->horizontal.Line_Gap );
856
857 #if 0
858 /* if the line_gap is 0, we add an extra 15% to the text height -- */
859 /* this computation is based on various versions of Times New Roman */
860 if ( face->horizontal.Line_Gap == 0 )
861 root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 );
862 #endif
863
864 #if 0
865
866 /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
867 /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF */
868 if ( face->os2.version != 0xFFFFU && root->ascender )
869 {
870 FT_Int height;
871
872
873 root->ascender = face->os2.sTypoAscender;
874 root->descender = -face->os2.sTypoDescender;
875
876 height = root->ascender + root->descender + face->os2.sTypoLineGap;
877 if ( height > root->height )
878 root->height = height;
879 }
880
881 #endif /* 0 */
882
883 root->max_advance_width = face->horizontal.advance_Width_Max;
884
885 root->max_advance_height = (FT_Short)( face->vertical_info
886 ? face->vertical.advance_Height_Max
887 : root->height );
888
889 root->underline_position = face->postscript.underlinePosition;
890 root->underline_thickness = face->postscript.underlineThickness;
891 }
892
893 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
894
895 /*
896 * Now allocate the root array of FT_Bitmap_Size records and
897 * populate them. Unfortunately, it isn't possible to indicate bit
898 * depths in the FT_Bitmap_Size record. This is a design error.
899 */
900 {
901 FT_UInt i, count;
902
903
904 #if !defined FT_CONFIG_OPTION_OLD_INTERNALS
905 count = face->sbit_num_strikes;
906 #else
907 count = (FT_UInt)face->num_sbit_strikes;
908 #endif
909
910 if ( count > 0 )
911 {
912 FT_Memory memory = face->root.stream->memory;
913 FT_UShort em_size = face->header.Units_Per_EM;
914 FT_Short avgwidth = face->os2.xAvgCharWidth;
915 FT_Size_Metrics metrics;
916
917
918 if ( em_size == 0 || face->os2.version == 0xFFFFU )
919 {
920 avgwidth = 0;
921 em_size = 1;
922 }
923
924 if ( FT_NEW_ARRAY( root->available_sizes, count ) )
925 goto Exit;
926
927 for ( i = 0; i < count; i++ )
928 {
929 FT_Bitmap_Size* bsize = root->available_sizes + i;
930
931
932 error = sfnt->load_strike_metrics( face, i, &metrics );
933 if ( error )
934 goto Exit;
935
936 bsize->height = (FT_Short)( metrics.height >> 6 );
937 bsize->width = (FT_Short)(
938 ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
939
940 bsize->x_ppem = metrics.x_ppem << 6;
941 bsize->y_ppem = metrics.y_ppem << 6;
942
943 /* assume 72dpi */
944 bsize->size = metrics.y_ppem << 6;
945 }
946
947 root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
948 root->num_fixed_sizes = (FT_Int)count;
949 }
950 }
951
952 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
953
954 }
955
956 Exit:
957 FT_TRACE2(( "sfnt_load_face: done\n" ));
958
959 return error;
960 }
961
962
963 #undef LOAD_
964 #undef LOADM_
965
966
967 FT_LOCAL_DEF( void )
968 sfnt_done_face( TT_Face face )
969 {
970 FT_Memory memory = face->root.memory;
971 SFNT_Service sfnt = (SFNT_Service)face->sfnt;
972
973
974 if ( sfnt )
975 {
976 /* destroy the postscript names table if it is loaded */
977 if ( sfnt->free_psnames )
978 sfnt->free_psnames( face );
979
980 /* destroy the embedded bitmaps table if it is loaded */
981 if ( sfnt->free_eblc )
982 sfnt->free_eblc( face );
983 }
984
985 #ifdef TT_CONFIG_OPTION_BDF
986 /* freeing the embedded BDF properties */
987 tt_face_free_bdf_props( face );
988 #endif
989
990 /* freeing the kerning table */
991 tt_face_done_kern( face );
992
993 /* freeing the collection table */
994 FT_FREE( face->ttc_header.offsets );
995 face->ttc_header.count = 0;
996
997 /* freeing table directory */
998 FT_FREE( face->dir_tables );
999 face->num_tables = 0;
1000
1001 {
1002 FT_Stream stream = FT_FACE_STREAM( face );
1003
1004
1005 /* simply release the 'cmap' table frame */
1006 FT_FRAME_RELEASE( face->cmap_table );
1007 face->cmap_size = 0;
1008 }
1009
1010 /* freeing the horizontal metrics */
1011 #if !defined FT_CONFIG_OPTION_OLD_INTERNALS
1012 {
1013 FT_Stream stream = FT_FACE_STREAM( face );
1014
1015
1016 FT_FRAME_RELEASE( face->horz_metrics );
1017 FT_FRAME_RELEASE( face->vert_metrics );
1018 face->horz_metrics_size = 0;
1019 face->vert_metrics_size = 0;
1020 }
1021 #else
1022 FT_FREE( face->horizontal.long_metrics );
1023 FT_FREE( face->horizontal.short_metrics );
1024 #endif
1025
1026 /* freeing the vertical ones, if any */
1027 if ( face->vertical_info )
1028 {
1029 FT_FREE( face->vertical.long_metrics );
1030 FT_FREE( face->vertical.short_metrics );
1031 face->vertical_info = 0;
1032 }
1033
1034 /* freeing the gasp table */
1035 FT_FREE( face->gasp.gaspRanges );
1036 face->gasp.numRanges = 0;
1037
1038 /* freeing the name table */
1039 sfnt->free_name( face );
1040
1041 /* freeing family and style name */
1042 FT_FREE( face->root.family_name );
1043 FT_FREE( face->root.style_name );
1044
1045 /* freeing sbit size table */
1046 FT_FREE( face->root.available_sizes );
1047 face->root.num_fixed_sizes = 0;
1048
1049 FT_FREE( face->postscript_name );
1050
1051 face->sfnt = 0;
1052 }
1053
1054
1055 /* END */