:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / subsys / win32k / freetype / src / sfnt / ttload.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  ttload.c                                                               */
4 /*                                                                         */
5 /*    Load the basic TrueType tables, i.e., tables that can be either in   */
6 /*    TTF or OTF fonts (body).                                             */
7 /*                                                                         */
8 /*  Copyright 1996-2000 by                                                 */
9 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
10 /*                                                                         */
11 /*  This file is part of the FreeType project, and may only be used,       */
12 /*  modified, and distributed under the terms of the FreeType project      */
13 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
14 /*  this file you indicate that you have read the license and              */
15 /*  understand and accept it fully.                                        */
16 /*                                                                         */
17 /***************************************************************************/
18
19
20 #include <freetype/internal/ftdebug.h>
21 #include <freetype/internal/tterrors.h>
22 #include <freetype/tttags.h>
23
24
25 #ifdef FT_FLAT_COMPILE
26
27 #include "ttload.h"
28 #include "ttcmap.h"
29
30 #else
31
32 #include <freetype/src/sfnt/ttload.h>
33 #include <freetype/src/sfnt/ttcmap.h>
34
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_ttload
46
47
48   /*************************************************************************/
49   /*                                                                       */
50   /* <Function>                                                            */
51   /*    TT_LookUp_Table                                                    */
52   /*                                                                       */
53   /* <Description>                                                         */
54   /*    Looks for a TrueType table by name.                                */
55   /*                                                                       */
56   /* <Input>                                                               */
57   /*    face :: A face object handle.                                      */
58   /*    tag  :: The searched tag.                                          */
59   /*                                                                       */
60   /* <Return>                                                              */
61   /*    A pointer to the table directory entry.  0 if not found.           */
62   /*                                                                       */
63   LOCAL_FUNC
64   TT_Table*  TT_LookUp_Table( TT_Face   face,
65                               FT_ULong  tag  )
66   {
67     TT_Table*  entry;
68     TT_Table*  limit;
69
70
71     FT_TRACE3(( "TT_LookUp_Table: %08p, `%c%c%c%c'\n",
72                   face,
73                   (FT_Char)( tag >> 24 ),
74                   (FT_Char)( tag >> 16 ),
75                   (FT_Char)( tag >> 8  ),
76                   (FT_Char)( tag       ) ));
77
78     entry = face->dir_tables;
79     limit = entry + face->num_tables;
80
81     for ( ; entry < limit; entry++ )
82     {
83       if ( entry->Tag == tag )
84         return entry;
85     }
86
87     FT_TRACE3(( "    Could not find table!\n" ));
88     return 0;
89   }
90
91
92   /*************************************************************************/
93   /*                                                                       */
94   /* <Function>                                                            */
95   /*    TT_Goto_Table                                                      */
96   /*                                                                       */
97   /* <Description>                                                         */
98   /*    Looks for a TrueType table by name, then seek a stream to it.      */
99   /*                                                                       */
100   /* <Input>                                                               */
101   /*    face   :: A face object handle.                                    */
102   /*    tag    :: The searched tag.                                        */
103   /*    stream :: The stream to seek when the table is found.              */
104   /*                                                                       */
105   /* <Output>                                                              */
106   /*    length :: The length of the table if found, undefined otherwise.   */
107   /*                                                                       */
108   /* <Return>                                                              */
109   /*    FreeType error code.  0 means success.                             */
110   /*                                                                       */
111   LOCAL_FUNC
112   FT_Error  TT_Goto_Table( TT_Face    face,
113                            FT_ULong   tag,
114                            FT_Stream  stream,
115                            FT_ULong*  length )
116   {
117     TT_Table*  table;
118     FT_Error   error;
119
120
121     table = TT_LookUp_Table( face, tag );
122     if ( table )
123     {
124       if ( length )
125         *length = table->Length;
126
127       (void)FILE_Seek( table->Offset );
128     }
129     else
130       error = TT_Err_Table_Missing;
131
132     return error;
133   }
134
135
136   /*************************************************************************/
137   /*                                                                       */
138   /* <Function>                                                            */
139   /*    TT_Load_SFNT_Header                                                */
140   /*                                                                       */
141   /* <Description>                                                         */
142   /*    Loads the header of a SFNT font file.  Supports collections.       */
143   /*                                                                       */
144   /* <Input>                                                               */
145   /*    face       :: A handle to the target face object.                  */
146   /*    stream     :: The input stream.                                    */
147   /*    face_index :: If the font is a collection, the number of the font  */
148   /*                  in the collection, ignored otherwise.                */
149   /*                                                                       */
150   /* <Output>                                                              */
151   /*    sfnt       :: The SFNT header.                                     */
152   /*                                                                       */
153   /* <Return>                                                              */
154   /*    FreeType error code.  0 means success.                             */
155   /*                                                                       */
156   /* <Note>                                                                */
157   /*    The stream cursor must be at the font file's origin.               */
158   /*                                                                       */
159   /*    This function recognizes fonts embedded in a `TrueType collection' */
160   /*                                                                       */
161   /*    The header will be checked whether it is valid by looking at the   */
162   /*    values of `search_range', `entry_selector', and `range_shift'.     */
163   /*                                                                       */
164   LOCAL_FUNC
165   FT_Error  TT_Load_SFNT_Header( TT_Face       face,
166                                  FT_Stream     stream,
167                                  FT_Long       face_index,
168                                  SFNT_Header*  sfnt )
169   {
170     FT_Error   error;
171     FT_ULong   format_tag;
172     FT_Memory  memory = stream->memory;
173
174     const FT_Frame_Field  sfnt_header_fields[] =
175     {
176       FT_FRAME_START( 8 ),
177         FT_FRAME_USHORT( SFNT_Header, num_tables ),
178         FT_FRAME_USHORT( SFNT_Header, search_range ),
179         FT_FRAME_USHORT( SFNT_Header, entry_selector ),
180         FT_FRAME_USHORT( SFNT_Header, range_shift ),
181       FT_FRAME_END
182     };
183
184     const FT_Frame_Field  ttc_header_fields[] =
185     {
186       FT_FRAME_START( 8 ),
187         FT_FRAME_LONG( TTC_Header, version ),
188         FT_FRAME_LONG( TTC_Header, count   ),
189       FT_FRAME_END };
190
191
192     FT_TRACE2(( "TT_Load_SFNT_Header: %08p, %ld\n",
193                 face, face_index ));
194
195     face->ttc_header.tag      = 0;
196     face->ttc_header.version  = 0;
197     face->ttc_header.count    = 0;
198
199     face->num_tables = 0;
200
201     /* first of all, read the first 4 bytes.  If it is `ttcf', then the */
202     /* file is a TrueType collection, otherwise it can be any other     */
203     /* kind of font.                                                    */
204     if ( READ_ULong( format_tag ) )
205       goto Exit;
206
207     if ( format_tag == TTAG_ttcf )
208     {
209       FT_Int  n;
210
211
212       FT_TRACE3(( "TT_Load_SFNT_Header: file is a collection\n" ));
213
214       /* it's a TrueType collection, i.e. a file containing several */
215       /* font files.  Read the font directory now                   */
216       if ( READ_Fields( ttc_header_fields, &face->ttc_header ) )
217         goto Exit;
218
219       /* now read the offsets of each font in the file */
220       if ( ALLOC_ARRAY( face->ttc_header.offsets,
221                         face->ttc_header.count,
222                         FT_ULong )                     ||
223            ACCESS_Frame( face->ttc_header.count * 4L ) )
224         goto Exit;
225
226       for ( n = 0; n < face->ttc_header.count; n++ )
227         face->ttc_header.offsets[n] = GET_ULong();
228
229       FORGET_Frame();
230
231       /* check face index */
232       if ( face_index >= face->ttc_header.count )
233       {
234         error = TT_Err_Bad_Argument;
235         goto Exit;
236       }
237
238       /* seek to the appropriate TrueType file, then read tag */
239       if ( FILE_Seek( face->ttc_header.offsets[face_index] ) ||
240            READ_Long( format_tag )                           )
241         goto Exit;
242     }
243
244     /* the format tag was read, now check the rest of the header */
245     sfnt->format_tag = format_tag;
246     if ( READ_Fields( sfnt_header_fields, sfnt ) )
247       goto Exit;
248
249     /* now, check the values of `num_tables', `seach_range', etc. */
250     {
251       FT_UInt   num_tables     = sfnt->num_tables;
252       FT_ULong  entry_selector = 1L << sfnt->entry_selector;
253
254
255       /* IMPORTANT: Many fonts have an incorrect `search_range' value, so */
256       /*            we only check the `entry_selector' correctness here.  */
257       /*                                                                  */
258       if ( num_tables == 0                  ||
259            entry_selector > num_tables      ||
260            entry_selector * 2 <= num_tables )
261       {
262         FT_TRACE2(( "TT_Load_SFNT_Header: file is not SFNT!\n" ));
263         error = FT_Err_Unknown_File_Format;
264       }
265     }
266
267   Exit:
268     return error;
269   }
270
271
272   /*************************************************************************/
273   /*                                                                       */
274   /* <Function>                                                            */
275   /*    TT_Load_Directory                                                  */
276   /*                                                                       */
277   /* <Description>                                                         */
278   /*    Loads the table directory into a face object.                      */
279   /*                                                                       */
280   /* <InOut>                                                               */
281   /*    face   :: A handle to the target face object.                      */
282   /*                                                                       */
283   /* <Input>                                                               */
284   /*    stream :: The input stream.                                        */
285   /*    sfnt   :: The SFNT directory header.                               */
286   /*                                                                       */
287   /* <Return>                                                              */
288   /*    FreeType error code.  0 means success.                             */
289   /*                                                                       */
290   /* <Note>                                                                */
291   /*    The stream cursor must be at the font file's origin.               */
292   /*                                                                       */
293   LOCAL_FUNC
294   FT_Error  TT_Load_Directory( TT_Face       face,
295                                FT_Stream     stream,
296                                SFNT_Header*  sfnt )
297   {
298     FT_Error   error;
299     FT_Memory  memory = stream->memory;
300
301     TT_Table *entry, *limit;
302
303
304     FT_TRACE2(( "TT_Load_Directory: %08p\n", face ));
305
306     FT_TRACE2(( "-- Tables count:   %12u\n",  sfnt->num_tables ));
307     FT_TRACE2(( "-- Format version: %08lx\n", sfnt->format_tag ));
308
309     face->num_tables = sfnt->num_tables;
310
311     if ( ALLOC_ARRAY( face->dir_tables,
312                       face->num_tables,
313                       TT_Table ) )
314       goto Exit;
315
316     if ( ACCESS_Frame( face->num_tables * 16L ) )
317       goto Exit;
318
319     entry = face->dir_tables;
320     limit = entry + face->num_tables;
321
322     for ( ; entry < limit; entry++ )
323     {                    /* loop through the tables and get all entries */
324       entry->Tag      = GET_Tag4();
325       entry->CheckSum = GET_ULong();
326       entry->Offset   = GET_Long();
327       entry->Length   = GET_Long();
328
329       FT_TRACE2(( "  %c%c%c%c  -  %08lx  -  %08lx\n",
330                   (FT_Char)( entry->Tag >> 24 ),
331                   (FT_Char)( entry->Tag >> 16 ),
332                   (FT_Char)( entry->Tag >> 8  ),
333                   (FT_Char)( entry->Tag       ),
334                   entry->Offset,
335                   entry->Length ));
336     }
337
338     FORGET_Frame();
339
340     FT_TRACE2(( "Directory loaded\n\n" ));
341
342   Exit:
343     return error;
344   }
345
346
347   /*************************************************************************/
348   /*                                                                       */
349   /* <Function>                                                            */
350   /*    TT_Load_Any                                                        */
351   /*                                                                       */
352   /* <Description>                                                         */
353   /*    Loads any font table into client memory.                           */
354   /*                                                                       */
355   /* <Input>                                                               */
356   /*    face   :: The face object to look for.                             */
357   /*                                                                       */
358   /*    tag    :: The tag of table to load.  Use the value 0 if you want   */
359   /*              to access the whole font file, else set this parameter   */
360   /*              to a valid TrueType table tag that you can forge with    */
361   /*              the MAKE_TT_TAG macro.                                   */
362   /*                                                                       */
363   /*    offset :: The starting offset in the table (or the file if         */
364   /*              tag == 0).                                               */
365   /*                                                                       */
366   /*    length :: The address of the decision variable:                    */
367   /*                                                                       */
368   /*                If length == NULL:                                     */
369   /*                  Loads the whole table.  Returns an error if          */
370   /*                  `offset' == 0!                                       */
371   /*                                                                       */
372   /*                If *length == 0:                                       */
373   /*                  Exits immediately; returning the length of the given */
374   /*                  table or of the font file, depending on the value of */
375   /*                  `tag'.                                               */
376   /*                                                                       */
377   /*                If *length != 0:                                       */
378   /*                  Loads the next `length' bytes of table or font,      */
379   /*                  starting at offset `offset' (in table or font too).  */
380   /*                                                                       */
381   /* <Output>                                                              */
382   /*    buffer :: The address of target buffer.                            */
383   /*                                                                       */
384   /* <Return>                                                              */
385   /*    FreeType error code.  0 means success.                             */
386   /*                                                                       */
387   LOCAL_FUNC
388   FT_Error  TT_Load_Any( TT_Face    face,
389                          FT_ULong   tag,
390                          FT_Long    offset,
391                          FT_Byte*   buffer,
392                          FT_ULong*  length )
393   {
394     FT_Error   error;
395     FT_Stream  stream;
396     TT_Table*  table;
397     FT_ULong   size;
398
399
400     if ( tag != 0 )
401     {
402       /* look for tag in font directory */
403       table = TT_LookUp_Table( face, tag );
404       if ( !table )
405       {
406         error = TT_Err_Table_Missing;
407         goto Exit;
408       }
409
410       offset += table->Offset;
411       size    = table->Length;
412     }
413     else
414       /* tag == 0 -- the user wants to access the font file directly */
415       size = face->root.stream->size;
416
417     if ( length && *length == 0 )
418     {
419       *length = size;
420
421       return TT_Err_Ok;
422     }
423
424     if ( length )
425       size = *length;
426
427     stream = face->root.stream;
428     (void)FILE_Read_At( offset, buffer, size );
429
430   Exit:
431     return error;
432   }
433
434
435   /*************************************************************************/
436   /*                                                                       */
437   /* <Function>                                                            */
438   /*    TT_Load_Header                                                     */
439   /*                                                                       */
440   /* <Description>                                                         */
441   /*    Loads the TrueType font header.                                    */
442   /*                                                                       */
443   /* <Input>                                                               */
444   /*    face   :: A handle to the target face object.                      */
445   /*    stream :: The input stream.                                        */
446   /*                                                                       */
447   /* <Return>                                                              */
448   /*    FreeType error code.  0 means success.                             */
449   /*                                                                       */
450   LOCAL_FUNC
451   FT_Error  TT_Load_Header( TT_Face    face,
452                             FT_Stream  stream )
453   {
454     FT_Error    error;
455     TT_Header*  header;
456
457     static const FT_Frame_Field  header_fields[] =
458     {
459       FT_FRAME_START( 54 ),
460         FT_FRAME_ULONG(  TT_Header, Table_Version ),
461         FT_FRAME_ULONG(  TT_Header, Font_Revision ),
462         FT_FRAME_LONG(   TT_Header, CheckSum_Adjust ),
463         FT_FRAME_LONG(   TT_Header, Magic_Number ),
464         FT_FRAME_USHORT( TT_Header, Flags ),
465         FT_FRAME_USHORT( TT_Header, Units_Per_EM ),
466         FT_FRAME_LONG(   TT_Header, Created[0] ),
467         FT_FRAME_LONG(   TT_Header, Created[1] ),
468         FT_FRAME_LONG(   TT_Header, Modified[0] ),
469         FT_FRAME_LONG(   TT_Header, Modified[1] ),
470         FT_FRAME_SHORT(  TT_Header, xMin ),
471         FT_FRAME_SHORT(  TT_Header, yMin ),
472         FT_FRAME_SHORT(  TT_Header, xMax ),
473         FT_FRAME_SHORT(  TT_Header, yMax ),
474         FT_FRAME_USHORT( TT_Header, Mac_Style ),
475         FT_FRAME_USHORT( TT_Header, Lowest_Rec_PPEM ),
476         FT_FRAME_SHORT(  TT_Header, Font_Direction ),
477         FT_FRAME_SHORT(  TT_Header, Index_To_Loc_Format ),
478         FT_FRAME_SHORT(  TT_Header, Glyph_Data_Format ),
479       FT_FRAME_END
480     };
481
482
483     FT_TRACE2(( "Load_TT_Header: %08p\n", face ));
484
485     error = face->goto_table( face, TTAG_head, stream, 0 );
486     if ( error )
487     {
488       FT_TRACE0(( "Font Header is missing!\n" ));
489       goto Exit;
490     }
491
492     header = &face->header;
493
494     if ( READ_Fields( header_fields, header ) )
495       goto Exit;
496
497     FT_TRACE2(( "    Units per EM: %8u\n", header->Units_Per_EM ));
498     FT_TRACE2(( "    IndexToLoc:   %8d\n", header->Index_To_Loc_Format ));
499     FT_TRACE2(( "Font Header Loaded.\n" ));
500
501   Exit:
502     return error;
503   }
504
505
506   /*************************************************************************/
507   /*                                                                       */
508   /* <Function>                                                            */
509   /*    TT_Load_MaxProfile                                                 */
510   /*                                                                       */
511   /* <Description>                                                         */
512   /*    Loads the maximum profile into a face object.                      */
513   /*                                                                       */
514   /* <Input>                                                               */
515   /*    face   :: A handle to the target face object.                      */
516   /*    stream :: The input stream.                                        */
517   /*                                                                       */
518   /* <Return>                                                              */
519   /*    FreeType error code.  0 means success.                             */
520   /*                                                                       */
521   LOCAL_FUNC
522   FT_Error  TT_Load_MaxProfile( TT_Face    face,
523                                 FT_Stream  stream )
524   {
525     FT_Error        error;
526     TT_MaxProfile*  maxProfile = &face->max_profile;
527
528     const FT_Frame_Field  maxp_fields[] =
529     {
530       FT_FRAME_START( 32 ),
531         FT_FRAME_ULONG(  TT_MaxProfile, version ),
532         FT_FRAME_USHORT( TT_MaxProfile, numGlyphs ),
533         FT_FRAME_USHORT( TT_MaxProfile, maxPoints ),
534         FT_FRAME_USHORT( TT_MaxProfile, maxContours ),
535         FT_FRAME_USHORT( TT_MaxProfile, maxCompositePoints ),
536         FT_FRAME_USHORT( TT_MaxProfile, maxCompositeContours ),
537         FT_FRAME_USHORT( TT_MaxProfile, maxZones ),
538         FT_FRAME_USHORT( TT_MaxProfile, maxTwilightPoints ),
539         FT_FRAME_USHORT( TT_MaxProfile, maxStorage ),
540         FT_FRAME_USHORT( TT_MaxProfile, maxFunctionDefs ),
541         FT_FRAME_USHORT( TT_MaxProfile, maxInstructionDefs ),
542         FT_FRAME_USHORT( TT_MaxProfile, maxStackElements ),
543         FT_FRAME_USHORT( TT_MaxProfile, maxSizeOfInstructions ),
544         FT_FRAME_USHORT( TT_MaxProfile, maxComponentElements ),
545         FT_FRAME_USHORT( TT_MaxProfile, maxComponentDepth ),
546       FT_FRAME_END };
547
548
549     FT_TRACE2(( "Load_TT_MaxProfile: %08p\n", face ));
550
551     error = face->goto_table( face, TTAG_maxp, stream, 0 );
552     if ( error )
553       goto Exit;
554
555     if ( READ_Fields( maxp_fields, maxProfile ) )
556       goto Exit;
557
558     /* XXX: an adjustment that is necessary to load certain */
559     /*      broken fonts like `Keystrokes MT' :-(           */
560     /*                                                      */
561     /*   We allocate 64 function entries by default when    */
562     /*   the maxFunctionDefs field is null.                 */
563
564     if ( maxProfile->maxFunctionDefs == 0 )
565       maxProfile->maxFunctionDefs = 64;
566
567     face->root.num_glyphs = maxProfile->numGlyphs;
568
569     face->root.max_points = MAX( maxProfile->maxCompositePoints,
570                                  maxProfile->maxPoints );
571
572     face->root.max_contours = MAX( maxProfile->maxCompositeContours,
573                                    maxProfile->maxContours );
574
575     face->max_components = (FT_ULong)maxProfile->maxComponentElements +
576                            maxProfile->maxComponentDepth;
577
578     /* XXX: some fonts have maxComponents set to 0; we will */
579     /*      then use 16 of them by default.                 */
580     if ( face->max_components == 0 )
581       face->max_components = 16;
582
583     /* We also increase maxPoints and maxContours in order to support */
584     /* some broken fonts.                                             */
585     face->root.max_points   += 8;
586     face->root.max_contours += 4;
587
588     FT_TRACE2(( "MAXP loaded.\n" ));
589
590   Exit:
591     return error;
592   }
593
594
595   /*************************************************************************/
596   /*                                                                       */
597   /* <Function>                                                            */
598   /*    TT_Load_Metrics                                                    */
599   /*                                                                       */
600   /* <Description>                                                         */
601   /*    Loads the horizontal or vertical metrics table into a face object. */
602   /*                                                                       */
603   /* <Input>                                                               */
604   /*    face     :: A handle to the target face object.                    */
605   /*    stream   :: The input stream.                                      */
606   /*    vertical :: A boolean flag.  If set, load vertical metrics.        */
607   /*                                                                       */
608   /* <Return>                                                              */
609   /*    FreeType error code.  0 means success.                             */
610   /*                                                                       */
611   static
612   FT_Error  TT_Load_Metrics( TT_Face    face,
613                              FT_Stream  stream,
614                              FT_Bool    vertical )
615   {
616     FT_Error   error;
617     FT_Memory  memory = stream->memory;
618
619     FT_ULong   table_len;
620     FT_Long    num_shorts, num_longs, num_shorts_checked;
621
622     TT_LongMetrics**   longs;
623     TT_ShortMetrics**  shorts;
624
625
626     FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical"
627                                                        : "Horizontal",
628                                               face ));
629
630     if ( vertical )
631     {
632       /* The table is optional, quit silently if it wasn't found       */
633       /* XXX: Some fonts have a valid vertical header with a non-null  */
634       /*      `number_of_VMetrics' fields, but no corresponding `vmtx' */
635       /*      table to get the metrics from (e.g. mingliu).            */
636       /*                                                               */
637       /*      For safety, we set the field to 0!                       */
638       /*                                                               */
639       error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
640       if ( error )
641       {
642         /* Set number_Of_VMetrics to 0! */
643         FT_TRACE2(( "  no vertical header in file.\n" ));
644         face->vertical.number_Of_VMetrics = 0;
645         error = TT_Err_Ok;
646         goto Exit;
647       }
648
649       num_longs = face->vertical.number_Of_VMetrics;
650       longs     = (TT_LongMetrics**)&face->vertical.long_metrics;
651       shorts    = (TT_ShortMetrics**)&face->vertical.short_metrics;
652     }
653     else
654     {
655       error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
656       if ( error )
657       {
658         FT_ERROR(( " no horizontal metrics in file!\n" ));
659         error = TT_Err_Hmtx_Table_Missing;
660         goto Exit;
661       }
662
663       num_longs = face->horizontal.number_Of_HMetrics;
664       longs     = (TT_LongMetrics**)&face->horizontal.long_metrics;
665       shorts    = (TT_ShortMetrics**)&face->horizontal.short_metrics;
666     }
667
668     /* never trust derived values */
669
670     num_shorts         = face->max_profile.numGlyphs - num_longs;
671     num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
672
673     if ( num_shorts < 0 )
674     {
675       FT_ERROR(( "TT_Load_%s_Metrics: more metrics than glyphs!\n",
676                  vertical ? "Vertical"
677                           : "Horizontal" ));
678
679       error = vertical ? TT_Err_Invalid_Vert_Metrics
680                        : TT_Err_Invalid_Horiz_Metrics;
681       goto Exit;
682     }
683
684     if ( ALLOC_ARRAY( *longs,  num_longs,  TT_LongMetrics )  ||
685          ALLOC_ARRAY( *shorts, num_shorts, TT_ShortMetrics ) )
686       goto Exit;
687
688     if ( ACCESS_Frame( table_len ) )
689       goto Exit;
690
691     {
692       TT_LongMetrics*  cur   = *longs;
693       TT_LongMetrics*  limit = cur + num_longs;
694
695
696       for ( ; cur < limit; cur++ )
697       {
698         cur->advance = GET_UShort();
699         cur->bearing = GET_Short();
700       }
701     }
702
703     /* do we have an inconsistent number of metric values? */
704     {
705       TT_ShortMetrics*  cur   = *shorts;
706       TT_ShortMetrics*  limit = cur + MIN( num_shorts, num_shorts_checked );
707
708
709       for ( ; cur < limit; cur++ )
710         *cur = GET_Short();
711
712       /* we fill up the missing left side bearings with the     */
713       /* last valid value.  Since this will occur for buggy CJK */
714       /* fonts usually only, nothing serious will happen        */
715       if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
716       {
717         FT_Short  val = *(shorts)[num_shorts_checked - 1];
718
719
720         limit = *shorts + num_shorts;
721         for ( ; cur < limit; cur++ )
722           *cur = val;
723       }
724     }
725
726     FORGET_Frame();
727
728     FT_TRACE2(( "loaded\n" ));
729
730   Exit:
731     return error;
732   }
733
734
735   /*************************************************************************/
736   /*                                                                       */
737   /* <Function>                                                            */
738   /*    TT_Load_Metrics_Header                                             */
739   /*                                                                       */
740   /* <Description>                                                         */
741   /*    Loads the horizontal or vertical header in a face object.          */
742   /*                                                                       */
743   /* <Input>                                                               */
744   /*    face     :: A handle to the target face object.                    */
745   /*    stream   :: The input stream.                                      */
746   /*    vertical :: A boolean flag.  If set, load vertical metrics.        */
747   /*                                                                       */
748   /* <Return>                                                              */
749   /*    FreeType error code.  0 means success.                             */
750   /*                                                                       */
751   LOCAL_FUNC
752   FT_Error  TT_Load_Metrics_Header( TT_Face    face,
753                                     FT_Stream  stream,
754                                     FT_Bool    vertical )
755   {
756     FT_Error        error;
757     TT_HoriHeader*  header;
758
759     const FT_Frame_Field  metrics_header_fields[] =
760     {
761       FT_FRAME_START( 36 ),
762         FT_FRAME_ULONG(  TT_HoriHeader, Version ),
763         FT_FRAME_SHORT(  TT_HoriHeader, Ascender ),
764         FT_FRAME_SHORT(  TT_HoriHeader, Descender ),
765         FT_FRAME_SHORT(  TT_HoriHeader, Line_Gap ),
766         FT_FRAME_USHORT( TT_HoriHeader, advance_Width_Max ),
767         FT_FRAME_SHORT(  TT_HoriHeader, min_Left_Side_Bearing ),
768         FT_FRAME_SHORT(  TT_HoriHeader, min_Right_Side_Bearing ),
769         FT_FRAME_SHORT(  TT_HoriHeader, xMax_Extent ),
770         FT_FRAME_SHORT(  TT_HoriHeader, caret_Slope_Rise ),
771         FT_FRAME_SHORT(  TT_HoriHeader, caret_Slope_Run ),
772         FT_FRAME_SHORT(  TT_HoriHeader, Reserved[0] ),
773         FT_FRAME_SHORT(  TT_HoriHeader, Reserved[1] ),
774         FT_FRAME_SHORT(  TT_HoriHeader, Reserved[2] ),
775         FT_FRAME_SHORT(  TT_HoriHeader, Reserved[3] ),
776         FT_FRAME_SHORT(  TT_HoriHeader, Reserved[4] ),
777         FT_FRAME_SHORT(  TT_HoriHeader, metric_Data_Format ),
778         FT_FRAME_USHORT( TT_HoriHeader, number_Of_HMetrics ),
779       FT_FRAME_END
780     };
781
782
783     FT_TRACE2(( vertical ? "Vertical header " : "Horizontal header " ));
784
785     if ( vertical )
786     {
787       face->vertical_info = 0;
788
789       /* The vertical header table is optional, so return quietly if */
790       /* we don't find it.                                           */
791       error = face->goto_table( face, TTAG_vhea, stream, 0 );
792       if ( error )
793       {
794         error = TT_Err_Ok;
795         goto Exit;
796       }
797
798       face->vertical_info = 1;
799       header = (TT_HoriHeader*)&face->vertical;
800     }
801     else
802     {
803       /* The horizontal header is mandatory; return an error if we */
804       /* don't find it.                                            */
805       error = face->goto_table( face, TTAG_hhea, stream, 0 );
806       if ( error )
807       {
808         error = TT_Err_Horiz_Header_Missing;
809         goto Exit;
810       }
811
812       header = &face->horizontal;
813     }
814
815     if ( READ_Fields( metrics_header_fields, header ) )
816       goto Exit;
817
818     header->long_metrics  = NULL;
819     header->short_metrics = NULL;
820
821     FT_TRACE2(( "loaded\n" ));
822
823     /* Now try to load the corresponding metrics */
824
825     error = TT_Load_Metrics( face, stream, vertical );
826
827   Exit:
828     return error;
829   }
830
831
832   /*************************************************************************/
833   /*                                                                       */
834   /* <Function>                                                            */
835   /*    TT_Load_Names                                                      */
836   /*                                                                       */
837   /* <Description>                                                         */
838   /*    Loads the name records.                                            */
839   /*                                                                       */
840   /* <Input>                                                               */
841   /*    face   :: A handle to the target face object.                      */
842   /*    stream :: The input stream.                                        */
843   /*                                                                       */
844   /* <Return>                                                              */
845   /*    FreeType error code.  0 means success.                             */
846   /*                                                                       */
847   LOCAL_FUNC
848   FT_Error  TT_Load_Names( TT_Face    face,
849                            FT_Stream  stream )
850   {
851     FT_Error   error;
852     FT_Memory  memory = stream->memory;
853
854     FT_ULong   table_pos, table_len;
855     FT_ULong   storageSize;
856
857     TT_NameTable*  names;
858
859     const FT_Frame_Field  name_table_fields[] =
860     {
861       FT_FRAME_START( 6 ),
862         FT_FRAME_USHORT( TT_NameTable, format ),
863         FT_FRAME_USHORT( TT_NameTable, numNameRecords ),
864         FT_FRAME_USHORT( TT_NameTable, storageOffset ),
865       FT_FRAME_END
866     };
867
868     const FT_Frame_Field  name_record_fields[] =
869     {
870       /* no FT_FRAME_START */
871         FT_FRAME_USHORT( TT_NameRec, platformID ),
872         FT_FRAME_USHORT( TT_NameRec, encodingID ),
873         FT_FRAME_USHORT( TT_NameRec, languageID ),
874         FT_FRAME_USHORT( TT_NameRec, nameID ),
875         FT_FRAME_USHORT( TT_NameRec, stringLength ),
876         FT_FRAME_USHORT( TT_NameRec, stringOffset ),
877       FT_FRAME_END
878     };
879
880
881     FT_TRACE2(( "Names " ));
882
883     error = face->goto_table( face, TTAG_name, stream, &table_len );
884     if ( error )
885     {
886       /* The name table is required so indicate failure. */
887       FT_TRACE2(( "is missing!\n" ));
888       error = TT_Err_Name_Table_Missing;
889       goto Exit;
890     }
891
892     table_pos = FILE_Pos();
893
894     names = &face->name_table;
895
896     if ( READ_Fields( name_table_fields, names ) )
897       goto Exit;
898
899     /* Allocate the array of name records. */
900     if ( ALLOC_ARRAY( names->names,
901                       names->numNameRecords,
902                       TT_NameRec )                   ||
903          ACCESS_Frame( names->numNameRecords * 12L ) )
904       goto Exit;
905
906     /* Load the name records and determine how much storage is needed */
907     /* to hold the strings themselves.                                */
908     {
909       TT_NameRec*  cur   = names->names;
910       TT_NameRec*  limit = cur + names->numNameRecords;
911
912
913       storageSize = 0;
914
915       for ( ; cur < limit; cur ++ )
916       {
917         FT_ULong  upper;
918
919
920         (void)READ_Fields( name_record_fields, cur );
921
922         upper = (FT_ULong)( cur->stringOffset + cur->stringLength );
923         if ( upper > storageSize )
924           storageSize = upper;
925       }
926     }
927
928     FORGET_Frame();
929
930     if ( storageSize > 0 )
931     {
932       /* allocate the name storage area in memory, then read it */
933       if ( ALLOC( names->storage, storageSize )               ||
934            FILE_Read_At( table_pos + names->storageOffset,
935                          names->storage, storageSize ) )
936         goto Exit;
937
938       /* Go through and assign the string pointers to the name records. */
939       {
940         TT_NameRec*  cur   = names->names;
941         TT_NameRec*  limit = cur + names->numNameRecords;
942
943
944         for ( ; cur < limit; cur++ )
945           cur->string = names->storage + cur->stringOffset;
946       }
947
948 #ifdef FT_DEBUG_LEVEL_TRACE
949
950       /* Print Name Record Table in case of debugging */
951       {
952         TT_NameRec*  cur   = names->names;
953         TT_NameRec*  limit = cur + names->numNameRecords;
954
955
956         for ( ; cur < limit; cur++ )
957         {
958           FT_UInt  j;
959
960
961           FT_TRACE3(( "%d %d %x %d\n  ",
962                        cur->platformID,
963                        cur->encodingID,
964                        cur->languageID,
965                        cur->nameID ));
966
967           /* I know that M$ encoded strings are Unicode,            */
968           /* but this works reasonable well for debugging purposes. */
969           if ( cur->string )
970             for ( j = 0; j < cur->stringLength; j++ )
971             {
972               FT_Char  c = *( cur->string + j );
973
974
975               if ( (FT_Byte)c < 128 )
976                 FT_TRACE3(( "%c", c ));
977             }
978         }
979       }
980       FT_TRACE3(( "\n" ));
981
982 #endif /* FT_DEBUG_LEVEL_TRACE */
983
984     }
985     FT_TRACE2(( "loaded\n" ));
986
987     /* everything went well, update face->num_names */
988     face->num_names = names->numNameRecords;
989
990   Exit:
991     return error;
992   }
993
994
995   /*************************************************************************/
996   /*                                                                       */
997   /* <Function>                                                            */
998   /*    TT_Free_Names                                                      */
999   /*                                                                       */
1000   /* <Description>                                                         */
1001   /*    Frees the name records.                                            */
1002   /*                                                                       */
1003   /* <Input>                                                               */
1004   /*    face :: A handle to the target face object.                        */
1005   /*                                                                       */
1006   LOCAL_FUNC
1007   void  TT_Free_Names( TT_Face  face )
1008   {
1009     FT_Memory      memory = face->root.driver->root.memory;
1010     TT_NameTable*  names  = &face->name_table;
1011
1012
1013     /* free strings table */
1014     FREE( names->names );
1015
1016     /* free strings storage */
1017     FREE( names->storage );
1018
1019     names->numNameRecords = 0;
1020     names->format         = 0;
1021     names->storageOffset  = 0;
1022   }
1023
1024
1025   /*************************************************************************/
1026   /*                                                                       */
1027   /* <Function>                                                            */
1028   /*    TT_Load_CMap                                                       */
1029   /*                                                                       */
1030   /* <Description>                                                         */
1031   /*    Loads the cmap directory in a face object.  The cmaps itselves are */
1032   /*    loaded on demand in the `ttcmap.c' module.                         */
1033   /*                                                                       */
1034   /* <Input>                                                               */
1035   /*    face   :: A handle to the target face object.                      */
1036   /*    stream :: A handle to the input stream.                            */
1037   /*                                                                       */
1038   /* <Return>                                                              */
1039   /*    FreeType error code.  0 means success.                             */
1040   /*                                                                       */
1041   LOCAL_FUNC
1042   FT_Error  TT_Load_CMap( TT_Face    face,
1043                           FT_Stream  stream )
1044   {
1045     FT_Error    error;
1046     FT_Memory   memory = stream->memory;
1047     FT_Long     table_start;
1048     TT_CMapDir  cmap_dir;
1049
1050     const FT_Frame_Field  cmap_fields[] =
1051     {
1052       FT_FRAME_START( 4 ),
1053         FT_FRAME_USHORT( TT_CMapDir, tableVersionNumber ),
1054         FT_FRAME_USHORT( TT_CMapDir, numCMaps ),
1055       FT_FRAME_END
1056     };
1057
1058     const FT_Frame_Field  cmap_rec_fields[] =
1059     {
1060       FT_FRAME_START( 6 ),
1061         FT_FRAME_USHORT( TT_CMapTable, format ),
1062         FT_FRAME_USHORT( TT_CMapTable, length ),
1063         FT_FRAME_USHORT( TT_CMapTable, version ),
1064       FT_FRAME_END
1065     };
1066
1067
1068     FT_TRACE2(( "CMaps " ));
1069
1070     error = face->goto_table( face, TTAG_cmap, stream, 0 );
1071     if ( error )
1072     {
1073       error = TT_Err_CMap_Table_Missing;
1074       goto Exit;
1075     }
1076
1077     table_start = FILE_Pos();
1078
1079     if ( READ_Fields( cmap_fields, &cmap_dir ) )
1080       goto Exit;
1081
1082     /* reserve space in face table for cmap tables */
1083     if ( ALLOC_ARRAY( face->charmaps,
1084                       cmap_dir.numCMaps,
1085                       TT_CharMapRec ) )
1086       goto Exit;
1087
1088     face->num_charmaps = cmap_dir.numCMaps;
1089     {
1090       TT_CharMap  charmap = face->charmaps;
1091       TT_CharMap  limit   = charmap + face->num_charmaps;
1092
1093
1094       /* read the header of each charmap first */
1095       if ( ACCESS_Frame( face->num_charmaps * 8L ) )
1096         goto Exit;
1097
1098       for ( ; charmap < limit; charmap++ )
1099       {
1100         TT_CMapTable*  cmap;
1101
1102
1103         charmap->root.face = (FT_Face)face;
1104         cmap               = &charmap->cmap;
1105
1106         cmap->loaded             = FALSE;
1107         cmap->platformID         = GET_UShort();
1108         cmap->platformEncodingID = GET_UShort();
1109         cmap->offset             = (FT_ULong)GET_Long();
1110       }
1111
1112       FORGET_Frame();
1113
1114       /* now read the rest of each table */
1115       for ( charmap = face->charmaps; charmap < limit; charmap++ )
1116       {
1117         TT_CMapTable* cmap = &charmap->cmap;
1118
1119
1120         if ( FILE_Seek( table_start + (FT_Long)cmap->offset ) ||
1121              READ_Fields( cmap_rec_fields, cmap )             )
1122           goto Exit;
1123
1124         cmap->offset = FILE_Pos();
1125       }
1126     }
1127
1128     FT_TRACE2(( "loaded\n" ));
1129
1130   Exit:
1131     return error;
1132   }
1133
1134
1135   /*************************************************************************/
1136   /*                                                                       */
1137   /* <Function>                                                            */
1138   /*    TT_Load_OS2                                                        */
1139   /*                                                                       */
1140   /* <Description>                                                         */
1141   /*    Loads the OS2 table.                                               */
1142   /*                                                                       */
1143   /* <Input>                                                               */
1144   /*    face   :: A handle to the target face object.                      */
1145   /*    stream :: A handle to the input stream.                            */
1146   /*                                                                       */
1147   /* <Return>                                                              */
1148   /*    FreeType error code.  0 means success.                             */
1149   /*                                                                       */
1150   LOCAL_FUNC
1151   FT_Error  TT_Load_OS2( TT_Face    face,
1152                          FT_Stream  stream )
1153   {
1154     FT_Error  error;
1155     TT_OS2*   os2;
1156
1157     const FT_Frame_Field  os2_fields[] =
1158     {
1159       FT_FRAME_START( 78 ),
1160         FT_FRAME_USHORT( TT_OS2, version ),
1161         FT_FRAME_SHORT(  TT_OS2, xAvgCharWidth ),
1162         FT_FRAME_USHORT( TT_OS2, usWeightClass ),
1163         FT_FRAME_USHORT( TT_OS2, usWidthClass ),
1164         FT_FRAME_SHORT(  TT_OS2, fsType ),
1165         FT_FRAME_SHORT(  TT_OS2, ySubscriptXSize ),
1166         FT_FRAME_SHORT(  TT_OS2, ySubscriptYSize ),
1167         FT_FRAME_SHORT(  TT_OS2, ySubscriptXOffset ),
1168         FT_FRAME_SHORT(  TT_OS2, ySubscriptYOffset ),
1169         FT_FRAME_SHORT(  TT_OS2, ySuperscriptXSize ),
1170         FT_FRAME_SHORT(  TT_OS2, ySuperscriptYSize ),
1171         FT_FRAME_SHORT(  TT_OS2, ySuperscriptXOffset ),
1172         FT_FRAME_SHORT(  TT_OS2, ySuperscriptYOffset ),
1173         FT_FRAME_SHORT(  TT_OS2, yStrikeoutSize ),
1174         FT_FRAME_SHORT(  TT_OS2, yStrikeoutPosition ),
1175         FT_FRAME_SHORT(  TT_OS2, sFamilyClass ),
1176         FT_FRAME_BYTE(   TT_OS2, panose[0] ),
1177         FT_FRAME_BYTE(   TT_OS2, panose[1] ),
1178         FT_FRAME_BYTE(   TT_OS2, panose[2] ),
1179         FT_FRAME_BYTE(   TT_OS2, panose[3] ),
1180         FT_FRAME_BYTE(   TT_OS2, panose[4] ),
1181         FT_FRAME_BYTE(   TT_OS2, panose[5] ),
1182         FT_FRAME_BYTE(   TT_OS2, panose[6] ),
1183         FT_FRAME_BYTE(   TT_OS2, panose[7] ),
1184         FT_FRAME_BYTE(   TT_OS2, panose[8] ),
1185         FT_FRAME_BYTE(   TT_OS2, panose[9] ),
1186         FT_FRAME_ULONG(  TT_OS2, ulUnicodeRange1 ),
1187         FT_FRAME_ULONG(  TT_OS2, ulUnicodeRange2 ),
1188         FT_FRAME_ULONG(  TT_OS2, ulUnicodeRange3 ),
1189         FT_FRAME_ULONG(  TT_OS2, ulUnicodeRange4 ),
1190         FT_FRAME_BYTE(   TT_OS2, achVendID[0] ),
1191         FT_FRAME_BYTE(   TT_OS2, achVendID[1] ),
1192         FT_FRAME_BYTE(   TT_OS2, achVendID[2] ),
1193         FT_FRAME_BYTE(   TT_OS2, achVendID[3] ),
1194
1195         FT_FRAME_USHORT( TT_OS2, fsSelection ),
1196         FT_FRAME_USHORT( TT_OS2, usFirstCharIndex ),
1197         FT_FRAME_USHORT( TT_OS2, usLastCharIndex ),
1198         FT_FRAME_SHORT(  TT_OS2, sTypoAscender ),
1199         FT_FRAME_SHORT(  TT_OS2, sTypoDescender ),
1200         FT_FRAME_SHORT(  TT_OS2, sTypoLineGap ),
1201         FT_FRAME_USHORT( TT_OS2, usWinAscent ),
1202         FT_FRAME_USHORT( TT_OS2, usWinDescent ),
1203       FT_FRAME_END
1204     };
1205
1206     const FT_Frame_Field  os2_fields_extra[] =
1207     {
1208       FT_FRAME_START( 8 ),
1209         FT_FRAME_ULONG( TT_OS2, ulCodePageRange1 ),
1210         FT_FRAME_ULONG( TT_OS2, ulCodePageRange2 ),
1211       FT_FRAME_END
1212     };
1213
1214     const FT_Frame_Field  os2_fields_extra2[] =
1215     {
1216       FT_FRAME_START( 10 ),
1217         FT_FRAME_SHORT( TT_OS2,  sxHeight ),
1218         FT_FRAME_SHORT( TT_OS2,  sCapHeight ),
1219         FT_FRAME_USHORT( TT_OS2, usDefaultChar ),
1220         FT_FRAME_USHORT( TT_OS2, usBreakChar ),
1221         FT_FRAME_USHORT( TT_OS2, usMaxContext ),
1222       FT_FRAME_END
1223     };
1224
1225
1226     FT_TRACE2(( "OS/2 Table " ));
1227
1228     /* We now support old Mac fonts where the OS/2 table doesn't  */
1229     /* exist.  Simply put, we set the `version' field to 0xFFFF   */
1230     /* and test this value each time we need to access the table. */
1231     error = face->goto_table( face, TTAG_OS2, stream, 0 );
1232     if ( error )
1233     {
1234       FT_TRACE2(( "is missing!\n" ));
1235       face->os2.version = 0xFFFF;
1236       error = TT_Err_Ok;
1237       goto Exit;
1238     }
1239
1240     os2 = &face->os2;
1241
1242     if ( READ_Fields( os2_fields, os2 ) )
1243       goto Exit;
1244
1245     os2->ulCodePageRange1 = 0;
1246     os2->ulCodePageRange2 = 0;
1247
1248     if ( os2->version >= 0x0001 )
1249     {
1250       /* only version 1 tables */
1251       if ( READ_Fields( os2_fields_extra, os2 ) )
1252         goto Exit;
1253
1254       if ( os2->version >= 0x0002 )
1255       {
1256         /* only version 2 tables */
1257         if ( READ_Fields( os2_fields_extra2, os2 ) )
1258           goto Exit;
1259       }
1260     }
1261
1262     FT_TRACE2(( "loaded\n" ));
1263
1264   Exit:
1265     return error;
1266   }
1267
1268
1269   /*************************************************************************/
1270   /*                                                                       */
1271   /* <Function>                                                            */
1272   /*    TT_Load_Postscript                                                 */
1273   /*                                                                       */
1274   /* <Description>                                                         */
1275   /*    Loads the Postscript table.                                        */
1276   /*                                                                       */
1277   /* <Input>                                                               */
1278   /*    face   :: A handle to the target face object.                      */
1279   /*    stream :: A handle to the input stream.                            */
1280   /*                                                                       */
1281   /* <Return>                                                              */
1282   /*    FreeType error code.  0 means success.                             */
1283   /*                                                                       */
1284   LOCAL_FUNC
1285   FT_Error  TT_Load_PostScript( TT_Face    face,
1286                                 FT_Stream  stream )
1287   {
1288     FT_Error        error;
1289     TT_Postscript*  post = &face->postscript;
1290
1291     static const FT_Frame_Field  post_fields[] =
1292     {
1293       FT_FRAME_START( 32 ),
1294         FT_FRAME_ULONG( TT_Postscript, FormatType ),
1295         FT_FRAME_ULONG( TT_Postscript, italicAngle ),
1296         FT_FRAME_SHORT( TT_Postscript, underlinePosition ),
1297         FT_FRAME_SHORT( TT_Postscript, underlineThickness ),
1298         FT_FRAME_ULONG( TT_Postscript, isFixedPitch ),
1299         FT_FRAME_ULONG( TT_Postscript, minMemType42 ),
1300         FT_FRAME_ULONG( TT_Postscript, maxMemType42 ),
1301         FT_FRAME_ULONG( TT_Postscript, minMemType1 ),
1302         FT_FRAME_ULONG( TT_Postscript, maxMemType1 ),
1303       FT_FRAME_END
1304     };
1305
1306
1307     FT_TRACE2(( "PostScript " ));
1308
1309     error = face->goto_table( face, TTAG_post, stream, 0 );
1310     if ( error )
1311       return TT_Err_Post_Table_Missing;
1312
1313     if ( READ_Fields( post_fields, post ) )
1314       return error;
1315
1316     /* we don't load the glyph names, we do that in another */
1317     /* module (ttpost).                                     */
1318     FT_TRACE2(( "loaded\n" ));
1319
1320     return TT_Err_Ok;
1321   }
1322
1323
1324   /*************************************************************************/
1325   /*                                                                       */
1326   /* <Function>                                                            */
1327   /*    TT_Load_PCLT                                                       */
1328   /*                                                                       */
1329   /* <Description>                                                         */
1330   /*    Loads the PCL 5 Table.                                             */
1331   /*                                                                       */
1332   /* <Input>                                                               */
1333   /*    face   :: A handle to the target face object.                      */
1334   /*    stream :: A handle to the input stream.                            */
1335   /*                                                                       */
1336   /* <Return>                                                              */
1337   /*    FreeType error code.  0 means success.                             */
1338   /*                                                                       */
1339   LOCAL_FUNC
1340   FT_Error  TT_Load_PCLT( TT_Face    face,
1341                           FT_Stream  stream )
1342   {
1343     static const FT_Frame_Field  pclt_fields[] =
1344     {
1345       FT_FRAME_START( 54 ),
1346         FT_FRAME_ULONG ( TT_PCLT, Version ),
1347         FT_FRAME_ULONG ( TT_PCLT, FontNumber ),
1348         FT_FRAME_USHORT( TT_PCLT, Pitch ),
1349         FT_FRAME_USHORT( TT_PCLT, xHeight ),
1350         FT_FRAME_USHORT( TT_PCLT, Style ),
1351         FT_FRAME_USHORT( TT_PCLT, TypeFamily ),
1352         FT_FRAME_USHORT( TT_PCLT, CapHeight ),
1353         FT_FRAME_BYTES ( TT_PCLT, TypeFace, 16 ),
1354         FT_FRAME_BYTES ( TT_PCLT, CharacterComplement, 8 ),
1355         FT_FRAME_BYTES ( TT_PCLT, FileName, 6 ),
1356         FT_FRAME_CHAR  ( TT_PCLT, StrokeWeight ),
1357         FT_FRAME_CHAR  ( TT_PCLT, WidthType ),
1358         FT_FRAME_BYTE  ( TT_PCLT, SerifStyle ),
1359         FT_FRAME_BYTE  ( TT_PCLT, Reserved ),
1360       FT_FRAME_END
1361     };
1362
1363     FT_Error  error;
1364     TT_PCLT*  pclt = &face->pclt;
1365
1366
1367     FT_TRACE2(( "PCLT " ));
1368
1369     /* optional table */
1370     error = face->goto_table( face, TTAG_PCLT, stream, 0 );
1371     if ( error )
1372     {
1373       FT_TRACE2(( "missing (optional)\n" ));
1374       pclt->Version = 0;
1375       return TT_Err_Ok;
1376     }
1377
1378     if ( READ_Fields( pclt_fields, pclt ) )
1379       goto Exit;
1380
1381     FT_TRACE2(( "loaded\n" ));
1382
1383   Exit:
1384     return error;
1385   }
1386
1387
1388   /*************************************************************************/
1389   /*                                                                       */
1390   /* <Function>                                                            */
1391   /*    TT_Load_Gasp                                                       */
1392   /*                                                                       */
1393   /* <Description>                                                         */
1394   /*    Loads the `gasp' table into a face object.                         */
1395   /*                                                                       */
1396   /* <Input>                                                               */
1397   /*    face   :: A handle to the target face object.                      */
1398   /*    stream :: The input stream.                                        */
1399   /*                                                                       */
1400   /* <Return>                                                              */
1401   /*    FreeType error code.  0 means success.                             */
1402   /*                                                                       */
1403   LOCAL_FUNC
1404   FT_Error  TT_Load_Gasp( TT_Face    face,
1405                           FT_Stream  stream )
1406   {
1407     FT_Error   error;
1408     FT_Memory  memory = stream->memory;
1409
1410     FT_UInt        j,num_ranges;
1411     TT_GaspRange*  gaspranges;
1412
1413
1414     FT_TRACE2(( "TT_Load_Gasp: %08p\n", face ));
1415
1416     /* the gasp table is optional */
1417     error = face->goto_table( face, TTAG_gasp, stream, 0 );
1418     if ( error )
1419       return TT_Err_Ok;
1420
1421     if ( ACCESS_Frame( 4L ) )
1422       goto Exit;
1423
1424     face->gasp.version   = GET_UShort();
1425     face->gasp.numRanges = GET_UShort();
1426
1427     FORGET_Frame();
1428
1429     num_ranges = face->gasp.numRanges;
1430     FT_TRACE3(( "number of ranges = %d\n", num_ranges ));
1431
1432     if ( ALLOC_ARRAY( gaspranges, num_ranges, TT_GaspRange ) ||
1433          ACCESS_Frame( num_ranges * 4L )                     )
1434       goto Exit;
1435
1436     face->gasp.gaspRanges = gaspranges;
1437
1438     for ( j = 0; j < num_ranges; j++ )
1439     {
1440       gaspranges[j].maxPPEM  = GET_UShort();
1441       gaspranges[j].gaspFlag = GET_UShort();
1442
1443       FT_TRACE3(( " [max:%d flag:%d]",
1444                     gaspranges[j].maxPPEM,
1445                     gaspranges[j].gaspFlag ));
1446     }
1447     FT_TRACE3(( "\n" ));
1448
1449     FORGET_Frame();
1450     FT_TRACE2(( "GASP loaded\n" ));
1451
1452   Exit:
1453     return error;
1454   }
1455
1456
1457   /*************************************************************************/
1458   /*                                                                       */
1459   /* <Function>                                                            */
1460   /*    TT_Load_Kern                                                       */
1461   /*                                                                       */
1462   /* <Description>                                                         */
1463   /*    Loads the first kerning table with format 0 in the font.  Only     */
1464   /*    accepts the first horizontal kerning table.  Developers should use */
1465   /*    the `ftxkern' extension to access other kerning tables in the font */
1466   /*    file, if they really want to.                                      */
1467   /*                                                                       */
1468   /* <Input>                                                               */
1469   /*    face   :: A handle to the target face object.                      */
1470   /*    stream :: The input stream.                                        */
1471   /*                                                                       */
1472   /* <Return>                                                              */
1473   /*    FreeType error code.  0 means success.                             */
1474   /*                                                                       */
1475   LOCAL_FUNC
1476   FT_Error  TT_Load_Kern( TT_Face    face,
1477                           FT_Stream  stream )
1478   {
1479     FT_Error   error;
1480     FT_Memory  memory = stream->memory;
1481
1482     FT_UInt    n, num_tables, version;
1483
1484
1485     /* the kern table is optional; exit silently if it is missing */
1486     error = face->goto_table( face, TTAG_kern, stream, 0 );
1487     if ( error )
1488       return TT_Err_Ok;
1489
1490     if ( ACCESS_Frame( 4L ) )
1491       goto Exit;
1492
1493     version    = GET_UShort();
1494     num_tables = GET_UShort();
1495
1496     FORGET_Frame();
1497
1498     for ( n = 0; n < num_tables; n++ )
1499     {
1500       FT_UInt  coverage;
1501       FT_UInt  length;
1502
1503
1504       if ( ACCESS_Frame( 6L ) )
1505         goto Exit;
1506
1507       version  = GET_UShort();      /* version                 */
1508       length   = GET_UShort() - 6;  /* substract header length */
1509       coverage = GET_UShort();
1510
1511       FORGET_Frame();
1512
1513       if ( coverage == 0x0001 )
1514       {
1515         FT_UInt          num_pairs;
1516         TT_Kern_0_Pair*  pair;
1517         TT_Kern_0_Pair*  limit;
1518
1519
1520         /* found a horizontal format 0 kerning table! */
1521         if ( ACCESS_Frame( 8L ) )
1522           goto Exit;
1523
1524         num_pairs = GET_UShort();
1525
1526         /* skip the rest */
1527
1528         FORGET_Frame();
1529
1530         /* allocate array of kerning pairs */
1531         if ( ALLOC_ARRAY( face->kern_pairs, num_pairs, TT_Kern_0_Pair ) ||
1532              ACCESS_Frame( 6L * num_pairs )                             )
1533           goto Exit;
1534
1535         pair  = face->kern_pairs;
1536         limit = pair + num_pairs;
1537         for ( ; pair < limit; pair++ )
1538         {
1539           pair->left  = GET_UShort();
1540           pair->right = GET_UShort();
1541           pair->value = GET_UShort();
1542         }
1543
1544         FORGET_Frame();
1545
1546         face->num_kern_pairs   = num_pairs;
1547         face->kern_table_index = n;
1548         goto Exit;
1549       }
1550
1551       if ( FILE_Skip( length ) )
1552         goto Exit;
1553     }
1554
1555     /* no kern table found -- doesn't matter */
1556     face->kern_table_index = -1;
1557     face->num_kern_pairs   = 0;
1558     face->kern_pairs       = NULL;
1559
1560   Exit:
1561     return error;
1562   }
1563
1564
1565   /*************************************************************************/
1566   /*                                                                       */
1567   /* <Function>                                                            */
1568   /*    TT_Load_Hdmx                                                       */
1569   /*                                                                       */
1570   /* <Description>                                                         */
1571   /*    Loads the horizontal device metrics table.                         */
1572   /*                                                                       */
1573   /* <Input>                                                               */
1574   /*    face   :: A handle to the target face object.                      */
1575   /*    stream :: A handle to the input stream.                            */
1576   /*                                                                       */
1577   /* <Return>                                                              */
1578   /*    FreeType error code.  0 means success.                             */
1579   /*                                                                       */
1580   LOCAL_FUNC
1581   FT_Error  TT_Load_Hdmx( TT_Face    face,
1582                           FT_Stream  stream )
1583   {
1584     FT_Error  error;
1585     FT_Memory memory = stream->memory;
1586
1587     TT_Hdmx*  hdmx = &face->hdmx;
1588     FT_Long   num_glyphs;
1589     FT_Long   record_size;
1590
1591
1592     hdmx->version     = 0;
1593     hdmx->num_records = 0;
1594     hdmx->records     = 0;
1595
1596     /* this table is optional */
1597     error = face->goto_table( face, TTAG_hdmx, stream, 0 );
1598     if ( error )
1599       return TT_Err_Ok;
1600
1601     if ( ACCESS_Frame( 8L ) )
1602       goto Exit;
1603
1604     hdmx->version     = GET_UShort();
1605     hdmx->num_records = GET_Short();
1606     record_size       = GET_Long();
1607
1608     FORGET_Frame();
1609
1610     /* Only recognize format 0 */
1611     if ( hdmx->version != 0 )
1612       goto Exit;
1613
1614     if ( ALLOC_ARRAY( hdmx->records, hdmx->num_records, TT_HdmxRec ) )
1615       goto Exit;
1616
1617     num_glyphs   = face->root.num_glyphs;
1618     record_size -= num_glyphs + 2;
1619
1620     {
1621       TT_HdmxRec*  cur   = hdmx->records;
1622       TT_HdmxRec*  limit = cur + hdmx->num_records;
1623
1624
1625       for ( ; cur < limit; cur++ )
1626       {
1627         /* read record */
1628         if ( READ_Byte( cur->ppem      ) ||
1629              READ_Byte( cur->max_width ) )
1630           goto Exit;
1631
1632         if ( ALLOC( cur->widths, num_glyphs )     ||
1633              FILE_Read( cur->widths, num_glyphs ) )
1634           goto Exit;
1635
1636         /* skip padding bytes */
1637         if ( record_size > 0 && FILE_Skip( record_size ) )
1638             goto Exit;
1639       }
1640     }
1641
1642   Exit:
1643     return error;
1644   }
1645
1646
1647   /*************************************************************************/
1648   /*                                                                       */
1649   /* <Function>                                                            */
1650   /*    TT_Free_Hdmx                                                       */
1651   /*                                                                       */
1652   /* <Description>                                                         */
1653   /*    Frees the horizontal device metrics table.                         */
1654   /*                                                                       */
1655   /* <Input>                                                               */
1656   /*    face :: A handle to the target face object.                        */
1657   /*                                                                       */
1658   LOCAL_FUNC
1659   void  TT_Free_Hdmx( TT_Face  face )
1660   {
1661     if ( face )
1662     {
1663       FT_Int     n;
1664       FT_Memory  memory = face->root.driver->root.memory;
1665
1666
1667       for ( n = 0; n < face->hdmx.num_records; n++ )
1668         FREE( face->hdmx.records[n].widths );
1669
1670       FREE( face->hdmx.records );
1671       face->hdmx.num_records = 0;
1672     }
1673   }
1674
1675
1676 /* END */