Imported Upstream version 2.6.5
[platform/upstream/freetype2.git] / src / sfnt / sfobjs.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  sfobjs.c                                                               */
4 /*                                                                         */
5 /*    SFNT object management (base).                                       */
6 /*                                                                         */
7 /*  Copyright 1996-2016 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 FT_SFNT_NAMES_H
30 #include FT_GZIP_H
31 #include "sferrors.h"
32
33 #ifdef TT_CONFIG_OPTION_BDF
34 #include "ttbdf.h"
35 #endif
36
37
38   /*************************************************************************/
39   /*                                                                       */
40   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
41   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
42   /* messages during execution.                                            */
43   /*                                                                       */
44 #undef  FT_COMPONENT
45 #define FT_COMPONENT  trace_sfobjs
46
47
48
49   /* convert a UTF-16 name entry to ASCII */
50   static FT_String*
51   tt_name_entry_ascii_from_utf16( TT_NameEntry  entry,
52                                   FT_Memory     memory )
53   {
54     FT_String*  string = NULL;
55     FT_UInt     len, code, n;
56     FT_Byte*    read   = (FT_Byte*)entry->string;
57     FT_Error    error;
58
59
60     len = (FT_UInt)entry->stringLength / 2;
61
62     if ( FT_NEW_ARRAY( string, len + 1 ) )
63       return NULL;
64
65     for ( n = 0; n < len; n++ )
66     {
67       code = FT_NEXT_USHORT( read );
68
69       if ( code == 0 )
70         break;
71
72       if ( code < 32 || code > 127 )
73         code = '?';
74
75       string[n] = (char)code;
76     }
77
78     string[n] = 0;
79
80     return string;
81   }
82
83
84   /* convert an Apple Roman or symbol name entry to ASCII */
85   static FT_String*
86   tt_name_entry_ascii_from_other( TT_NameEntry  entry,
87                                   FT_Memory     memory )
88   {
89     FT_String*  string = NULL;
90     FT_UInt     len, code, n;
91     FT_Byte*    read   = (FT_Byte*)entry->string;
92     FT_Error    error;
93
94
95     len = (FT_UInt)entry->stringLength;
96
97     if ( FT_NEW_ARRAY( string, len + 1 ) )
98       return NULL;
99
100     for ( n = 0; n < len; n++ )
101     {
102       code = *read++;
103
104       if ( code == 0 )
105         break;
106
107       if ( code < 32 || code > 127 )
108         code = '?';
109
110       string[n] = (char)code;
111     }
112
113     string[n] = 0;
114
115     return string;
116   }
117
118
119   typedef FT_String*  (*TT_NameEntry_ConvertFunc)( TT_NameEntry  entry,
120                                                    FT_Memory     memory );
121
122
123   /* documentation is in sfnt.h */
124
125   FT_LOCAL_DEF( FT_Error )
126   tt_face_get_name( TT_Face      face,
127                     FT_UShort    nameid,
128                     FT_String**  name )
129   {
130     FT_Memory         memory = face->root.memory;
131     FT_Error          error  = FT_Err_Ok;
132     FT_String*        result = NULL;
133     FT_UShort         n;
134     TT_NameEntryRec*  rec;
135     FT_Int            found_apple         = -1;
136     FT_Int            found_apple_roman   = -1;
137     FT_Int            found_apple_english = -1;
138     FT_Int            found_win           = -1;
139     FT_Int            found_unicode       = -1;
140
141     FT_Bool           is_english = 0;
142
143     TT_NameEntry_ConvertFunc  convert;
144
145
146     FT_ASSERT( name );
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_Stream  stream = face->name_table.stream;
260
261
262         if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) ||
263              FT_STREAM_SEEK( rec->stringOffset )              ||
264              FT_STREAM_READ( rec->string, rec->stringLength ) )
265         {
266           FT_FREE( rec->string );
267           rec->stringLength = 0;
268           result            = NULL;
269           goto Exit;
270         }
271       }
272
273       result = convert( rec, memory );
274     }
275
276   Exit:
277     *name = result;
278     return error;
279   }
280
281
282   static FT_Encoding
283   sfnt_find_encoding( int  platform_id,
284                       int  encoding_id )
285   {
286     typedef struct  TEncoding_
287     {
288       int          platform_id;
289       int          encoding_id;
290       FT_Encoding  encoding;
291
292     } TEncoding;
293
294     static
295     const TEncoding  tt_encodings[] =
296     {
297       { TT_PLATFORM_ISO,           -1,                  FT_ENCODING_UNICODE },
298
299       { TT_PLATFORM_APPLE_UNICODE, -1,                  FT_ENCODING_UNICODE },
300
301       { TT_PLATFORM_MACINTOSH,     TT_MAC_ID_ROMAN,     FT_ENCODING_APPLE_ROMAN },
302
303       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SYMBOL_CS,  FT_ENCODING_MS_SYMBOL },
304       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UCS_4,      FT_ENCODING_UNICODE },
305       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE },
306       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SJIS,       FT_ENCODING_SJIS },
307       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_GB2312,     FT_ENCODING_GB2312 },
308       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_BIG_5,      FT_ENCODING_BIG5 },
309       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_WANSUNG,    FT_ENCODING_WANSUNG },
310       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_JOHAB,      FT_ENCODING_JOHAB }
311     };
312
313     const TEncoding  *cur, *limit;
314
315
316     cur   = tt_encodings;
317     limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );
318
319     for ( ; cur < limit; cur++ )
320     {
321       if ( cur->platform_id == platform_id )
322       {
323         if ( cur->encoding_id == encoding_id ||
324              cur->encoding_id == -1          )
325           return cur->encoding;
326       }
327     }
328
329     return FT_ENCODING_NONE;
330   }
331
332
333 #define WRITE_USHORT( p, v )                \
334           do                                \
335           {                                 \
336             *(p)++ = (FT_Byte)( (v) >> 8 ); \
337             *(p)++ = (FT_Byte)( (v) >> 0 ); \
338                                             \
339           } while ( 0 )
340
341 #define WRITE_ULONG( p, v )                  \
342           do                                 \
343           {                                  \
344             *(p)++ = (FT_Byte)( (v) >> 24 ); \
345             *(p)++ = (FT_Byte)( (v) >> 16 ); \
346             *(p)++ = (FT_Byte)( (v) >>  8 ); \
347             *(p)++ = (FT_Byte)( (v) >>  0 ); \
348                                              \
349           } while ( 0 )
350
351
352   static void
353   sfnt_stream_close( FT_Stream  stream )
354   {
355     FT_Memory  memory = stream->memory;
356
357
358     FT_FREE( stream->base );
359
360     stream->size  = 0;
361     stream->base  = NULL;
362     stream->close = NULL;
363   }
364
365
366   FT_CALLBACK_DEF( int )
367   compare_offsets( const void*  a,
368                    const void*  b )
369   {
370     WOFF_Table  table1 = *(WOFF_Table*)a;
371     WOFF_Table  table2 = *(WOFF_Table*)b;
372
373     FT_ULong  offset1 = table1->Offset;
374     FT_ULong  offset2 = table2->Offset;
375
376
377     if ( offset1 > offset2 )
378       return 1;
379     else if ( offset1 < offset2 )
380       return -1;
381     else
382       return 0;
383   }
384
385
386   /* Replace `face->root.stream' with a stream containing the extracted */
387   /* SFNT of a WOFF font.                                               */
388
389   static FT_Error
390   woff_open_font( FT_Stream  stream,
391                   TT_Face    face )
392   {
393     FT_Memory       memory = stream->memory;
394     FT_Error        error  = FT_Err_Ok;
395
396     WOFF_HeaderRec  woff;
397     WOFF_Table      tables  = NULL;
398     WOFF_Table*     indices = NULL;
399
400     FT_ULong        woff_offset;
401
402     FT_Byte*        sfnt        = NULL;
403     FT_Stream       sfnt_stream = NULL;
404
405     FT_Byte*        sfnt_header;
406     FT_ULong        sfnt_offset;
407
408     FT_Int          nn;
409     FT_ULong        old_tag = 0;
410
411     static const FT_Frame_Field  woff_header_fields[] =
412     {
413 #undef  FT_STRUCTURE
414 #define FT_STRUCTURE  WOFF_HeaderRec
415
416       FT_FRAME_START( 44 ),
417         FT_FRAME_ULONG ( signature ),
418         FT_FRAME_ULONG ( flavor ),
419         FT_FRAME_ULONG ( length ),
420         FT_FRAME_USHORT( num_tables ),
421         FT_FRAME_USHORT( reserved ),
422         FT_FRAME_ULONG ( totalSfntSize ),
423         FT_FRAME_USHORT( majorVersion ),
424         FT_FRAME_USHORT( minorVersion ),
425         FT_FRAME_ULONG ( metaOffset ),
426         FT_FRAME_ULONG ( metaLength ),
427         FT_FRAME_ULONG ( metaOrigLength ),
428         FT_FRAME_ULONG ( privOffset ),
429         FT_FRAME_ULONG ( privLength ),
430       FT_FRAME_END
431     };
432
433
434     FT_ASSERT( stream == face->root.stream );
435     FT_ASSERT( FT_STREAM_POS() == 0 );
436
437     if ( FT_STREAM_READ_FIELDS( woff_header_fields, &woff ) )
438       return error;
439
440     /* Make sure we don't recurse back here or hit TTC code. */
441     if ( woff.flavor == TTAG_wOFF || woff.flavor == TTAG_ttcf )
442       return FT_THROW( Invalid_Table );
443
444     /* Miscellaneous checks. */
445     if ( woff.length != stream->size                              ||
446          woff.num_tables == 0                                     ||
447          44 + woff.num_tables * 20UL >= woff.length               ||
448          12 + woff.num_tables * 16UL >= woff.totalSfntSize        ||
449          ( woff.totalSfntSize & 3 ) != 0                          ||
450          ( woff.metaOffset == 0 && ( woff.metaLength != 0     ||
451                                      woff.metaOrigLength != 0 ) ) ||
452          ( woff.metaLength != 0 && woff.metaOrigLength == 0 )     ||
453          ( woff.privOffset == 0 && woff.privLength != 0 )         )
454     {
455       FT_ERROR(( "woff_font_open: invalid WOFF header\n" ));
456       return FT_THROW( Invalid_Table );
457     }
458
459     /* Don't trust `totalSfntSize' before thorough checks. */
460     if ( FT_ALLOC( sfnt, 12 + woff.num_tables * 16UL ) ||
461          FT_NEW( sfnt_stream )                         )
462       goto Exit;
463
464     sfnt_header = sfnt;
465
466     /* Write sfnt header. */
467     {
468       FT_UInt  searchRange, entrySelector, rangeShift, x;
469
470
471       x             = woff.num_tables;
472       entrySelector = 0;
473       while ( x )
474       {
475         x            >>= 1;
476         entrySelector += 1;
477       }
478       entrySelector--;
479
480       searchRange = ( 1 << entrySelector ) * 16;
481       rangeShift  = woff.num_tables * 16 - searchRange;
482
483       WRITE_ULONG ( sfnt_header, woff.flavor );
484       WRITE_USHORT( sfnt_header, woff.num_tables );
485       WRITE_USHORT( sfnt_header, searchRange );
486       WRITE_USHORT( sfnt_header, entrySelector );
487       WRITE_USHORT( sfnt_header, rangeShift );
488     }
489
490     /* While the entries in the sfnt header must be sorted by the */
491     /* tag value, the tables themselves are not.  We thus have to */
492     /* sort them by offset and check that they don't overlap.     */
493
494     if ( FT_NEW_ARRAY( tables, woff.num_tables )  ||
495          FT_NEW_ARRAY( indices, woff.num_tables ) )
496       goto Exit;
497
498     FT_TRACE2(( "\n"
499                 "  tag    offset    compLen  origLen  checksum\n"
500                 "  -------------------------------------------\n" ));
501
502     if ( FT_FRAME_ENTER( 20L * woff.num_tables ) )
503       goto Exit;
504
505     for ( nn = 0; nn < woff.num_tables; nn++ )
506     {
507       WOFF_Table  table = tables + nn;
508
509       table->Tag        = FT_GET_TAG4();
510       table->Offset     = FT_GET_ULONG();
511       table->CompLength = FT_GET_ULONG();
512       table->OrigLength = FT_GET_ULONG();
513       table->CheckSum   = FT_GET_ULONG();
514
515       FT_TRACE2(( "  %c%c%c%c  %08lx  %08lx  %08lx  %08lx\n",
516                   (FT_Char)( table->Tag >> 24 ),
517                   (FT_Char)( table->Tag >> 16 ),
518                   (FT_Char)( table->Tag >> 8  ),
519                   (FT_Char)( table->Tag       ),
520                   table->Offset,
521                   table->CompLength,
522                   table->OrigLength,
523                   table->CheckSum ));
524
525       if ( table->Tag <= old_tag )
526       {
527         FT_FRAME_EXIT();
528
529         FT_ERROR(( "woff_font_open: table tags are not sorted\n" ));
530         error = FT_THROW( Invalid_Table );
531         goto Exit;
532       }
533
534       old_tag     = table->Tag;
535       indices[nn] = table;
536     }
537
538     FT_FRAME_EXIT();
539
540     /* Sort by offset. */
541
542     ft_qsort( indices,
543               woff.num_tables,
544               sizeof ( WOFF_Table ),
545               compare_offsets );
546
547     /* Check offsets and lengths. */
548
549     woff_offset = 44 + woff.num_tables * 20L;
550     sfnt_offset = 12 + woff.num_tables * 16L;
551
552     for ( nn = 0; nn < woff.num_tables; nn++ )
553     {
554       WOFF_Table  table = indices[nn];
555
556
557       if ( table->Offset != woff_offset                         ||
558            table->CompLength > woff.length                      ||
559            table->Offset > woff.length - table->CompLength      ||
560            table->OrigLength > woff.totalSfntSize               ||
561            sfnt_offset > woff.totalSfntSize - table->OrigLength ||
562            table->CompLength > table->OrigLength                )
563       {
564         FT_ERROR(( "woff_font_open: invalid table offsets\n" ));
565         error = FT_THROW( Invalid_Table );
566         goto Exit;
567       }
568
569       table->OrigOffset = sfnt_offset;
570
571       /* The offsets must be multiples of 4. */
572       woff_offset += ( table->CompLength + 3 ) & ~3U;
573       sfnt_offset += ( table->OrigLength + 3 ) & ~3U;
574     }
575
576     /*
577      * Final checks!
578      *
579      * We don't decode and check the metadata block.
580      * We don't check table checksums either.
581      * But other than those, I think we implement all
582      * `MUST' checks from the spec.
583      */
584
585     if ( woff.metaOffset )
586     {
587       if ( woff.metaOffset != woff_offset                  ||
588            woff.metaOffset + woff.metaLength > woff.length )
589       {
590         FT_ERROR(( "woff_font_open:"
591                    " invalid `metadata' offset or length\n" ));
592         error = FT_THROW( Invalid_Table );
593         goto Exit;
594       }
595
596       /* We have padding only ... */
597       woff_offset += woff.metaLength;
598     }
599
600     if ( woff.privOffset )
601     {
602       /* ... if it isn't the last block. */
603       woff_offset = ( woff_offset + 3 ) & ~3U;
604
605       if ( woff.privOffset != woff_offset                  ||
606            woff.privOffset + woff.privLength > woff.length )
607       {
608         FT_ERROR(( "woff_font_open: invalid `private' offset or length\n" ));
609         error = FT_THROW( Invalid_Table );
610         goto Exit;
611       }
612
613       /* No padding for the last block. */
614       woff_offset += woff.privLength;
615     }
616
617     if ( sfnt_offset != woff.totalSfntSize ||
618          woff_offset != woff.length        )
619     {
620       FT_ERROR(( "woff_font_open: invalid `sfnt' table structure\n" ));
621       error = FT_THROW( Invalid_Table );
622       goto Exit;
623     }
624
625     /* Now use `totalSfntSize'. */
626     if ( FT_REALLOC( sfnt,
627                      12 + woff.num_tables * 16UL,
628                      woff.totalSfntSize ) )
629       goto Exit;
630
631     sfnt_header = sfnt + 12;
632
633     /* Write the tables. */
634
635     for ( nn = 0; nn < woff.num_tables; nn++ )
636     {
637       WOFF_Table  table = tables + nn;
638
639
640       /* Write SFNT table entry. */
641       WRITE_ULONG( sfnt_header, table->Tag );
642       WRITE_ULONG( sfnt_header, table->CheckSum );
643       WRITE_ULONG( sfnt_header, table->OrigOffset );
644       WRITE_ULONG( sfnt_header, table->OrigLength );
645
646       /* Write table data. */
647       if ( FT_STREAM_SEEK( table->Offset )     ||
648            FT_FRAME_ENTER( table->CompLength ) )
649         goto Exit;
650
651       if ( table->CompLength == table->OrigLength )
652       {
653         /* Uncompressed data; just copy. */
654         ft_memcpy( sfnt + table->OrigOffset,
655                    stream->cursor,
656                    table->OrigLength );
657       }
658       else
659       {
660 #ifdef FT_CONFIG_OPTION_USE_ZLIB
661
662         /* Uncompress with zlib. */
663         FT_ULong  output_len = table->OrigLength;
664
665
666         error = FT_Gzip_Uncompress( memory,
667                                     sfnt + table->OrigOffset, &output_len,
668                                     stream->cursor, table->CompLength );
669         if ( error )
670           goto Exit;
671         if ( output_len != table->OrigLength )
672         {
673           FT_ERROR(( "woff_font_open: compressed table length mismatch\n" ));
674           error = FT_THROW( Invalid_Table );
675           goto Exit;
676         }
677
678 #else /* !FT_CONFIG_OPTION_USE_ZLIB */
679
680         error = FT_THROW( Unimplemented_Feature );
681         goto Exit;
682
683 #endif /* !FT_CONFIG_OPTION_USE_ZLIB */
684       }
685
686       FT_FRAME_EXIT();
687
688       /* We don't check whether the padding bytes in the WOFF file are     */
689       /* actually '\0'.  For the output, however, we do set them properly. */
690       sfnt_offset = table->OrigOffset + table->OrigLength;
691       while ( sfnt_offset & 3 )
692       {
693         sfnt[sfnt_offset] = '\0';
694         sfnt_offset++;
695       }
696     }
697
698     /* Ok!  Finally ready.  Swap out stream and return. */
699     FT_Stream_OpenMemory( sfnt_stream, sfnt, woff.totalSfntSize );
700     sfnt_stream->memory = stream->memory;
701     sfnt_stream->close  = sfnt_stream_close;
702
703     FT_Stream_Free(
704       face->root.stream,
705       ( face->root.face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
706
707     face->root.stream = sfnt_stream;
708
709     face->root.face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
710
711   Exit:
712     FT_FREE( tables );
713     FT_FREE( indices );
714
715     if ( error )
716     {
717       FT_FREE( sfnt );
718       FT_Stream_Close( sfnt_stream );
719       FT_FREE( sfnt_stream );
720     }
721
722     return error;
723   }
724
725
726 #undef WRITE_USHORT
727 #undef WRITE_ULONG
728
729
730   /* Fill in face->ttc_header.  If the font is not a TTC, it is */
731   /* synthesized into a TTC with one offset table.              */
732   static FT_Error
733   sfnt_open_font( FT_Stream  stream,
734                   TT_Face    face )
735   {
736     FT_Memory  memory = stream->memory;
737     FT_Error   error;
738     FT_ULong   tag, offset;
739
740     static const FT_Frame_Field  ttc_header_fields[] =
741     {
742 #undef  FT_STRUCTURE
743 #define FT_STRUCTURE  TTC_HeaderRec
744
745       FT_FRAME_START( 8 ),
746         FT_FRAME_LONG( version ),
747         FT_FRAME_LONG( count   ),  /* this is ULong in the specs */
748       FT_FRAME_END
749     };
750
751
752     face->ttc_header.tag     = 0;
753     face->ttc_header.version = 0;
754     face->ttc_header.count   = 0;
755
756   retry:
757     offset = FT_STREAM_POS();
758
759     if ( FT_READ_ULONG( tag ) )
760       return error;
761
762     if ( tag == TTAG_wOFF )
763     {
764       FT_TRACE2(( "sfnt_open_font: file is a WOFF; synthesizing SFNT\n" ));
765
766       if ( FT_STREAM_SEEK( offset ) )
767         return error;
768
769       error = woff_open_font( stream, face );
770       if ( error )
771         return error;
772
773       /* Swap out stream and retry! */
774       stream = face->root.stream;
775       goto retry;
776     }
777
778     if ( tag != 0x00010000UL &&
779          tag != TTAG_ttcf    &&
780          tag != TTAG_OTTO    &&
781          tag != TTAG_true    &&
782          tag != TTAG_typ1    &&
783          tag != 0x00020000UL )
784     {
785       FT_TRACE2(( "  not a font using the SFNT container format\n" ));
786       return FT_THROW( Unknown_File_Format );
787     }
788
789     face->ttc_header.tag = TTAG_ttcf;
790
791     if ( tag == TTAG_ttcf )
792     {
793       FT_Int  n;
794
795
796       FT_TRACE3(( "sfnt_open_font: file is a collection\n" ));
797
798       if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )
799         return error;
800
801       if ( face->ttc_header.count == 0 )
802         return FT_THROW( Invalid_Table );
803
804       /* a rough size estimate: let's conservatively assume that there   */
805       /* is just a single table info in each subfont header (12 + 16*1 = */
806       /* 28 bytes), thus we have (at least) `12 + 4*count' bytes for the */
807       /* size of the TTC header plus `28*count' bytes for all subfont    */
808       /* headers                                                         */
809       if ( (FT_ULong)face->ttc_header.count > stream->size / ( 28 + 4 ) )
810         return FT_THROW( Array_Too_Large );
811
812       /* now read the offsets of each font in the file */
813       if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) )
814         return error;
815
816       if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) )
817         return error;
818
819       for ( n = 0; n < face->ttc_header.count; n++ )
820         face->ttc_header.offsets[n] = FT_GET_ULONG();
821
822       FT_FRAME_EXIT();
823     }
824     else
825     {
826       FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" ));
827
828       face->ttc_header.version = 1 << 16;
829       face->ttc_header.count   = 1;
830
831       if ( FT_NEW( face->ttc_header.offsets ) )
832         return error;
833
834       face->ttc_header.offsets[0] = offset;
835     }
836
837     return error;
838   }
839
840
841   FT_LOCAL_DEF( FT_Error )
842   sfnt_init_face( FT_Stream      stream,
843                   TT_Face        face,
844                   FT_Int         face_instance_index,
845                   FT_Int         num_params,
846                   FT_Parameter*  params )
847   {
848     FT_Error      error;
849     FT_Library    library = face->root.driver->root.library;
850     SFNT_Service  sfnt;
851     FT_Int        face_index;
852
853
854     /* for now, parameters are unused */
855     FT_UNUSED( num_params );
856     FT_UNUSED( params );
857
858
859     sfnt = (SFNT_Service)face->sfnt;
860     if ( !sfnt )
861     {
862       sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
863       if ( !sfnt )
864       {
865         FT_ERROR(( "sfnt_init_face: cannot access `sfnt' module\n" ));
866         return FT_THROW( Missing_Module );
867       }
868
869       face->sfnt       = sfnt;
870       face->goto_table = sfnt->goto_table;
871     }
872
873     FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS );
874
875     FT_TRACE2(( "SFNT driver\n" ));
876
877     error = sfnt_open_font( stream, face );
878     if ( error )
879       return error;
880
881     /* Stream may have changed in sfnt_open_font. */
882     stream = face->root.stream;
883
884     FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_instance_index ));
885
886     face_index = FT_ABS( face_instance_index ) & 0xFFFF;
887
888     if ( face_index >= face->ttc_header.count )
889     {
890       if ( face_instance_index >= 0 )
891         return FT_THROW( Invalid_Argument );
892       else
893         face_index = 0;
894     }
895
896     if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) )
897       return error;
898
899     /* check whether we have a valid TrueType file */
900     error = sfnt->load_font_dir( face, stream );
901     if ( error )
902       return error;
903
904 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
905     {
906       FT_ULong  fvar_len;
907
908       FT_ULong  version;
909       FT_ULong  offset;
910
911       FT_UShort  num_axes;
912       FT_UShort  axis_size;
913       FT_UShort  num_instances;
914       FT_UShort  instance_size;
915
916       FT_Int  instance_index;
917
918
919       instance_index = FT_ABS( face_instance_index ) >> 16;
920
921       /* test whether current face is a GX font with named instances */
922       if ( face->goto_table( face, TTAG_fvar, stream, &fvar_len ) ||
923            fvar_len < 20                                          ||
924            FT_READ_ULONG( version )                               ||
925            FT_READ_USHORT( offset )                               ||
926            FT_STREAM_SKIP( 2 )                                    ||
927            FT_READ_USHORT( num_axes )                             ||
928            FT_READ_USHORT( axis_size )                            ||
929            FT_READ_USHORT( num_instances )                        ||
930            FT_READ_USHORT( instance_size )                        )
931       {
932         version       = 0;
933         offset        = 0;
934         num_axes      = 0;
935         axis_size     = 0;
936         num_instances = 0;
937         instance_size = 0;
938       }
939
940       /* check that the data is bound by the table length; */
941       /* based on similar code in function `TT_Get_MM_Var' */
942       if ( version != 0x00010000UL                    ||
943            axis_size != 20                            ||
944            num_axes > 0x3FFE                          ||
945            instance_size != 4 + 4 * num_axes          ||
946            num_instances > 0x7EFF                     ||
947            offset                          +
948              axis_size * num_axes          +
949              instance_size * num_instances > fvar_len )
950         num_instances = 0;
951
952       /* we don't support Multiple Master CFFs yet */
953       if ( !face->goto_table( face, TTAG_CFF, stream, 0 ) )
954         num_instances = 0;
955
956       /* we support at most 2^15 - 1 instances */
957       if ( num_instances >= ( 1U << 15 ) - 1 )
958       {
959         if ( face_instance_index >= 0 )
960           return FT_THROW( Invalid_Argument );
961         else
962           num_instances = 0;
963       }
964
965       /* instance indices in `face_instance_index' start with index 1, */
966       /* thus `>' and not `>='                                         */
967       if ( instance_index > num_instances )
968       {
969         if ( face_instance_index >= 0 )
970           return FT_THROW( Invalid_Argument );
971         else
972           num_instances = 0;
973       }
974
975       face->root.style_flags = (FT_Long)num_instances << 16;
976     }
977 #endif
978
979     face->root.num_faces  = face->ttc_header.count;
980     face->root.face_index = face_index;
981
982     return error;
983   }
984
985
986 #define LOAD_( x )                                          \
987   do                                                        \
988   {                                                         \
989     FT_TRACE2(( "`" #x "' " ));                             \
990     FT_TRACE3(( "-->\n" ));                                 \
991                                                             \
992     error = sfnt->load_ ## x( face, stream );               \
993                                                             \
994     FT_TRACE2(( "%s\n", ( !error )                          \
995                         ? "loaded"                          \
996                         : FT_ERR_EQ( error, Table_Missing ) \
997                           ? "missing"                       \
998                           : "failed to load" ));            \
999     FT_TRACE3(( "\n" ));                                    \
1000   } while ( 0 )
1001
1002 #define LOADM_( x, vertical )                               \
1003   do                                                        \
1004   {                                                         \
1005     FT_TRACE2(( "`%s" #x "' ",                              \
1006                 vertical ? "vertical " : "" ));             \
1007     FT_TRACE3(( "-->\n" ));                                 \
1008                                                             \
1009     error = sfnt->load_ ## x( face, stream, vertical );     \
1010                                                             \
1011     FT_TRACE2(( "%s\n", ( !error )                          \
1012                         ? "loaded"                          \
1013                         : FT_ERR_EQ( error, Table_Missing ) \
1014                           ? "missing"                       \
1015                           : "failed to load" ));            \
1016     FT_TRACE3(( "\n" ));                                    \
1017   } while ( 0 )
1018
1019 #define GET_NAME( id, field )                                   \
1020   do                                                            \
1021   {                                                             \
1022     error = tt_face_get_name( face, TT_NAME_ID_ ## id, field ); \
1023     if ( error )                                                \
1024       goto Exit;                                                \
1025   } while ( 0 )
1026
1027
1028   FT_LOCAL_DEF( FT_Error )
1029   sfnt_load_face( FT_Stream      stream,
1030                   TT_Face        face,
1031                   FT_Int         face_instance_index,
1032                   FT_Int         num_params,
1033                   FT_Parameter*  params )
1034   {
1035     FT_Error      error;
1036 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
1037     FT_Error      psnames_error;
1038 #endif
1039     FT_Bool       has_outline;
1040     FT_Bool       is_apple_sbit;
1041     FT_Bool       is_apple_sbix;
1042     FT_Bool       ignore_preferred_family    = FALSE;
1043     FT_Bool       ignore_preferred_subfamily = FALSE;
1044
1045     SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
1046
1047     FT_UNUSED( face_instance_index );
1048
1049
1050     /* Check parameters */
1051
1052     {
1053       FT_Int  i;
1054
1055
1056       for ( i = 0; i < num_params; i++ )
1057       {
1058         if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY )
1059           ignore_preferred_family = TRUE;
1060         else if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY )
1061           ignore_preferred_subfamily = TRUE;
1062       }
1063     }
1064
1065     /* Load tables */
1066
1067     /* We now support two SFNT-based bitmapped font formats.  They */
1068     /* are recognized easily as they do not include a `glyf'       */
1069     /* table.                                                      */
1070     /*                                                             */
1071     /* The first format comes from Apple, and uses a table named   */
1072     /* `bhed' instead of `head' to store the font header (using    */
1073     /* the same format).  It also doesn't include horizontal and   */
1074     /* vertical metrics tables (i.e. `hhea' and `vhea' tables are  */
1075     /* missing).                                                   */
1076     /*                                                             */
1077     /* The other format comes from Microsoft, and is used with     */
1078     /* WinCE/PocketPC.  It looks like a standard TTF, except that  */
1079     /* it doesn't contain outlines.                                */
1080     /*                                                             */
1081
1082     FT_TRACE2(( "sfnt_load_face: %08p\n\n", face ));
1083
1084     /* do we have outlines in there? */
1085 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1086     has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 ||
1087                            tt_face_lookup_table( face, TTAG_glyf )    != 0 ||
1088                            tt_face_lookup_table( face, TTAG_CFF )     != 0 );
1089 #else
1090     has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
1091                            tt_face_lookup_table( face, TTAG_CFF )  != 0 );
1092 #endif
1093
1094     is_apple_sbit = 0;
1095     is_apple_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 );
1096
1097     /* Apple 'sbix' color bitmaps are rendered scaled and then the 'glyf'
1098      * outline rendered on top.  We don't support that yet, so just ignore
1099      * the 'glyf' outline and advertise it as a bitmap-only font. */
1100     if ( is_apple_sbix )
1101       has_outline = FALSE;
1102
1103     /* if this font doesn't contain outlines, we try to load */
1104     /* a `bhed' table                                        */
1105     if ( !has_outline && sfnt->load_bhed )
1106     {
1107       LOAD_( bhed );
1108       is_apple_sbit = FT_BOOL( !error );
1109     }
1110
1111     /* load the font header (`head' table) if this isn't an Apple */
1112     /* sbit font file                                             */
1113     if ( !is_apple_sbit || is_apple_sbix )
1114     {
1115       LOAD_( head );
1116       if ( error )
1117         goto Exit;
1118     }
1119
1120     if ( face->header.Units_Per_EM == 0 )
1121     {
1122       error = FT_THROW( Invalid_Table );
1123
1124       goto Exit;
1125     }
1126
1127     /* the following tables are often not present in embedded TrueType */
1128     /* fonts within PDF documents, so don't check for them.            */
1129     LOAD_( maxp );
1130     LOAD_( cmap );
1131
1132     /* the following tables are optional in PCL fonts -- */
1133     /* don't check for errors                            */
1134     LOAD_( name );
1135     LOAD_( post );
1136
1137 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
1138     psnames_error = error;
1139 #endif
1140
1141     /* do not load the metrics headers and tables if this is an Apple */
1142     /* sbit font file                                                 */
1143     if ( !is_apple_sbit )
1144     {
1145       /* load the `hhea' and `hmtx' tables */
1146       LOADM_( hhea, 0 );
1147       if ( !error )
1148       {
1149         LOADM_( hmtx, 0 );
1150         if ( FT_ERR_EQ( error, Table_Missing ) )
1151         {
1152           error = FT_THROW( Hmtx_Table_Missing );
1153
1154 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1155           /* If this is an incrementally loaded font and there are */
1156           /* overriding metrics, tolerate a missing `hmtx' table.  */
1157           if ( face->root.internal->incremental_interface          &&
1158                face->root.internal->incremental_interface->funcs->
1159                  get_glyph_metrics                                 )
1160           {
1161             face->horizontal.number_Of_HMetrics = 0;
1162             error                               = FT_Err_Ok;
1163           }
1164 #endif
1165         }
1166       }
1167       else if ( FT_ERR_EQ( error, Table_Missing ) )
1168       {
1169         /* No `hhea' table necessary for SFNT Mac fonts. */
1170         if ( face->format_tag == TTAG_true )
1171         {
1172           FT_TRACE2(( "This is an SFNT Mac font.\n" ));
1173
1174           has_outline = 0;
1175           error       = FT_Err_Ok;
1176         }
1177         else
1178         {
1179           error = FT_THROW( Horiz_Header_Missing );
1180
1181 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1182           /* If this is an incrementally loaded font and there are */
1183           /* overriding metrics, tolerate a missing `hhea' table.  */
1184           if ( face->root.internal->incremental_interface          &&
1185                face->root.internal->incremental_interface->funcs->
1186                  get_glyph_metrics                                 )
1187           {
1188             face->horizontal.number_Of_HMetrics = 0;
1189             error                               = FT_Err_Ok;
1190           }
1191 #endif
1192
1193         }
1194       }
1195
1196       if ( error )
1197         goto Exit;
1198
1199       /* try to load the `vhea' and `vmtx' tables */
1200       LOADM_( hhea, 1 );
1201       if ( !error )
1202       {
1203         LOADM_( hmtx, 1 );
1204         if ( !error )
1205           face->vertical_info = 1;
1206       }
1207
1208       if ( error && FT_ERR_NEQ( error, Table_Missing ) )
1209         goto Exit;
1210
1211       LOAD_( os2 );
1212       if ( error )
1213       {
1214         /* we treat the table as missing if there are any errors */
1215         face->os2.version = 0xFFFFU;
1216       }
1217     }
1218
1219     /* the optional tables */
1220
1221     /* embedded bitmap support */
1222     if ( sfnt->load_eblc )
1223     {
1224       LOAD_( eblc );
1225       if ( error )
1226       {
1227         /* a font which contains neither bitmaps nor outlines is */
1228         /* still valid (although rather useless in most cases);  */
1229         /* however, you can find such stripped fonts in PDFs     */
1230         if ( FT_ERR_EQ( error, Table_Missing ) )
1231           error = FT_Err_Ok;
1232         else
1233           goto Exit;
1234       }
1235     }
1236
1237     LOAD_( pclt );
1238     if ( error )
1239     {
1240       if ( FT_ERR_NEQ( error, Table_Missing ) )
1241         goto Exit;
1242
1243       face->pclt.Version = 0;
1244     }
1245
1246     /* consider the kerning and gasp tables as optional */
1247     LOAD_( gasp );
1248     LOAD_( kern );
1249
1250     face->root.num_glyphs = face->max_profile.numGlyphs;
1251
1252     /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes  */
1253     /* a WWS-only font face.  `WWS' stands for `weight', width', and */
1254     /* `slope', a term used by Microsoft's Windows Presentation      */
1255     /* Foundation (WPF).  This flag has been introduced in version   */
1256     /* 1.5 of the OpenType specification (May 2008).                 */
1257
1258     face->root.family_name = NULL;
1259     face->root.style_name  = NULL;
1260     if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 )
1261     {
1262       if ( !ignore_preferred_family )
1263         GET_NAME( PREFERRED_FAMILY, &face->root.family_name );
1264       if ( !face->root.family_name )
1265         GET_NAME( FONT_FAMILY, &face->root.family_name );
1266
1267       if ( !ignore_preferred_subfamily )
1268         GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name );
1269       if ( !face->root.style_name )
1270         GET_NAME( FONT_SUBFAMILY, &face->root.style_name );
1271     }
1272     else
1273     {
1274       GET_NAME( WWS_FAMILY, &face->root.family_name );
1275       if ( !face->root.family_name && !ignore_preferred_family )
1276         GET_NAME( PREFERRED_FAMILY, &face->root.family_name );
1277       if ( !face->root.family_name )
1278         GET_NAME( FONT_FAMILY, &face->root.family_name );
1279
1280       GET_NAME( WWS_SUBFAMILY, &face->root.style_name );
1281       if ( !face->root.style_name && !ignore_preferred_subfamily )
1282         GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name );
1283       if ( !face->root.style_name )
1284         GET_NAME( FONT_SUBFAMILY, &face->root.style_name );
1285     }
1286
1287     /* now set up root fields */
1288     {
1289       FT_Face  root  = &face->root;
1290       FT_Long  flags = root->face_flags;
1291
1292
1293       /*********************************************************************/
1294       /*                                                                   */
1295       /* Compute face flags.                                               */
1296       /*                                                                   */
1297       if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC ||
1298            face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX )
1299         flags |= FT_FACE_FLAG_COLOR;      /* color glyphs */
1300
1301       if ( has_outline == TRUE )
1302         flags |= FT_FACE_FLAG_SCALABLE;   /* scalable outlines */
1303
1304       /* The sfnt driver only supports bitmap fonts natively, thus we */
1305       /* don't set FT_FACE_FLAG_HINTER.                               */
1306       flags |= FT_FACE_FLAG_SFNT       |  /* SFNT file format  */
1307                FT_FACE_FLAG_HORIZONTAL;   /* horizontal data   */
1308
1309 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
1310       if ( !psnames_error                             &&
1311            face->postscript.FormatType != 0x00030000L )
1312         flags |= FT_FACE_FLAG_GLYPH_NAMES;
1313 #endif
1314
1315       /* fixed width font? */
1316       if ( face->postscript.isFixedPitch )
1317         flags |= FT_FACE_FLAG_FIXED_WIDTH;
1318
1319       /* vertical information? */
1320       if ( face->vertical_info )
1321         flags |= FT_FACE_FLAG_VERTICAL;
1322
1323       /* kerning available ? */
1324       if ( TT_FACE_HAS_KERNING( face ) )
1325         flags |= FT_FACE_FLAG_KERNING;
1326
1327 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1328       /* Don't bother to load the tables unless somebody asks for them. */
1329       /* No need to do work which will (probably) not be used.          */
1330       if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 &&
1331            tt_face_lookup_table( face, TTAG_fvar ) != 0 &&
1332            tt_face_lookup_table( face, TTAG_gvar ) != 0 )
1333         flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
1334 #endif
1335
1336       root->face_flags = flags;
1337
1338       /*********************************************************************/
1339       /*                                                                   */
1340       /* Compute style flags.                                              */
1341       /*                                                                   */
1342
1343       flags = 0;
1344       if ( has_outline == TRUE && face->os2.version != 0xFFFFU )
1345       {
1346         /* We have an OS/2 table; use the `fsSelection' field.  Bit 9 */
1347         /* indicates an oblique font face.  This flag has been        */
1348         /* introduced in version 1.5 of the OpenType specification.   */
1349
1350         if ( face->os2.fsSelection & 512 )       /* bit 9 */
1351           flags |= FT_STYLE_FLAG_ITALIC;
1352         else if ( face->os2.fsSelection & 1 )    /* bit 0 */
1353           flags |= FT_STYLE_FLAG_ITALIC;
1354
1355         if ( face->os2.fsSelection & 32 )        /* bit 5 */
1356           flags |= FT_STYLE_FLAG_BOLD;
1357       }
1358       else
1359       {
1360         /* this is an old Mac font, use the header field */
1361
1362         if ( face->header.Mac_Style & 1 )
1363           flags |= FT_STYLE_FLAG_BOLD;
1364
1365         if ( face->header.Mac_Style & 2 )
1366           flags |= FT_STYLE_FLAG_ITALIC;
1367       }
1368
1369       root->style_flags |= flags;
1370
1371       /*********************************************************************/
1372       /*                                                                   */
1373       /* Polish the charmaps.                                              */
1374       /*                                                                   */
1375       /*   Try to set the charmap encoding according to the platform &     */
1376       /*   encoding ID of each charmap.                                    */
1377       /*                                                                   */
1378
1379       tt_face_build_cmaps( face );  /* ignore errors */
1380
1381
1382       /* set the encoding fields */
1383       {
1384         FT_Int  m;
1385
1386
1387         for ( m = 0; m < root->num_charmaps; m++ )
1388         {
1389           FT_CharMap  charmap = root->charmaps[m];
1390
1391
1392           charmap->encoding = sfnt_find_encoding( charmap->platform_id,
1393                                                   charmap->encoding_id );
1394
1395 #if 0
1396           if ( root->charmap     == NULL &&
1397                charmap->encoding == FT_ENCODING_UNICODE )
1398           {
1399             /* set 'root->charmap' to the first Unicode encoding we find */
1400             root->charmap = charmap;
1401           }
1402 #endif
1403         }
1404       }
1405
1406 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1407
1408       /*
1409        *  Now allocate the root array of FT_Bitmap_Size records and
1410        *  populate them.  Unfortunately, it isn't possible to indicate bit
1411        *  depths in the FT_Bitmap_Size record.  This is a design error.
1412        */
1413       {
1414         FT_UInt  i, count;
1415
1416
1417         count = face->sbit_num_strikes;
1418
1419         if ( count > 0 )
1420         {
1421           FT_Memory        memory   = face->root.stream->memory;
1422           FT_UShort        em_size  = face->header.Units_Per_EM;
1423           FT_Short         avgwidth = face->os2.xAvgCharWidth;
1424           FT_Size_Metrics  metrics;
1425
1426
1427           if ( em_size == 0 || face->os2.version == 0xFFFFU )
1428           {
1429             avgwidth = 1;
1430             em_size = 1;
1431           }
1432
1433           if ( FT_NEW_ARRAY( root->available_sizes, count ) )
1434             goto Exit;
1435
1436           for ( i = 0; i < count; i++ )
1437           {
1438             FT_Bitmap_Size*  bsize = root->available_sizes + i;
1439
1440
1441             error = sfnt->load_strike_metrics( face, i, &metrics );
1442             if ( error )
1443               goto Exit;
1444
1445             bsize->height = (FT_Short)( metrics.height >> 6 );
1446             bsize->width = (FT_Short)(
1447                 ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
1448
1449             bsize->x_ppem = metrics.x_ppem << 6;
1450             bsize->y_ppem = metrics.y_ppem << 6;
1451
1452             /* assume 72dpi */
1453             bsize->size   = metrics.y_ppem << 6;
1454           }
1455
1456           root->face_flags     |= FT_FACE_FLAG_FIXED_SIZES;
1457           root->num_fixed_sizes = (FT_Int)count;
1458         }
1459       }
1460
1461 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1462
1463       /* a font with no bitmaps and no outlines is scalable; */
1464       /* it has only empty glyphs then                       */
1465       if ( !FT_HAS_FIXED_SIZES( root ) && !FT_IS_SCALABLE( root ) )
1466         root->face_flags |= FT_FACE_FLAG_SCALABLE;
1467
1468
1469       /*********************************************************************/
1470       /*                                                                   */
1471       /*  Set up metrics.                                                  */
1472       /*                                                                   */
1473       if ( FT_IS_SCALABLE( root ) )
1474       {
1475         /* XXX What about if outline header is missing */
1476         /*     (e.g. sfnt wrapped bitmap)?             */
1477         root->bbox.xMin    = face->header.xMin;
1478         root->bbox.yMin    = face->header.yMin;
1479         root->bbox.xMax    = face->header.xMax;
1480         root->bbox.yMax    = face->header.yMax;
1481         root->units_per_EM = face->header.Units_Per_EM;
1482
1483
1484         /* XXX: Computing the ascender/descender/height is very different */
1485         /*      from what the specification tells you.  Apparently, we    */
1486         /*      must be careful because                                   */
1487         /*                                                                */
1488         /*      - not all fonts have an OS/2 table; in this case, we take */
1489         /*        the values in the horizontal header.  However, these    */
1490         /*        values very often are not reliable.                     */
1491         /*                                                                */
1492         /*      - otherwise, the correct typographic values are in the    */
1493         /*        sTypoAscender, sTypoDescender & sTypoLineGap fields.    */
1494         /*                                                                */
1495         /*        However, certain fonts have these fields set to 0.      */
1496         /*        Rather, they have usWinAscent & usWinDescent correctly  */
1497         /*        set (but with different values).                        */
1498         /*                                                                */
1499         /*      As an example, Arial Narrow is implemented through four   */
1500         /*      files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
1501         /*                                                                */
1502         /*      Strangely, all fonts have the same values in their        */
1503         /*      sTypoXXX fields, except ARIALNB which sets them to 0.     */
1504         /*                                                                */
1505         /*      On the other hand, they all have different                */
1506         /*      usWinAscent/Descent values -- as a conclusion, the OS/2   */
1507         /*      table cannot be used to compute the text height reliably! */
1508         /*                                                                */
1509
1510         /* The ascender and descender are taken from the `hhea' table. */
1511         /* If zero, they are taken from the `OS/2' table.              */
1512
1513         root->ascender  = face->horizontal.Ascender;
1514         root->descender = face->horizontal.Descender;
1515
1516         root->height = root->ascender - root->descender +
1517                        face->horizontal.Line_Gap;
1518
1519         if ( !( root->ascender || root->descender ) )
1520         {
1521           if ( face->os2.version != 0xFFFFU )
1522           {
1523             if ( face->os2.sTypoAscender || face->os2.sTypoDescender )
1524             {
1525               root->ascender  = face->os2.sTypoAscender;
1526               root->descender = face->os2.sTypoDescender;
1527
1528               root->height = root->ascender - root->descender +
1529                              face->os2.sTypoLineGap;
1530             }
1531             else
1532             {
1533               root->ascender  =  (FT_Short)face->os2.usWinAscent;
1534               root->descender = -(FT_Short)face->os2.usWinDescent;
1535
1536               root->height = root->ascender - root->descender;
1537             }
1538           }
1539         }
1540
1541         root->max_advance_width  =
1542           (FT_Short)face->horizontal.advance_Width_Max;
1543         root->max_advance_height =
1544           (FT_Short)( face->vertical_info ? face->vertical.advance_Height_Max
1545                                           : root->height );
1546
1547         /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */
1548         /* Adjust underline position from top edge to centre of     */
1549         /* stroke to convert TrueType meaning to FreeType meaning.  */
1550         root->underline_position  = face->postscript.underlinePosition -
1551                                     face->postscript.underlineThickness / 2;
1552         root->underline_thickness = face->postscript.underlineThickness;
1553       }
1554
1555     }
1556
1557   Exit:
1558     FT_TRACE2(( "sfnt_load_face: done\n" ));
1559
1560     return error;
1561   }
1562
1563
1564 #undef LOAD_
1565 #undef LOADM_
1566 #undef GET_NAME
1567
1568
1569   FT_LOCAL_DEF( void )
1570   sfnt_done_face( TT_Face  face )
1571   {
1572     FT_Memory     memory;
1573     SFNT_Service  sfnt;
1574
1575
1576     if ( !face )
1577       return;
1578
1579     memory = face->root.memory;
1580     sfnt   = (SFNT_Service)face->sfnt;
1581
1582     if ( sfnt )
1583     {
1584       /* destroy the postscript names table if it is loaded */
1585       if ( sfnt->free_psnames )
1586         sfnt->free_psnames( face );
1587
1588       /* destroy the embedded bitmaps table if it is loaded */
1589       if ( sfnt->free_eblc )
1590         sfnt->free_eblc( face );
1591     }
1592
1593 #ifdef TT_CONFIG_OPTION_BDF
1594     /* freeing the embedded BDF properties */
1595     tt_face_free_bdf_props( face );
1596 #endif
1597
1598     /* freeing the kerning table */
1599     tt_face_done_kern( face );
1600
1601     /* freeing the collection table */
1602     FT_FREE( face->ttc_header.offsets );
1603     face->ttc_header.count = 0;
1604
1605     /* freeing table directory */
1606     FT_FREE( face->dir_tables );
1607     face->num_tables = 0;
1608
1609     {
1610       FT_Stream  stream = FT_FACE_STREAM( face );
1611
1612
1613       /* simply release the 'cmap' table frame */
1614       FT_FRAME_RELEASE( face->cmap_table );
1615       face->cmap_size = 0;
1616     }
1617
1618     /* freeing the horizontal metrics */
1619     {
1620       FT_Stream  stream = FT_FACE_STREAM( face );
1621
1622
1623       FT_FRAME_RELEASE( face->horz_metrics );
1624       FT_FRAME_RELEASE( face->vert_metrics );
1625       face->horz_metrics_size = 0;
1626       face->vert_metrics_size = 0;
1627     }
1628
1629     /* freeing the vertical ones, if any */
1630     if ( face->vertical_info )
1631     {
1632       FT_FREE( face->vertical.long_metrics  );
1633       FT_FREE( face->vertical.short_metrics );
1634       face->vertical_info = 0;
1635     }
1636
1637     /* freeing the gasp table */
1638     FT_FREE( face->gasp.gaspRanges );
1639     face->gasp.numRanges = 0;
1640
1641     /* freeing the name table */
1642     if ( sfnt )
1643       sfnt->free_name( face );
1644
1645     /* freeing family and style name */
1646     FT_FREE( face->root.family_name );
1647     FT_FREE( face->root.style_name );
1648
1649     /* freeing sbit size table */
1650     FT_FREE( face->root.available_sizes );
1651     face->root.num_fixed_sizes = 0;
1652
1653     FT_FREE( face->postscript_name );
1654
1655     face->sfnt = NULL;
1656   }
1657
1658
1659 /* END */