Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  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-2010, 2012, 2013 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 <ft2build.h>
  21. #include FT_INTERNAL_DEBUG_H
  22. #include FT_INTERNAL_STREAM_H
  23. #include FT_TRUETYPE_TAGS_H
  24. #include "ttload.h"
  25.  
  26. #include "sferrors.h"
  27.  
  28.  
  29.   /*************************************************************************/
  30.   /*                                                                       */
  31.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  32.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  33.   /* messages during execution.                                            */
  34.   /*                                                                       */
  35. #undef  FT_COMPONENT
  36. #define FT_COMPONENT  trace_ttload
  37.  
  38.  
  39.   /*************************************************************************/
  40.   /*                                                                       */
  41.   /* <Function>                                                            */
  42.   /*    tt_face_lookup_table                                               */
  43.   /*                                                                       */
  44.   /* <Description>                                                         */
  45.   /*    Looks for a TrueType table by name.                                */
  46.   /*                                                                       */
  47.   /* <Input>                                                               */
  48.   /*    face :: A face object handle.                                      */
  49.   /*                                                                       */
  50.   /*    tag  :: The searched tag.                                          */
  51.   /*                                                                       */
  52.   /* <Return>                                                              */
  53.   /*    A pointer to the table directory entry.  0 if not found.           */
  54.   /*                                                                       */
  55.   FT_LOCAL_DEF( TT_Table  )
  56.   tt_face_lookup_table( TT_Face   face,
  57.                         FT_ULong  tag  )
  58.   {
  59.     TT_Table  entry;
  60.     TT_Table  limit;
  61. #ifdef FT_DEBUG_LEVEL_TRACE
  62.     FT_Bool   zero_length = FALSE;
  63. #endif
  64.  
  65.  
  66.     FT_TRACE4(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ",
  67.                 face,
  68.                 (FT_Char)( tag >> 24 ),
  69.                 (FT_Char)( tag >> 16 ),
  70.                 (FT_Char)( tag >> 8  ),
  71.                 (FT_Char)( tag       ) ));
  72.  
  73.     entry = face->dir_tables;
  74.     limit = entry + face->num_tables;
  75.  
  76.     for ( ; entry < limit; entry++ )
  77.     {
  78.       /* For compatibility with Windows, we consider    */
  79.       /* zero-length tables the same as missing tables. */
  80.       if ( entry->Tag == tag )
  81.       {
  82.         if ( entry->Length != 0 )
  83.         {
  84.           FT_TRACE4(( "found table.\n" ));
  85.           return entry;
  86.         }
  87. #ifdef FT_DEBUG_LEVEL_TRACE
  88.         zero_length = TRUE;
  89. #endif
  90.       }
  91.     }
  92.  
  93. #ifdef FT_DEBUG_LEVEL_TRACE
  94.     if ( zero_length )
  95.       FT_TRACE4(( "ignoring empty table\n" ));
  96.     else
  97.       FT_TRACE4(( "could not find table\n" ));
  98. #endif
  99.  
  100.     return NULL;
  101.   }
  102.  
  103.  
  104.   /*************************************************************************/
  105.   /*                                                                       */
  106.   /* <Function>                                                            */
  107.   /*    tt_face_goto_table                                                 */
  108.   /*                                                                       */
  109.   /* <Description>                                                         */
  110.   /*    Looks for a TrueType table by name, then seek a stream to it.      */
  111.   /*                                                                       */
  112.   /* <Input>                                                               */
  113.   /*    face   :: A face object handle.                                    */
  114.   /*                                                                       */
  115.   /*    tag    :: The searched tag.                                        */
  116.   /*                                                                       */
  117.   /*    stream :: The stream to seek when the table is found.              */
  118.   /*                                                                       */
  119.   /* <Output>                                                              */
  120.   /*    length :: The length of the table if found, undefined otherwise.   */
  121.   /*                                                                       */
  122.   /* <Return>                                                              */
  123.   /*    FreeType error code.  0 means success.                             */
  124.   /*                                                                       */
  125.   FT_LOCAL_DEF( FT_Error )
  126.   tt_face_goto_table( TT_Face    face,
  127.                       FT_ULong   tag,
  128.                       FT_Stream  stream,
  129.                       FT_ULong*  length )
  130.   {
  131.     TT_Table  table;
  132.     FT_Error  error;
  133.  
  134.  
  135.     table = tt_face_lookup_table( face, tag );
  136.     if ( table )
  137.     {
  138.       if ( length )
  139.         *length = table->Length;
  140.  
  141.       if ( FT_STREAM_SEEK( table->Offset ) )
  142.         goto Exit;
  143.     }
  144.     else
  145.       error = FT_THROW( Table_Missing );
  146.  
  147.   Exit:
  148.     return error;
  149.   }
  150.  
  151.  
  152.   /* Here, we                                                         */
  153.   /*                                                                  */
  154.   /* - check that `num_tables' is valid (and adjust it if necessary)  */
  155.   /*                                                                  */
  156.   /* - look for a `head' table, check its size, and parse it to check */
  157.   /*   whether its `magic' field is correctly set                     */
  158.   /*                                                                  */
  159.   /* - errors (except errors returned by stream handling)             */
  160.   /*                                                                  */
  161.   /*     SFNT_Err_Unknown_File_Format:                                */
  162.   /*       no table is defined in directory, it is not sfnt-wrapped   */
  163.   /*       data                                                       */
  164.   /*     SFNT_Err_Table_Missing:                                      */
  165.   /*       table directory is valid, but essential tables             */
  166.   /*       (head/bhed/SING) are missing                               */
  167.   /*                                                                  */
  168.   static FT_Error
  169.   check_table_dir( SFNT_Header  sfnt,
  170.                    FT_Stream    stream )
  171.   {
  172.     FT_Error   error;
  173.     FT_UShort  nn, valid_entries = 0;
  174.     FT_UInt    has_head = 0, has_sing = 0, has_meta = 0;
  175.     FT_ULong   offset = sfnt->offset + 12;
  176.  
  177.     static const FT_Frame_Field  table_dir_entry_fields[] =
  178.     {
  179. #undef  FT_STRUCTURE
  180. #define FT_STRUCTURE  TT_TableRec
  181.  
  182.       FT_FRAME_START( 16 ),
  183.         FT_FRAME_ULONG( Tag ),
  184.         FT_FRAME_ULONG( CheckSum ),
  185.         FT_FRAME_ULONG( Offset ),
  186.         FT_FRAME_ULONG( Length ),
  187.       FT_FRAME_END
  188.     };
  189.  
  190.  
  191.     if ( FT_STREAM_SEEK( offset ) )
  192.       goto Exit;
  193.  
  194.     for ( nn = 0; nn < sfnt->num_tables; nn++ )
  195.     {
  196.       TT_TableRec  table;
  197.  
  198.  
  199.       if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) )
  200.       {
  201.         nn--;
  202.         FT_TRACE2(( "check_table_dir:"
  203.                     " can read only %d table%s in font (instead of %d)\n",
  204.                     nn, nn == 1 ? "" : "s", sfnt->num_tables ));
  205.         sfnt->num_tables = nn;
  206.         break;
  207.       }
  208.  
  209.       /* we ignore invalid tables */
  210.       if ( table.Offset + table.Length > stream->size )
  211.       {
  212.         FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn ));
  213.         continue;
  214.       }
  215.       else
  216.         valid_entries++;
  217.  
  218.       if ( table.Tag == TTAG_head || table.Tag == TTAG_bhed )
  219.       {
  220.         FT_UInt32  magic;
  221.  
  222.  
  223. #ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
  224.         if ( table.Tag == TTAG_head )
  225. #endif
  226.           has_head = 1;
  227.  
  228.         /*
  229.          * The table length should be 0x36, but certain font tools make it
  230.          * 0x38, so we will just check that it is greater.
  231.          *
  232.          * Note that according to the specification, the table must be
  233.          * padded to 32-bit lengths, but this doesn't apply to the value of
  234.          * its `Length' field!
  235.          *
  236.          */
  237.         if ( table.Length < 0x36 )
  238.         {
  239.           FT_TRACE2(( "check_table_dir: `head' table too small\n" ));
  240.           error = FT_THROW( Table_Missing );
  241.           goto Exit;
  242.         }
  243.  
  244.         if ( FT_STREAM_SEEK( table.Offset + 12 ) ||
  245.              FT_READ_ULONG( magic )              )
  246.           goto Exit;
  247.  
  248.         if ( magic != 0x5F0F3CF5UL )
  249.         {
  250.           FT_TRACE2(( "check_table_dir:"
  251.                       " no magic number found in `head' table\n"));
  252.           error = FT_THROW( Table_Missing );
  253.           goto Exit;
  254.         }
  255.  
  256.         if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) )
  257.           goto Exit;
  258.       }
  259.       else if ( table.Tag == TTAG_SING )
  260.         has_sing = 1;
  261.       else if ( table.Tag == TTAG_META )
  262.         has_meta = 1;
  263.     }
  264.  
  265.     sfnt->num_tables = valid_entries;
  266.  
  267.     if ( sfnt->num_tables == 0 )
  268.     {
  269.       FT_TRACE2(( "check_table_dir: no tables found\n" ));
  270.       error = FT_THROW( Unknown_File_Format );
  271.       goto Exit;
  272.     }
  273.  
  274.     /* if `sing' and `meta' tables are present, there is no `head' table */
  275.     if ( has_head || ( has_sing && has_meta ) )
  276.     {
  277.       error = FT_Err_Ok;
  278.       goto Exit;
  279.     }
  280.     else
  281.     {
  282.       FT_TRACE2(( "check_table_dir:" ));
  283. #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
  284.       FT_TRACE2(( " neither `head', `bhed', nor `sing' table found\n" ));
  285. #else
  286.       FT_TRACE2(( " neither `head' nor `sing' table found\n" ));
  287. #endif
  288.       error = FT_THROW( Table_Missing );
  289.     }
  290.  
  291.   Exit:
  292.     return error;
  293.   }
  294.  
  295.  
  296.   /*************************************************************************/
  297.   /*                                                                       */
  298.   /* <Function>                                                            */
  299.   /*    tt_face_load_font_dir                                              */
  300.   /*                                                                       */
  301.   /* <Description>                                                         */
  302.   /*    Loads the header of a SFNT font file.                              */
  303.   /*                                                                       */
  304.   /* <Input>                                                               */
  305.   /*    face       :: A handle to the target face object.                  */
  306.   /*                                                                       */
  307.   /*    stream     :: The input stream.                                    */
  308.   /*                                                                       */
  309.   /* <Output>                                                              */
  310.   /*    sfnt       :: The SFNT header.                                     */
  311.   /*                                                                       */
  312.   /* <Return>                                                              */
  313.   /*    FreeType error code.  0 means success.                             */
  314.   /*                                                                       */
  315.   /* <Note>                                                                */
  316.   /*    The stream cursor must be at the beginning of the font directory.  */
  317.   /*                                                                       */
  318.   FT_LOCAL_DEF( FT_Error )
  319.   tt_face_load_font_dir( TT_Face    face,
  320.                          FT_Stream  stream )
  321.   {
  322.     SFNT_HeaderRec  sfnt;
  323.     FT_Error        error;
  324.     FT_Memory       memory = stream->memory;
  325.     TT_TableRec*    entry;
  326.     FT_Int          nn;
  327.  
  328.     static const FT_Frame_Field  offset_table_fields[] =
  329.     {
  330. #undef  FT_STRUCTURE
  331. #define FT_STRUCTURE  SFNT_HeaderRec
  332.  
  333.       FT_FRAME_START( 8 ),
  334.         FT_FRAME_USHORT( num_tables ),
  335.         FT_FRAME_USHORT( search_range ),
  336.         FT_FRAME_USHORT( entry_selector ),
  337.         FT_FRAME_USHORT( range_shift ),
  338.       FT_FRAME_END
  339.     };
  340.  
  341.  
  342.     FT_TRACE2(( "tt_face_load_font_dir: %08p\n", face ));
  343.  
  344.     /* read the offset table */
  345.  
  346.     sfnt.offset = FT_STREAM_POS();
  347.  
  348.     if ( FT_READ_ULONG( sfnt.format_tag )                    ||
  349.          FT_STREAM_READ_FIELDS( offset_table_fields, &sfnt ) )
  350.       goto Exit;
  351.  
  352.     /* many fonts don't have these fields set correctly */
  353. #if 0
  354.     if ( sfnt.search_range != 1 << ( sfnt.entry_selector + 4 )        ||
  355.          sfnt.search_range + sfnt.range_shift != sfnt.num_tables << 4 )
  356.       return FT_THROW( Unknown_File_Format );
  357. #endif
  358.  
  359.     /* load the table directory */
  360.  
  361.     FT_TRACE2(( "-- Number of tables: %10u\n",    sfnt.num_tables ));
  362.     FT_TRACE2(( "-- Format version:   0x%08lx\n", sfnt.format_tag ));
  363.  
  364.     if ( sfnt.format_tag != TTAG_OTTO )
  365.     {
  366.       /* check first */
  367.       error = check_table_dir( &sfnt, stream );
  368.       if ( error )
  369.       {
  370.         FT_TRACE2(( "tt_face_load_font_dir:"
  371.                     " invalid table directory for TrueType\n" ));
  372.  
  373.         goto Exit;
  374.       }
  375.     }
  376.  
  377.     face->num_tables = sfnt.num_tables;
  378.     face->format_tag = sfnt.format_tag;
  379.  
  380.     if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) )
  381.       goto Exit;
  382.  
  383.     if ( FT_STREAM_SEEK( sfnt.offset + 12 )       ||
  384.          FT_FRAME_ENTER( face->num_tables * 16L ) )
  385.       goto Exit;
  386.  
  387.     entry = face->dir_tables;
  388.  
  389.     FT_TRACE2(( "\n"
  390.                 "  tag    offset    length   checksum\n"
  391.                 "  ----------------------------------\n" ));
  392.  
  393.     for ( nn = 0; nn < sfnt.num_tables; nn++ )
  394.     {
  395.       entry->Tag      = FT_GET_TAG4();
  396.       entry->CheckSum = FT_GET_ULONG();
  397.       entry->Offset   = FT_GET_LONG();
  398.       entry->Length   = FT_GET_LONG();
  399.  
  400.       /* ignore invalid tables */
  401.       if ( entry->Offset + entry->Length > stream->size )
  402.         continue;
  403.       else
  404.       {
  405.         FT_TRACE2(( "  %c%c%c%c  %08lx  %08lx  %08lx\n",
  406.                     (FT_Char)( entry->Tag >> 24 ),
  407.                     (FT_Char)( entry->Tag >> 16 ),
  408.                     (FT_Char)( entry->Tag >> 8  ),
  409.                     (FT_Char)( entry->Tag       ),
  410.                     entry->Offset,
  411.                     entry->Length,
  412.                     entry->CheckSum ));
  413.         entry++;
  414.       }
  415.     }
  416.  
  417.     FT_FRAME_EXIT();
  418.  
  419.     FT_TRACE2(( "table directory loaded\n\n" ));
  420.  
  421.   Exit:
  422.     return error;
  423.   }
  424.  
  425.  
  426.   /*************************************************************************/
  427.   /*                                                                       */
  428.   /* <Function>                                                            */
  429.   /*    tt_face_load_any                                                   */
  430.   /*                                                                       */
  431.   /* <Description>                                                         */
  432.   /*    Loads any font table into client memory.                           */
  433.   /*                                                                       */
  434.   /* <Input>                                                               */
  435.   /*    face   :: The face object to look for.                             */
  436.   /*                                                                       */
  437.   /*    tag    :: The tag of table to load.  Use the value 0 if you want   */
  438.   /*              to access the whole font file, else set this parameter   */
  439.   /*              to a valid TrueType table tag that you can forge with    */
  440.   /*              the MAKE_TT_TAG macro.                                   */
  441.   /*                                                                       */
  442.   /*    offset :: The starting offset in the table (or the file if         */
  443.   /*              tag == 0).                                               */
  444.   /*                                                                       */
  445.   /*    length :: The address of the decision variable:                    */
  446.   /*                                                                       */
  447.   /*                If length == NULL:                                     */
  448.   /*                  Loads the whole table.  Returns an error if          */
  449.   /*                  `offset' == 0!                                       */
  450.   /*                                                                       */
  451.   /*                If *length == 0:                                       */
  452.   /*                  Exits immediately; returning the length of the given */
  453.   /*                  table or of the font file, depending on the value of */
  454.   /*                  `tag'.                                               */
  455.   /*                                                                       */
  456.   /*                If *length != 0:                                       */
  457.   /*                  Loads the next `length' bytes of table or font,      */
  458.   /*                  starting at offset `offset' (in table or font too).  */
  459.   /*                                                                       */
  460.   /* <Output>                                                              */
  461.   /*    buffer :: The address of target buffer.                            */
  462.   /*                                                                       */
  463.   /* <Return>                                                              */
  464.   /*    FreeType error code.  0 means success.                             */
  465.   /*                                                                       */
  466.   FT_LOCAL_DEF( FT_Error )
  467.   tt_face_load_any( TT_Face    face,
  468.                     FT_ULong   tag,
  469.                     FT_Long    offset,
  470.                     FT_Byte*   buffer,
  471.                     FT_ULong*  length )
  472.   {
  473.     FT_Error   error;
  474.     FT_Stream  stream;
  475.     TT_Table   table;
  476.     FT_ULong   size;
  477.  
  478.  
  479.     if ( tag != 0 )
  480.     {
  481.       /* look for tag in font directory */
  482.       table = tt_face_lookup_table( face, tag );
  483.       if ( !table )
  484.       {
  485.         error = FT_THROW( Table_Missing );
  486.         goto Exit;
  487.       }
  488.  
  489.       offset += table->Offset;
  490.       size    = table->Length;
  491.     }
  492.     else
  493.       /* tag == 0 -- the user wants to access the font file directly */
  494.       size = face->root.stream->size;
  495.  
  496.     if ( length && *length == 0 )
  497.     {
  498.       *length = size;
  499.  
  500.       return FT_Err_Ok;
  501.     }
  502.  
  503.     if ( length )
  504.       size = *length;
  505.  
  506.     stream = face->root.stream;
  507.     /* the `if' is syntactic sugar for picky compilers */
  508.     if ( FT_STREAM_READ_AT( offset, buffer, size ) )
  509.       goto Exit;
  510.  
  511.   Exit:
  512.     return error;
  513.   }
  514.  
  515.  
  516.   /*************************************************************************/
  517.   /*                                                                       */
  518.   /* <Function>                                                            */
  519.   /*    tt_face_load_generic_header                                        */
  520.   /*                                                                       */
  521.   /* <Description>                                                         */
  522.   /*    Loads the TrueType table `head' or `bhed'.                         */
  523.   /*                                                                       */
  524.   /* <Input>                                                               */
  525.   /*    face   :: A handle to the target face object.                      */
  526.   /*                                                                       */
  527.   /*    stream :: The input stream.                                        */
  528.   /*                                                                       */
  529.   /* <Return>                                                              */
  530.   /*    FreeType error code.  0 means success.                             */
  531.   /*                                                                       */
  532.   static FT_Error
  533.   tt_face_load_generic_header( TT_Face    face,
  534.                                FT_Stream  stream,
  535.                                FT_ULong   tag )
  536.   {
  537.     FT_Error    error;
  538.     TT_Header*  header;
  539.  
  540.     static const FT_Frame_Field  header_fields[] =
  541.     {
  542. #undef  FT_STRUCTURE
  543. #define FT_STRUCTURE  TT_Header
  544.  
  545.       FT_FRAME_START( 54 ),
  546.         FT_FRAME_ULONG ( Table_Version ),
  547.         FT_FRAME_ULONG ( Font_Revision ),
  548.         FT_FRAME_LONG  ( CheckSum_Adjust ),
  549.         FT_FRAME_LONG  ( Magic_Number ),
  550.         FT_FRAME_USHORT( Flags ),
  551.         FT_FRAME_USHORT( Units_Per_EM ),
  552.         FT_FRAME_LONG  ( Created[0] ),
  553.         FT_FRAME_LONG  ( Created[1] ),
  554.         FT_FRAME_LONG  ( Modified[0] ),
  555.         FT_FRAME_LONG  ( Modified[1] ),
  556.         FT_FRAME_SHORT ( xMin ),
  557.         FT_FRAME_SHORT ( yMin ),
  558.         FT_FRAME_SHORT ( xMax ),
  559.         FT_FRAME_SHORT ( yMax ),
  560.         FT_FRAME_USHORT( Mac_Style ),
  561.         FT_FRAME_USHORT( Lowest_Rec_PPEM ),
  562.         FT_FRAME_SHORT ( Font_Direction ),
  563.         FT_FRAME_SHORT ( Index_To_Loc_Format ),
  564.         FT_FRAME_SHORT ( Glyph_Data_Format ),
  565.       FT_FRAME_END
  566.     };
  567.  
  568.  
  569.     error = face->goto_table( face, tag, stream, 0 );
  570.     if ( error )
  571.       goto Exit;
  572.  
  573.     header = &face->header;
  574.  
  575.     if ( FT_STREAM_READ_FIELDS( header_fields, header ) )
  576.       goto Exit;
  577.  
  578.     FT_TRACE3(( "Units per EM: %4u\n", header->Units_Per_EM ));
  579.     FT_TRACE3(( "IndexToLoc:   %4d\n", header->Index_To_Loc_Format ));
  580.  
  581.   Exit:
  582.     return error;
  583.   }
  584.  
  585.  
  586.   FT_LOCAL_DEF( FT_Error )
  587.   tt_face_load_head( TT_Face    face,
  588.                      FT_Stream  stream )
  589.   {
  590.     return tt_face_load_generic_header( face, stream, TTAG_head );
  591.   }
  592.  
  593.  
  594. #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
  595.  
  596.   FT_LOCAL_DEF( FT_Error )
  597.   tt_face_load_bhed( TT_Face    face,
  598.                      FT_Stream  stream )
  599.   {
  600.     return tt_face_load_generic_header( face, stream, TTAG_bhed );
  601.   }
  602.  
  603. #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
  604.  
  605.  
  606.   /*************************************************************************/
  607.   /*                                                                       */
  608.   /* <Function>                                                            */
  609.   /*    tt_face_load_max_profile                                           */
  610.   /*                                                                       */
  611.   /* <Description>                                                         */
  612.   /*    Loads the maximum profile into a face object.                      */
  613.   /*                                                                       */
  614.   /* <Input>                                                               */
  615.   /*    face   :: A handle to the target face object.                      */
  616.   /*                                                                       */
  617.   /*    stream :: The input stream.                                        */
  618.   /*                                                                       */
  619.   /* <Return>                                                              */
  620.   /*    FreeType error code.  0 means success.                             */
  621.   /*                                                                       */
  622.   FT_LOCAL_DEF( FT_Error )
  623.   tt_face_load_maxp( TT_Face    face,
  624.                      FT_Stream  stream )
  625.   {
  626.     FT_Error        error;
  627.     TT_MaxProfile*  maxProfile = &face->max_profile;
  628.  
  629.     static const FT_Frame_Field  maxp_fields[] =
  630.     {
  631. #undef  FT_STRUCTURE
  632. #define FT_STRUCTURE  TT_MaxProfile
  633.  
  634.       FT_FRAME_START( 6 ),
  635.         FT_FRAME_LONG  ( version ),
  636.         FT_FRAME_USHORT( numGlyphs ),
  637.       FT_FRAME_END
  638.     };
  639.  
  640.     static const FT_Frame_Field  maxp_fields_extra[] =
  641.     {
  642.       FT_FRAME_START( 26 ),
  643.         FT_FRAME_USHORT( maxPoints ),
  644.         FT_FRAME_USHORT( maxContours ),
  645.         FT_FRAME_USHORT( maxCompositePoints ),
  646.         FT_FRAME_USHORT( maxCompositeContours ),
  647.         FT_FRAME_USHORT( maxZones ),
  648.         FT_FRAME_USHORT( maxTwilightPoints ),
  649.         FT_FRAME_USHORT( maxStorage ),
  650.         FT_FRAME_USHORT( maxFunctionDefs ),
  651.         FT_FRAME_USHORT( maxInstructionDefs ),
  652.         FT_FRAME_USHORT( maxStackElements ),
  653.         FT_FRAME_USHORT( maxSizeOfInstructions ),
  654.         FT_FRAME_USHORT( maxComponentElements ),
  655.         FT_FRAME_USHORT( maxComponentDepth ),
  656.       FT_FRAME_END
  657.     };
  658.  
  659.  
  660.     error = face->goto_table( face, TTAG_maxp, stream, 0 );
  661.     if ( error )
  662.       goto Exit;
  663.  
  664.     if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) )
  665.       goto Exit;
  666.  
  667.     maxProfile->maxPoints             = 0;
  668.     maxProfile->maxContours           = 0;
  669.     maxProfile->maxCompositePoints    = 0;
  670.     maxProfile->maxCompositeContours  = 0;
  671.     maxProfile->maxZones              = 0;
  672.     maxProfile->maxTwilightPoints     = 0;
  673.     maxProfile->maxStorage            = 0;
  674.     maxProfile->maxFunctionDefs       = 0;
  675.     maxProfile->maxInstructionDefs    = 0;
  676.     maxProfile->maxStackElements      = 0;
  677.     maxProfile->maxSizeOfInstructions = 0;
  678.     maxProfile->maxComponentElements  = 0;
  679.     maxProfile->maxComponentDepth     = 0;
  680.  
  681.     if ( maxProfile->version >= 0x10000L )
  682.     {
  683.       if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) )
  684.         goto Exit;
  685.  
  686.       /* XXX: an adjustment that is necessary to load certain */
  687.       /*      broken fonts like `Keystrokes MT' :-(           */
  688.       /*                                                      */
  689.       /*   We allocate 64 function entries by default when    */
  690.       /*   the maxFunctionDefs value is smaller.              */
  691.  
  692.       if ( maxProfile->maxFunctionDefs < 64 )
  693.         maxProfile->maxFunctionDefs = 64;
  694.  
  695.       /* we add 4 phantom points later */
  696.       if ( maxProfile->maxTwilightPoints > ( 0xFFFFU - 4 ) )
  697.       {
  698.         FT_TRACE0(( "tt_face_load_maxp:"
  699.                     " too much twilight points in `maxp' table;\n"
  700.                     "                  "
  701.                     " some glyphs might be rendered incorrectly\n" ));
  702.  
  703.         maxProfile->maxTwilightPoints = 0xFFFFU - 4;
  704.       }
  705.  
  706.       /* we arbitrarily limit recursion to avoid stack exhaustion */
  707.       if ( maxProfile->maxComponentDepth > 100 )
  708.       {
  709.         FT_TRACE0(( "tt_face_load_maxp:"
  710.                     " abnormally large component depth (%d) set to 100\n",
  711.                     maxProfile->maxComponentDepth ));
  712.         maxProfile->maxComponentDepth = 100;
  713.       }
  714.     }
  715.  
  716.     FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs ));
  717.  
  718.   Exit:
  719.     return error;
  720.   }
  721.  
  722.  
  723.   /*************************************************************************/
  724.   /*                                                                       */
  725.   /* <Function>                                                            */
  726.   /*    tt_face_load_name                                                  */
  727.   /*                                                                       */
  728.   /* <Description>                                                         */
  729.   /*    Loads the name records.                                            */
  730.   /*                                                                       */
  731.   /* <Input>                                                               */
  732.   /*    face   :: A handle to the target face object.                      */
  733.   /*                                                                       */
  734.   /*    stream :: The input stream.                                        */
  735.   /*                                                                       */
  736.   /* <Return>                                                              */
  737.   /*    FreeType error code.  0 means success.                             */
  738.   /*                                                                       */
  739.   FT_LOCAL_DEF( FT_Error )
  740.   tt_face_load_name( TT_Face    face,
  741.                      FT_Stream  stream )
  742.   {
  743.     FT_Error      error;
  744.     FT_Memory     memory = stream->memory;
  745.     FT_ULong      table_pos, table_len;
  746.     FT_ULong      storage_start, storage_limit;
  747.     FT_UInt       count;
  748.     TT_NameTable  table;
  749.  
  750.     static const FT_Frame_Field  name_table_fields[] =
  751.     {
  752. #undef  FT_STRUCTURE
  753. #define FT_STRUCTURE  TT_NameTableRec
  754.  
  755.       FT_FRAME_START( 6 ),
  756.         FT_FRAME_USHORT( format ),
  757.         FT_FRAME_USHORT( numNameRecords ),
  758.         FT_FRAME_USHORT( storageOffset ),
  759.       FT_FRAME_END
  760.     };
  761.  
  762.     static const FT_Frame_Field  name_record_fields[] =
  763.     {
  764. #undef  FT_STRUCTURE
  765. #define FT_STRUCTURE  TT_NameEntryRec
  766.  
  767.       /* no FT_FRAME_START */
  768.         FT_FRAME_USHORT( platformID ),
  769.         FT_FRAME_USHORT( encodingID ),
  770.         FT_FRAME_USHORT( languageID ),
  771.         FT_FRAME_USHORT( nameID ),
  772.         FT_FRAME_USHORT( stringLength ),
  773.         FT_FRAME_USHORT( stringOffset ),
  774.       FT_FRAME_END
  775.     };
  776.  
  777.  
  778.     table         = &face->name_table;
  779.     table->stream = stream;
  780.  
  781.     error = face->goto_table( face, TTAG_name, stream, &table_len );
  782.     if ( error )
  783.       goto Exit;
  784.  
  785.     table_pos = FT_STREAM_POS();
  786.  
  787.  
  788.     if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) )
  789.       goto Exit;
  790.  
  791.     /* Some popular Asian fonts have an invalid `storageOffset' value   */
  792.     /* (it should be at least "6 + 12*num_names").  However, the string */
  793.     /* offsets, computed as "storageOffset + entry->stringOffset", are  */
  794.     /* valid pointers within the name table...                          */
  795.     /*                                                                  */
  796.     /* We thus can't check `storageOffset' right now.                   */
  797.     /*                                                                  */
  798.     storage_start = table_pos + 6 + 12*table->numNameRecords;
  799.     storage_limit = table_pos + table_len;
  800.  
  801.     if ( storage_start > storage_limit )
  802.     {
  803.       FT_ERROR(( "tt_face_load_name: invalid `name' table\n" ));
  804.       error = FT_THROW( Name_Table_Missing );
  805.       goto Exit;
  806.     }
  807.  
  808.     /* Allocate the array of name records. */
  809.     count                 = table->numNameRecords;
  810.     table->numNameRecords = 0;
  811.  
  812.     if ( FT_NEW_ARRAY( table->names, count ) ||
  813.          FT_FRAME_ENTER( count * 12 )        )
  814.       goto Exit;
  815.  
  816.     /* Load the name records and determine how much storage is needed */
  817.     /* to hold the strings themselves.                                */
  818.     {
  819.       TT_NameEntryRec*  entry = table->names;
  820.  
  821.  
  822.       for ( ; count > 0; count-- )
  823.       {
  824.         if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) )
  825.           continue;
  826.  
  827.         /* check that the name is not empty */
  828.         if ( entry->stringLength == 0 )
  829.           continue;
  830.  
  831.         /* check that the name string is within the table */
  832.         entry->stringOffset += table_pos + table->storageOffset;
  833.         if ( entry->stringOffset                       < storage_start ||
  834.              entry->stringOffset + entry->stringLength > storage_limit )
  835.         {
  836.           /* invalid entry - ignore it */
  837.           entry->stringOffset = 0;
  838.           entry->stringLength = 0;
  839.           continue;
  840.         }
  841.  
  842.         entry++;
  843.       }
  844.  
  845.       table->numNameRecords = (FT_UInt)( entry - table->names );
  846.     }
  847.  
  848.     FT_FRAME_EXIT();
  849.  
  850.     /* everything went well, update face->num_names */
  851.     face->num_names = (FT_UShort) table->numNameRecords;
  852.  
  853.   Exit:
  854.     return error;
  855.   }
  856.  
  857.  
  858.   /*************************************************************************/
  859.   /*                                                                       */
  860.   /* <Function>                                                            */
  861.   /*    tt_face_free_names                                                 */
  862.   /*                                                                       */
  863.   /* <Description>                                                         */
  864.   /*    Frees the name records.                                            */
  865.   /*                                                                       */
  866.   /* <Input>                                                               */
  867.   /*    face :: A handle to the target face object.                        */
  868.   /*                                                                       */
  869.   FT_LOCAL_DEF( void )
  870.   tt_face_free_name( TT_Face  face )
  871.   {
  872.     FT_Memory     memory = face->root.driver->root.memory;
  873.     TT_NameTable  table  = &face->name_table;
  874.     TT_NameEntry  entry  = table->names;
  875.     FT_UInt       count  = table->numNameRecords;
  876.  
  877.  
  878.     if ( table->names )
  879.     {
  880.       for ( ; count > 0; count--, entry++ )
  881.       {
  882.         FT_FREE( entry->string );
  883.         entry->stringLength = 0;
  884.       }
  885.  
  886.       /* free strings table */
  887.       FT_FREE( table->names );
  888.     }
  889.  
  890.     table->numNameRecords = 0;
  891.     table->format         = 0;
  892.     table->storageOffset  = 0;
  893.   }
  894.  
  895.  
  896.   /*************************************************************************/
  897.   /*                                                                       */
  898.   /* <Function>                                                            */
  899.   /*    tt_face_load_cmap                                                  */
  900.   /*                                                                       */
  901.   /* <Description>                                                         */
  902.   /*    Loads the cmap directory in a face object.  The cmaps themselves   */
  903.   /*    are loaded on demand in the `ttcmap.c' module.                     */
  904.   /*                                                                       */
  905.   /* <Input>                                                               */
  906.   /*    face   :: A handle to the target face object.                      */
  907.   /*                                                                       */
  908.   /*    stream :: A handle to the input stream.                            */
  909.   /*                                                                       */
  910.   /* <Return>                                                              */
  911.   /*    FreeType error code.  0 means success.                             */
  912.   /*                                                                       */
  913.  
  914.   FT_LOCAL_DEF( FT_Error )
  915.   tt_face_load_cmap( TT_Face    face,
  916.                      FT_Stream  stream )
  917.   {
  918.     FT_Error  error;
  919.  
  920.  
  921.     error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size );
  922.     if ( error )
  923.       goto Exit;
  924.  
  925.     if ( FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) )
  926.       face->cmap_size = 0;
  927.  
  928.   Exit:
  929.     return error;
  930.   }
  931.  
  932.  
  933.  
  934.   /*************************************************************************/
  935.   /*                                                                       */
  936.   /* <Function>                                                            */
  937.   /*    tt_face_load_os2                                                   */
  938.   /*                                                                       */
  939.   /* <Description>                                                         */
  940.   /*    Loads the OS2 table.                                               */
  941.   /*                                                                       */
  942.   /* <Input>                                                               */
  943.   /*    face   :: A handle to the target face object.                      */
  944.   /*                                                                       */
  945.   /*    stream :: A handle to the input stream.                            */
  946.   /*                                                                       */
  947.   /* <Return>                                                              */
  948.   /*    FreeType error code.  0 means success.                             */
  949.   /*                                                                       */
  950.   FT_LOCAL_DEF( FT_Error )
  951.   tt_face_load_os2( TT_Face    face,
  952.                     FT_Stream  stream )
  953.   {
  954.     FT_Error  error;
  955.     TT_OS2*   os2;
  956.  
  957.     static const FT_Frame_Field  os2_fields[] =
  958.     {
  959. #undef  FT_STRUCTURE
  960. #define FT_STRUCTURE  TT_OS2
  961.  
  962.       FT_FRAME_START( 78 ),
  963.         FT_FRAME_USHORT( version ),
  964.         FT_FRAME_SHORT ( xAvgCharWidth ),
  965.         FT_FRAME_USHORT( usWeightClass ),
  966.         FT_FRAME_USHORT( usWidthClass ),
  967.         FT_FRAME_SHORT ( fsType ),
  968.         FT_FRAME_SHORT ( ySubscriptXSize ),
  969.         FT_FRAME_SHORT ( ySubscriptYSize ),
  970.         FT_FRAME_SHORT ( ySubscriptXOffset ),
  971.         FT_FRAME_SHORT ( ySubscriptYOffset ),
  972.         FT_FRAME_SHORT ( ySuperscriptXSize ),
  973.         FT_FRAME_SHORT ( ySuperscriptYSize ),
  974.         FT_FRAME_SHORT ( ySuperscriptXOffset ),
  975.         FT_FRAME_SHORT ( ySuperscriptYOffset ),
  976.         FT_FRAME_SHORT ( yStrikeoutSize ),
  977.         FT_FRAME_SHORT ( yStrikeoutPosition ),
  978.         FT_FRAME_SHORT ( sFamilyClass ),
  979.         FT_FRAME_BYTE  ( panose[0] ),
  980.         FT_FRAME_BYTE  ( panose[1] ),
  981.         FT_FRAME_BYTE  ( panose[2] ),
  982.         FT_FRAME_BYTE  ( panose[3] ),
  983.         FT_FRAME_BYTE  ( panose[4] ),
  984.         FT_FRAME_BYTE  ( panose[5] ),
  985.         FT_FRAME_BYTE  ( panose[6] ),
  986.         FT_FRAME_BYTE  ( panose[7] ),
  987.         FT_FRAME_BYTE  ( panose[8] ),
  988.         FT_FRAME_BYTE  ( panose[9] ),
  989.         FT_FRAME_ULONG ( ulUnicodeRange1 ),
  990.         FT_FRAME_ULONG ( ulUnicodeRange2 ),
  991.         FT_FRAME_ULONG ( ulUnicodeRange3 ),
  992.         FT_FRAME_ULONG ( ulUnicodeRange4 ),
  993.         FT_FRAME_BYTE  ( achVendID[0] ),
  994.         FT_FRAME_BYTE  ( achVendID[1] ),
  995.         FT_FRAME_BYTE  ( achVendID[2] ),
  996.         FT_FRAME_BYTE  ( achVendID[3] ),
  997.  
  998.         FT_FRAME_USHORT( fsSelection ),
  999.         FT_FRAME_USHORT( usFirstCharIndex ),
  1000.         FT_FRAME_USHORT( usLastCharIndex ),
  1001.         FT_FRAME_SHORT ( sTypoAscender ),
  1002.         FT_FRAME_SHORT ( sTypoDescender ),
  1003.         FT_FRAME_SHORT ( sTypoLineGap ),
  1004.         FT_FRAME_USHORT( usWinAscent ),
  1005.         FT_FRAME_USHORT( usWinDescent ),
  1006.       FT_FRAME_END
  1007.     };
  1008.  
  1009.     static const FT_Frame_Field  os2_fields_extra[] =
  1010.     {
  1011.       FT_FRAME_START( 8 ),
  1012.         FT_FRAME_ULONG( ulCodePageRange1 ),
  1013.         FT_FRAME_ULONG( ulCodePageRange2 ),
  1014.       FT_FRAME_END
  1015.     };
  1016.  
  1017.     static const FT_Frame_Field  os2_fields_extra2[] =
  1018.     {
  1019.       FT_FRAME_START( 10 ),
  1020.         FT_FRAME_SHORT ( sxHeight ),
  1021.         FT_FRAME_SHORT ( sCapHeight ),
  1022.         FT_FRAME_USHORT( usDefaultChar ),
  1023.         FT_FRAME_USHORT( usBreakChar ),
  1024.         FT_FRAME_USHORT( usMaxContext ),
  1025.       FT_FRAME_END
  1026.     };
  1027.  
  1028.  
  1029.     /* We now support old Mac fonts where the OS/2 table doesn't  */
  1030.     /* exist.  Simply put, we set the `version' field to 0xFFFF   */
  1031.     /* and test this value each time we need to access the table. */
  1032.     error = face->goto_table( face, TTAG_OS2, stream, 0 );
  1033.     if ( error )
  1034.       goto Exit;
  1035.  
  1036.     os2 = &face->os2;
  1037.  
  1038.     if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) )
  1039.       goto Exit;
  1040.  
  1041.     os2->ulCodePageRange1 = 0;
  1042.     os2->ulCodePageRange2 = 0;
  1043.     os2->sxHeight         = 0;
  1044.     os2->sCapHeight       = 0;
  1045.     os2->usDefaultChar    = 0;
  1046.     os2->usBreakChar      = 0;
  1047.     os2->usMaxContext     = 0;
  1048.  
  1049.     if ( os2->version >= 0x0001 )
  1050.     {
  1051.       /* only version 1 tables */
  1052.       if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) )
  1053.         goto Exit;
  1054.  
  1055.       if ( os2->version >= 0x0002 )
  1056.       {
  1057.         /* only version 2 tables */
  1058.         if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) )
  1059.           goto Exit;
  1060.       }
  1061.     }
  1062.  
  1063.     FT_TRACE3(( "sTypoAscender:  %4d\n",   os2->sTypoAscender ));
  1064.     FT_TRACE3(( "sTypoDescender: %4d\n",   os2->sTypoDescender ));
  1065.     FT_TRACE3(( "usWinAscent:    %4u\n",   os2->usWinAscent ));
  1066.     FT_TRACE3(( "usWinDescent:   %4u\n",   os2->usWinDescent ));
  1067.     FT_TRACE3(( "fsSelection:    0x%2x\n", os2->fsSelection ));
  1068.  
  1069.   Exit:
  1070.     return error;
  1071.   }
  1072.  
  1073.  
  1074.   /*************************************************************************/
  1075.   /*                                                                       */
  1076.   /* <Function>                                                            */
  1077.   /*    tt_face_load_postscript                                            */
  1078.   /*                                                                       */
  1079.   /* <Description>                                                         */
  1080.   /*    Loads the Postscript table.                                        */
  1081.   /*                                                                       */
  1082.   /* <Input>                                                               */
  1083.   /*    face   :: A handle to the target face object.                      */
  1084.   /*                                                                       */
  1085.   /*    stream :: A handle to the input stream.                            */
  1086.   /*                                                                       */
  1087.   /* <Return>                                                              */
  1088.   /*    FreeType error code.  0 means success.                             */
  1089.   /*                                                                       */
  1090.   FT_LOCAL_DEF( FT_Error )
  1091.   tt_face_load_post( TT_Face    face,
  1092.                      FT_Stream  stream )
  1093.   {
  1094.     FT_Error        error;
  1095.     TT_Postscript*  post = &face->postscript;
  1096.  
  1097.     static const FT_Frame_Field  post_fields[] =
  1098.     {
  1099. #undef  FT_STRUCTURE
  1100. #define FT_STRUCTURE  TT_Postscript
  1101.  
  1102.       FT_FRAME_START( 32 ),
  1103.         FT_FRAME_ULONG( FormatType ),
  1104.         FT_FRAME_ULONG( italicAngle ),
  1105.         FT_FRAME_SHORT( underlinePosition ),
  1106.         FT_FRAME_SHORT( underlineThickness ),
  1107.         FT_FRAME_ULONG( isFixedPitch ),
  1108.         FT_FRAME_ULONG( minMemType42 ),
  1109.         FT_FRAME_ULONG( maxMemType42 ),
  1110.         FT_FRAME_ULONG( minMemType1 ),
  1111.         FT_FRAME_ULONG( maxMemType1 ),
  1112.       FT_FRAME_END
  1113.     };
  1114.  
  1115.  
  1116.     error = face->goto_table( face, TTAG_post, stream, 0 );
  1117.     if ( error )
  1118.       return error;
  1119.  
  1120.     if ( FT_STREAM_READ_FIELDS( post_fields, post ) )
  1121.       return error;
  1122.  
  1123.     /* we don't load the glyph names, we do that in another */
  1124.     /* module (ttpost).                                     */
  1125.  
  1126.     FT_TRACE3(( "FormatType:   0x%x\n", post->FormatType ));
  1127.     FT_TRACE3(( "isFixedPitch:   %s\n", post->isFixedPitch
  1128.                                         ? "  yes" : "   no" ));
  1129.  
  1130.     return FT_Err_Ok;
  1131.   }
  1132.  
  1133.  
  1134.   /*************************************************************************/
  1135.   /*                                                                       */
  1136.   /* <Function>                                                            */
  1137.   /*    tt_face_load_pclt                                                  */
  1138.   /*                                                                       */
  1139.   /* <Description>                                                         */
  1140.   /*    Loads the PCL 5 Table.                                             */
  1141.   /*                                                                       */
  1142.   /* <Input>                                                               */
  1143.   /*    face   :: A handle to the target face object.                      */
  1144.   /*                                                                       */
  1145.   /*    stream :: A handle to the input stream.                            */
  1146.   /*                                                                       */
  1147.   /* <Return>                                                              */
  1148.   /*    FreeType error code.  0 means success.                             */
  1149.   /*                                                                       */
  1150.   FT_LOCAL_DEF( FT_Error )
  1151.   tt_face_load_pclt( TT_Face    face,
  1152.                      FT_Stream  stream )
  1153.   {
  1154.     static const FT_Frame_Field  pclt_fields[] =
  1155.     {
  1156. #undef  FT_STRUCTURE
  1157. #define FT_STRUCTURE  TT_PCLT
  1158.  
  1159.       FT_FRAME_START( 54 ),
  1160.         FT_FRAME_ULONG ( Version ),
  1161.         FT_FRAME_ULONG ( FontNumber ),
  1162.         FT_FRAME_USHORT( Pitch ),
  1163.         FT_FRAME_USHORT( xHeight ),
  1164.         FT_FRAME_USHORT( Style ),
  1165.         FT_FRAME_USHORT( TypeFamily ),
  1166.         FT_FRAME_USHORT( CapHeight ),
  1167.         FT_FRAME_BYTES ( TypeFace, 16 ),
  1168.         FT_FRAME_BYTES ( CharacterComplement, 8 ),
  1169.         FT_FRAME_BYTES ( FileName, 6 ),
  1170.         FT_FRAME_CHAR  ( StrokeWeight ),
  1171.         FT_FRAME_CHAR  ( WidthType ),
  1172.         FT_FRAME_BYTE  ( SerifStyle ),
  1173.         FT_FRAME_BYTE  ( Reserved ),
  1174.       FT_FRAME_END
  1175.     };
  1176.  
  1177.     FT_Error  error;
  1178.     TT_PCLT*  pclt = &face->pclt;
  1179.  
  1180.  
  1181.     /* optional table */
  1182.     error = face->goto_table( face, TTAG_PCLT, stream, 0 );
  1183.     if ( error )
  1184.       goto Exit;
  1185.  
  1186.     if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) )
  1187.       goto Exit;
  1188.  
  1189.   Exit:
  1190.     return error;
  1191.   }
  1192.  
  1193.  
  1194.   /*************************************************************************/
  1195.   /*                                                                       */
  1196.   /* <Function>                                                            */
  1197.   /*    tt_face_load_gasp                                                  */
  1198.   /*                                                                       */
  1199.   /* <Description>                                                         */
  1200.   /*    Loads the `gasp' table into a face object.                         */
  1201.   /*                                                                       */
  1202.   /* <Input>                                                               */
  1203.   /*    face   :: A handle to the target face object.                      */
  1204.   /*                                                                       */
  1205.   /*    stream :: The input stream.                                        */
  1206.   /*                                                                       */
  1207.   /* <Return>                                                              */
  1208.   /*    FreeType error code.  0 means success.                             */
  1209.   /*                                                                       */
  1210.   FT_LOCAL_DEF( FT_Error )
  1211.   tt_face_load_gasp( TT_Face    face,
  1212.                      FT_Stream  stream )
  1213.   {
  1214.     FT_Error   error;
  1215.     FT_Memory  memory = stream->memory;
  1216.  
  1217.     FT_UInt        j,num_ranges;
  1218.     TT_GaspRange   gaspranges = NULL;
  1219.  
  1220.  
  1221.     /* the gasp table is optional */
  1222.     error = face->goto_table( face, TTAG_gasp, stream, 0 );
  1223.     if ( error )
  1224.       goto Exit;
  1225.  
  1226.     if ( FT_FRAME_ENTER( 4L ) )
  1227.       goto Exit;
  1228.  
  1229.     face->gasp.version   = FT_GET_USHORT();
  1230.     face->gasp.numRanges = FT_GET_USHORT();
  1231.  
  1232.     FT_FRAME_EXIT();
  1233.  
  1234.     /* only support versions 0 and 1 of the table */
  1235.     if ( face->gasp.version >= 2 )
  1236.     {
  1237.       face->gasp.numRanges = 0;
  1238.       error = FT_THROW( Invalid_Table );
  1239.       goto Exit;
  1240.     }
  1241.  
  1242.     num_ranges = face->gasp.numRanges;
  1243.     FT_TRACE3(( "numRanges: %u\n", num_ranges ));
  1244.  
  1245.     if ( FT_QNEW_ARRAY( face->gasp.gaspRanges, num_ranges ) ||
  1246.          FT_FRAME_ENTER( num_ranges * 4L )                  )
  1247.       goto Exit;
  1248.  
  1249.     gaspranges = face->gasp.gaspRanges;
  1250.  
  1251.     for ( j = 0; j < num_ranges; j++ )
  1252.     {
  1253.       gaspranges[j].maxPPEM  = FT_GET_USHORT();
  1254.       gaspranges[j].gaspFlag = FT_GET_USHORT();
  1255.  
  1256.       FT_TRACE3(( "gaspRange %d: rangeMaxPPEM %5d, rangeGaspBehavior 0x%x\n",
  1257.                   j,
  1258.                   gaspranges[j].maxPPEM,
  1259.                   gaspranges[j].gaspFlag ));
  1260.     }
  1261.  
  1262.     FT_FRAME_EXIT();
  1263.  
  1264.   Exit:
  1265.     return error;
  1266.   }
  1267.  
  1268.  
  1269. /* END */
  1270.