home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: SysTools / SysTools.zip / ft-beta.zip / freetype / lib / ttload.c < prev    next >
C/C++ Source or Header  |  1997-10-06  |  30KB  |  1,169 lines

  1. /*******************************************************************
  2.  *
  3.  *  ttload.c                                                    1.0
  4.  *
  5.  *    TrueType Tables Loader.                          
  6.  *
  7.  *  Copyright 1996, 1997 by
  8.  *  David Turner, Robert Wilhelm, and Werner Lemberg.
  9.  *
  10.  *  This file is part of the FreeType project, and may only be used
  11.  *  modified and distributed under the terms of the FreeType project
  12.  *  license, LICENSE.TXT. By continuing to use, modify or distribute
  13.  *  this file you indicate that you have read the license and
  14.  *  understand and accept it fully.
  15.  *
  16.  *
  17.  ******************************************************************/
  18.  
  19. #include "tttypes.h"
  20. #include "tterror.h"
  21. #include "ttcalc.h"
  22. #include "ttfile.h"
  23.  
  24. #include "tttables.h"
  25. #include "ttobjs.h"
  26.  
  27. #include "ttmemory.h"
  28. #include "tttags.h"
  29. #include "ttload.h"
  30.  
  31. /* In all functions, the stream is taken from the 'face' object */
  32. #define DEFINE_LOCALS           DEFINE_LOAD_LOCALS(face->stream)
  33. #define DEFINE_LOCALS_WO_FRAME  DEFINE_LOAD_LOCALS_WO_FRAME(face->stream)
  34.  
  35.  
  36. /*******************************************************************
  37.  *
  38.  *  Function    :  LookUp_TrueType_Table
  39.  *
  40.  *  Description :  Looks for a TrueType table by name.
  41.  *
  42.  *  Input  :  face   face table to look for
  43.  *            tag        searched tag
  44.  *
  45.  *  Output :  index of table if found, -1 otherwise.
  46.  *
  47.  ******************************************************************/
  48.  
  49.   Int  LookUp_TrueType_Table( PFace  face,
  50.                               Long   tag  )
  51.   {
  52.     Int i;
  53.  
  54.     for ( i = 0; i < face->numTables; i++ )
  55.       if ( face->dirTables[i].Tag == tag )
  56.         return i;
  57.  
  58.     return -1;
  59.   }
  60.  
  61.  
  62. /*******************************************************************
  63.  *
  64.  *  Function    :  Load_TrueType_Collection
  65.  *
  66.  *  Description :  Loads the TTC table directory into face table.
  67.  *
  68.  *  Input  :  face    face record to look for
  69.  *
  70.  *  Output :  error code.                            
  71.  *
  72.  ******************************************************************/
  73.  
  74.   static TT_Error  Load_TrueType_Collection( PFace  face )
  75.   {
  76.     DEFINE_LOCALS;
  77.  
  78.     Int n;
  79.  
  80.     if ( FILE_Seek   ( 0L ) ||
  81.          ACCESS_Frame( 12L ) )
  82.       return error;
  83.  
  84.     face->ttcHeader.Tag      = GET_Tag4();
  85.     face->ttcHeader.version  = GET_Long();
  86.     face->ttcHeader.DirCount = GET_Long();
  87.  
  88.     FORGET_Frame();
  89.  
  90.     if ( face->ttcHeader.Tag != TTAG_ttcf )
  91.     {
  92.       face->ttcHeader.Tag      = 0;
  93.       face->ttcHeader.version  = 0;
  94.       face->ttcHeader.DirCount = 0;
  95.  
  96.       face->ttcHeader.TableDirectory = NULL;
  97.  
  98.       return TT_Err_File_Is_Not_Collection;
  99.     }
  100.  
  101.     if ( ALLOC_ARRAY( face->ttcHeader.TableDirectory,
  102.                       face->ttcHeader.DirCount, 
  103.                       ULong )                         ||
  104.  
  105.          ACCESS_Frame( face->ttcHeader.DirCount * 4L ) )
  106.  
  107.       return error;
  108.  
  109.     for ( n = 0; n < face->ttcHeader.DirCount; n++ )
  110.       face->ttcHeader.TableDirectory[n] = GET_ULong();
  111.  
  112.     FORGET_Frame();
  113.  
  114.     return TT_Err_Ok;
  115.   }
  116.  
  117.  
  118. /*******************************************************************
  119.  *
  120.  *  Function    :  Load_TrueType_Directory
  121.  *
  122.  *  Description :  Loads the table directory into face table.
  123.  *
  124.  *  Input  :  face       face record to look for
  125.  *
  126.  *            faceIndex  the index of the TrueType font, when
  127.  *                       we're opening a collection.
  128.  *
  129.  *  Output :  SUCCESS on success. FAILURE on error.
  130.  *
  131.  ******************************************************************/
  132.  
  133.   TT_Error Load_TrueType_Directory( PFace face, int faceIndex )
  134.   {
  135.     DEFINE_LOCALS;
  136.  
  137.     Int       n, limit;
  138.     TTableDir tableDir;
  139.  
  140.  
  141.     DebugTrace(( "Directory " ));
  142.  
  143.     error = Load_TrueType_Collection( face );
  144.  
  145.     if ( error )
  146.     {
  147.       if ( error != TT_Err_File_Is_Not_Collection )
  148.         return error;
  149.  
  150.       /* the file isn't a collection, exit if we're asking */
  151.       /* for a collected font                              */
  152.       if ( faceIndex != 0 )
  153.         return error;
  154.  
  155.       /* Now skip to the beginning of the file */
  156.       if ( FILE_Seek( 0 ) )
  157.         return error;
  158.     }
  159.     else
  160.     {
  161.       /* The file is a collection. Check the font index */
  162.       if ( faceIndex < 0 || faceIndex >= face->ttcHeader.DirCount )
  163.         return TT_Err_Bad_Argument;
  164.  
  165.       /* select a TrueType font in the ttc file   */
  166.       if ( FILE_Seek( face->ttcHeader.TableDirectory[faceIndex] ) )
  167.         return error;
  168.     }
  169.  
  170.     if ( ACCESS_Frame( 12L ) )
  171.       return error;
  172.  
  173.     tableDir.version   = GET_Long();
  174.     tableDir.numTables = GET_UShort();
  175.  
  176.     tableDir.searchRange   = GET_UShort();
  177.     tableDir.entrySelector = GET_UShort();
  178.     tableDir.rangeShift    = GET_UShort();
  179.  
  180.     DebugTrace(( "Tables number : %12u\n", tableDir.numTables ));
  181.  
  182.     FORGET_Frame();
  183.  
  184.     /* Check that we have a 'sfnt' format there */
  185.  
  186.     if ( tableDir.version != 0x00010000 )
  187.       return TT_Err_Invalid_File_Format;
  188.  
  189.     face->numTables = tableDir.numTables;
  190.  
  191.     if ( ALLOC_ARRAY( face->dirTables,
  192.                       face->numTables, 
  193.                       TTableDirEntry ) )
  194.       return error;
  195.  
  196.     if ( ACCESS_Frame( face->numTables*16L ) )
  197.       return error;
  198.  
  199.     limit = face->numTables;
  200.     for ( n = 0; n < limit; n++ )
  201.     {                      /* loop through the tables and get all entries */
  202.       face->dirTables[n].Tag      = GET_Tag4();
  203.       face->dirTables[n].CheckSum = GET_ULong();
  204.       face->dirTables[n].Offset   = GET_Long();
  205.       face->dirTables[n].Length   = GET_Long();
  206.     }
  207.  
  208.     FORGET_Frame();
  209.  
  210.     DebugTrace(( "loaded\n" ));
  211.  
  212.     return TT_Err_Ok;
  213.   }
  214.  
  215.  
  216. /*******************************************************************
  217.  *
  218.  *  Function    :  Load_TrueType_MaxProfile
  219.  *
  220.  *  Description :  Loads the maxp table into face table.
  221.  *
  222.  *  Input  :  face     face table to look for
  223.  *
  224.  *  Output :  error code
  225.  *
  226.  ******************************************************************/
  227.  
  228.   TT_Error  Load_TrueType_MaxProfile( PFace  face )
  229.   {
  230.     DEFINE_LOCALS;
  231.  
  232.     Int          i;
  233.     PMaxProfile  maxProfile = &face->maxProfile;
  234.  
  235.     DebugTrace(( "MaxProfile " ));
  236.  
  237.     if ( ( i = LookUp_TrueType_Table( face, TTAG_maxp ) ) < 0 )
  238.       return TT_Err_Table_Missing;
  239.  
  240.     if ( FILE_Seek( face->dirTables[i].Offset ) )   /* seek to maxprofile */
  241.       return error;
  242.  
  243.     if ( ACCESS_Frame( 32L ) )  /* read into frame */
  244.       return error;
  245.  
  246.     /* read frame data into face table */
  247.     maxProfile->version = GET_ULong();
  248.  
  249.     maxProfile->numGlyphs             = GET_UShort();
  250.  
  251.     maxProfile->maxPoints             = GET_UShort();
  252.     maxProfile->maxContours           = GET_UShort();
  253.     maxProfile->maxCompositePoints    = GET_UShort();
  254.     maxProfile->maxCompositeContours  = GET_UShort();
  255.  
  256.     maxProfile->maxZones              = GET_UShort();
  257.     maxProfile->maxTwilightPoints     = GET_UShort();
  258.  
  259.     maxProfile->maxStorage            = GET_UShort();
  260.     maxProfile->maxFunctionDefs       = GET_UShort();
  261.     maxProfile->maxInstructionDefs    = GET_UShort();
  262.     maxProfile->maxStackElements      = GET_UShort();
  263.     maxProfile->maxSizeOfInstructions = GET_UShort();
  264.     maxProfile->maxComponentElements  = GET_UShort();
  265.     maxProfile->maxComponentDepth     = GET_UShort();
  266.  
  267.     FORGET_Frame();
  268.  
  269.     face->numGlyphs     = maxProfile->numGlyphs;
  270.  
  271.     face->maxPoints     = MAX( maxProfile->maxCompositePoints, 
  272.                                maxProfile->maxPoints );
  273.  
  274.     face->maxContours   = MAX( maxProfile->maxCompositeContours,
  275.                                maxProfile->maxContours );
  276.  
  277.     face->maxComponents = maxProfile->maxComponentElements +
  278.                           maxProfile->maxComponentDepth;
  279.  
  280.     DebugTrace(( "loaded\n" ));
  281.   
  282.     return TT_Err_Ok;
  283.   }
  284.  
  285.  
  286. /*******************************************************************
  287.  *
  288.  *  Function    :  Load_TrueType_Gasp
  289.  *
  290.  *  Description :  Load the TrueType Gasp table into the face
  291.  *                 table.
  292.  *
  293.  *  Input  :  face     face table to look for
  294.  *
  295.  *  Output :  error code
  296.  *
  297.  ******************************************************************/
  298.  
  299.   TT_Error  Load_TrueType_Gasp( PFace  face )
  300.   {
  301.     DEFINE_LOCALS;
  302.  
  303.     Int         i;
  304.     TGasp*      gas;
  305.     GaspRange*  gaspranges;
  306.  
  307.     DebugTrace(( "Gasp " ));
  308.  
  309.     if ( ( i = LookUp_TrueType_Table( face, TTAG_gasp ) ) < 0 )
  310.       return TT_Err_Ok; /* gasp table is not required */
  311.  
  312.     if ( FILE_Seek( face->dirTables[i].Offset ) ||
  313.          ACCESS_Frame( 4L ) )
  314.       return error;
  315.  
  316.     gas = &face->gasp;
  317.  
  318.     gas->version   = GET_UShort();
  319.     gas->numRanges = GET_UShort();
  320.  
  321.     FORGET_Frame();
  322.  
  323.     DebugTrace(( "numRanges=%d\n" ,gas->numRanges ));
  324.  
  325.     if ( ALLOC_ARRAY( gaspranges, gas->numRanges, GaspRange ) ||
  326.          ACCESS_Frame( gas->numRanges * 4L ) )
  327.       goto Fail;
  328.  
  329.     face->gasp.gaspRanges = gaspranges;
  330.  
  331.     for ( i = 0; i < gas->numRanges; i++ )
  332.     {
  333.       gaspranges[i].maxPPEM  = GET_UShort();
  334.       gaspranges[i].gaspFlag = GET_UShort();
  335.       DebugTrace(( "%d %d\n",
  336.                    gaspranges[i].maxPPEM, gaspranges[i].gaspFlag ));
  337.     }
  338.  
  339.     FORGET_Frame();
  340.  
  341.     return TT_Err_Ok;
  342.  
  343.   Fail:
  344.     FREE( gaspranges );
  345.     gas->numRanges = 0;
  346.     return error;
  347.   }
  348.  
  349.  
  350. /*******************************************************************
  351.  *
  352.  *  Function    :  Load_TrueType_Header
  353.  *
  354.  *  Description :  Load the TrueType header table into the face
  355.  *                 table.
  356.  *
  357.  *  Input  :  face     face table to look for
  358.  *
  359.  *  Output :  error code
  360.  *
  361.  ******************************************************************/
  362.  
  363.   TT_Error  Load_TrueType_Header( PFace  face )
  364.   {
  365.     DEFINE_LOCALS;
  366.  
  367.     Int         i;
  368.     TT_Header*  header;
  369.  
  370.     DebugTrace(( "Header " ));
  371.  
  372.     if ( ( i = LookUp_TrueType_Table( face, TTAG_head ) ) < 0 )
  373.       return TT_Err_Table_Missing;
  374.  
  375.     if ( FILE_Seek( face->dirTables[i].Offset ) ||
  376.          ACCESS_Frame( 54L ) )
  377.       return error;
  378.  
  379.     header = &face->fontHeader;
  380.  
  381.     header->Table_Version = GET_ULong();
  382.     header->Font_Revision = GET_ULong();
  383.  
  384.     header->CheckSum_Adjust = GET_Long();
  385.     header->Magic_Number    = GET_Long();
  386.  
  387.     header->Flags        = GET_UShort();
  388.     header->Units_Per_EM = GET_UShort();
  389.  
  390.     header->Created [0] = GET_Long();
  391.     header->Created [1] = GET_Long();
  392.     header->Modified[0] = GET_Long();
  393.     header->Modified[1] = GET_Long();
  394.  
  395.     header->xMin = GET_Short();
  396.     header->yMin = GET_Short();
  397.     header->xMax = GET_Short();
  398.     header->yMax = GET_Short();
  399.  
  400.     header->Mac_Style       = GET_UShort();
  401.     header->Lowest_Rec_PPEM = GET_UShort();
  402.  
  403.     header->Font_Direction      = GET_Short();
  404.     header->Index_To_Loc_Format = GET_Short();
  405.     header->Glyph_Data_Format   = GET_Short();
  406.  
  407.     DebugTrace(( "loaded\n" ));
  408.  
  409.     DebugTrace(( "Units per EM       : %12u\n", 
  410.                  face->fontHeader.Units_Per_EM ));
  411.  
  412.     DebugTrace(( "IndexToLocFormat   : %12d\n",
  413.                  face->fontHeader.Index_To_Loc_Format ));
  414.  
  415.     FORGET_Frame();
  416.  
  417.     return TT_Err_Ok;
  418.   }
  419.  
  420.  
  421. /*******************************************************************
  422.  *
  423.  *  Function    : Load_TrueType_Horizontal_Header
  424.  *
  425.  *  Description : Loads the hhea table into face table.
  426.  *
  427.  *  Input  :  face   face table to look for
  428.  *
  429.  *  Output :  error code
  430.  *
  431.  ******************************************************************/
  432.  
  433.   TT_Error  Load_TrueType_Horizontal_Header( PFace  face )
  434.   {
  435.     DEFINE_LOCALS;
  436.  
  437.     Int  i;
  438.  
  439.     TT_Horizontal_Header*  hheader;
  440.  
  441.     DebugTrace(( "Horizontal header " ));
  442.  
  443.     if ( ( i = LookUp_TrueType_Table( face, TTAG_hhea ) ) < 0 )
  444.       return TT_Err_Table_Missing;
  445.  
  446.     if ( FILE_Seek( face->dirTables[i].Offset ) ||
  447.          ACCESS_Frame( 36L ) )
  448.       return error;
  449.  
  450.     hheader = &face->horizontalHeader;
  451.  
  452.     hheader->Version   = GET_ULong();
  453.     hheader->Ascender  = GET_Short();
  454.     hheader->Descender = GET_Short();
  455.     hheader->Line_Gap  = GET_Short();
  456.  
  457.     hheader->advance_Width_Max = GET_UShort();
  458.  
  459.     hheader->min_Left_Side_Bearing  = GET_Short();
  460.     hheader->min_Right_Side_Bearing = GET_Short();
  461.     hheader->xMax_Extent            = GET_Short();
  462.     hheader->caret_Slope_Rise       = GET_Short();
  463.     hheader->caret_Slope_Run        = GET_Short();
  464.  
  465.     hheader->Reserved[0] = GET_Short();
  466.     hheader->Reserved[1] = GET_Short();
  467.     hheader->Reserved[2] = GET_Short();
  468.     hheader->Reserved[3] = GET_Short();
  469.     hheader->Reserved[4] = GET_Short();
  470.  
  471.     hheader->metric_Data_Format = GET_Short();
  472.     hheader->number_Of_HMetrics = GET_UShort();
  473.  
  474.     FORGET_Frame();
  475.  
  476.     DebugTrace(( "loaded\n" ));
  477.  
  478.     return TT_Err_Ok;
  479.   }
  480.  
  481.  
  482. /*******************************************************************
  483.  *
  484.  *  Function    :  Load_TrueType_Locations
  485.  *
  486.  *  Description :  Loads the location table into face table.
  487.  *
  488.  *  Input  :  face     face table to look for
  489.  *
  490.  *  Output :  error code
  491.  *
  492.  *  NOTES :
  493.  *
  494.  *    The Font Header *must* be loaded in the leading segment
  495.  *    calling this function.
  496.  *
  497.  ******************************************************************/
  498.  
  499.   TT_Error  Load_TrueType_Locations( PFace  face )
  500.   {
  501.     DEFINE_LOCALS;
  502.  
  503.     Int  n, limit, LongOffsets;
  504.  
  505.     DebugTrace(( "Locations " ));
  506.  
  507.     LongOffsets = face->fontHeader.Index_To_Loc_Format;
  508.  
  509.     if ( ( n = LookUp_TrueType_Table( face, TTAG_loca ) ) < 0 )
  510.       return TT_Err_Table_Missing;
  511.  
  512.     if ( FILE_Seek( face->dirTables[n].Offset ) )
  513.       return error;
  514.  
  515.     if ( LongOffsets != 0 )
  516.     {
  517.       face->numLocations =
  518.         (unsigned long)face->dirTables[n].Length >> 2;
  519.  
  520.       DebugTrace(( "( 32 bits offsets ) : %12d ",
  521.                    face->numLocations ));
  522.  
  523.       if ( ALLOC_ARRAY( face->glyphLocations,
  524.                         face->numLocations,
  525.                         Long ) )
  526.         return error;
  527.  
  528.       if ( ACCESS_Frame( face->numLocations * 4L ) )
  529.         return error;
  530.  
  531.       limit = face->numLocations;
  532.  
  533.       for ( n = 0; n < limit; n++ )
  534.         face->glyphLocations[n] = GET_Long();
  535.  
  536.       FORGET_Frame();
  537.     }
  538.     else
  539.     {
  540.       face->numLocations =
  541.         (unsigned long)face->dirTables[n].Length >> 1;
  542.  
  543.       DebugTrace(( "( 16 bits offsets ) : %12d ",
  544.                    face->numLocations ));
  545.  
  546.       if ( ALLOC_ARRAY( face->glyphLocations,
  547.                         face->numLocations,
  548.                         Long ) )
  549.         return error;
  550.  
  551.       if ( ACCESS_Frame( face->numLocations * 2L ) )
  552.         return error;   
  553.  
  554.       limit = face->numLocations;
  555.  
  556.       for ( n = 0; n < limit; n++ )
  557.         face->glyphLocations[n] =
  558.           (Long)((unsigned long)GET_UShort() * 2);
  559.  
  560.       FORGET_Frame();
  561.     }
  562.  
  563.     DebugTrace(( "loaded\n" ));
  564.  
  565.     return TT_Err_Ok;
  566.   }
  567.  
  568.  
  569. /*******************************************************************
  570.  *
  571.  *  Function    :  Load_TrueType_Names
  572.  *
  573.  *  Description :  Loads the name table into face table.
  574.  *
  575.  *  Input  :  face     face table to look for
  576.  *
  577.  *  Output :  error code
  578.  *
  579.  ******************************************************************/
  580.  
  581.   TT_Error  Load_TrueType_Names( PFace  face )
  582.   {
  583.     DEFINE_LOCALS;
  584.  
  585.     int    i, bytes, n;
  586.     PByte  storage;
  587.  
  588.     TName_Table*  names;
  589.     TNameRec*     namerec;
  590.  
  591.     DebugTrace(( "Names " ));
  592.  
  593.     if ( (n = LookUp_TrueType_Table(face, TTAG_name) ) < 0 )
  594.     {
  595.       /* The name table is required so indicate failure. */
  596.       DebugTrace(( "is missing!\n" ));
  597.  
  598.       return TT_Err_Table_Missing;
  599.     }
  600.  
  601.     /* Seek to the beginning of the table and check the frame access. */
  602.     /* The names table has a 6 byte header.                           */
  603.     if ( FILE_Seek( face->dirTables[n].Offset ) ||
  604.          ACCESS_Frame( 6L ) )
  605.       return error;
  606.  
  607.     names = &face->nameTable;
  608.  
  609.     /* Load the initial names data. */
  610.     names->format         = GET_UShort();
  611.     names->numNameRecords = GET_UShort();
  612.     names->storageOffset  = GET_UShort();
  613.  
  614.     FORGET_Frame();
  615.  
  616.     /* Allocate the array of name records. */
  617.     if ( ALLOC_ARRAY( names->names,
  618.                       names->numNameRecords,
  619.                       TNameRec )              ||
  620.  
  621.          ACCESS_Frame( names->numNameRecords * 12L ) )
  622.     {
  623.       names->numNameRecords = 0;
  624.       goto Fail;
  625.     }
  626.  
  627.     /* Load the name records and determine how much storage is needed */
  628.     /* to hold the strings themselves.                                */
  629.  
  630.     for ( i = bytes = 0; i < names->numNameRecords; i++ )
  631.     {
  632.       namerec = names->names + i;
  633.       namerec->platformID   = GET_UShort();
  634.       namerec->encodingID   = GET_UShort();
  635.       namerec->languageID   = GET_UShort();
  636.       namerec->nameID       = GET_UShort();
  637.       namerec->stringLength = GET_UShort();
  638.       namerec->stringOffset = GET_UShort();
  639.  
  640.       /* check the ids */
  641.  
  642.       if ( namerec->platformID <= 3 )
  643.         bytes += namerec->stringLength;
  644.     }
  645.  
  646.     FORGET_Frame();
  647.  
  648.     /* Allocate storage for the strings if they exist. */
  649.  
  650.     names->storage = NULL;
  651.  
  652.     if ( bytes > 0 )
  653.     {
  654.       if ( ALLOC( storage, bytes ) ||
  655.  
  656.            FILE_Read_At( face->dirTables[n].Offset +
  657.                          names->storageOffset,
  658.                          (void*)storage, 
  659.                          bytes )    )
  660.         goto Fail_Storage;
  661.  
  662.       names->storage = storage;
  663.  
  664.       /* Go through and assign the string pointers to the name records. */
  665.  
  666.       for ( i = 0; i < names->numNameRecords; i++ )
  667.       {
  668.         namerec = names->names + i;
  669.  
  670.         if ( namerec->platformID <= 3)
  671.           namerec->string = storage + names->names[i].stringOffset;
  672.         else
  673.         {
  674.           namerec->string       = NULL;
  675.           namerec->stringLength = 0;
  676.         }
  677.       }
  678.     }
  679.  
  680. #ifdef DEBUG
  681.  
  682.     for ( i = 0; i < names->numNameRecords; i++ ) 
  683.     {
  684.       int  j;
  685.  
  686.       DebugTrace(( "%d %d %x %d ",
  687.                    names->names[i].platformID,
  688.                    names->names[i].encodingID,
  689.                    names->names[i].languageID,
  690.                    names->names[i].nameID ));
  691.  
  692.       /* I know, that  M$ encoded strings are unicode,          */
  693.       /* but this works reasonable well for debugging purposes. */ 
  694.       for ( j = 0; j < names->names[i].stringLength; j++ )
  695.       {
  696.         if (names->names[i].string)
  697.         {
  698.           char  c = *(names->names[i].string + j);
  699.      
  700.           if ( (unsigned char)c < 128 )
  701.             DebugTrace(( "%c", c ));
  702.         }
  703.       }
  704.  
  705.       DebugTrace(( "\n" ));
  706.     }
  707.  
  708. #endif
  709.  
  710.     DebugTrace(( "loaded\n" ));
  711.     return TT_Err_Ok;
  712.  
  713.   Fail_Storage :
  714.     FREE( storage );
  715.  
  716.   Fail :
  717.     Free_TrueType_Names( face );
  718.     return error;
  719.   }
  720.  
  721.  
  722.   TT_Error  Free_TrueType_Names( PFace  face )
  723.   {
  724.     TName_Table*  names = &face->nameTable;
  725.  
  726.     /* free strings table */
  727.     FREE( names->names );
  728.  
  729.     /* free strings storage */
  730.     FREE( names->storage );
  731.  
  732.     names->numNameRecords = 0;
  733.     names->format         = 0;
  734.     names->storageOffset  = 0;
  735.  
  736.     return TT_Err_Ok;
  737.   }
  738.  
  739. /*******************************************************************
  740.  *
  741.  *  Function    :  Load_TrueType_CVT
  742.  *
  743.  *  Description :  Loads cvt table into resdent table.
  744.  *
  745.  *  Input  :  face     face table to look for
  746.  *
  747.  *  Output :  error code
  748.  *
  749.  ******************************************************************/
  750.  
  751.   TT_Error  Load_TrueType_CVT( PFace  face )
  752.   {
  753.     DEFINE_LOCALS;
  754.  
  755.     long  n;
  756.     Int  limit;
  757.  
  758.     DebugTrace(( "CVT " ));
  759.  
  760.     if ( ( n = LookUp_TrueType_Table( face, TTAG_cvt ) ) < 0 )
  761.     {
  762.       DebugTrace(( "is missing!\n" ));
  763.  
  764.       face->cvtSize = 0;
  765.       face->cvt     = NULL;
  766.       return TT_Err_Ok;
  767.     }
  768.  
  769.     face->cvtSize = face->dirTables[n].Length / 2;
  770.  
  771.     if ( ALLOC_ARRAY( face->cvt,
  772.                       face->cvtSize,
  773.                       Short ) )
  774.       return error;
  775.  
  776.     if ( FILE_Seek( face->dirTables[n].Offset ) ||
  777.          ACCESS_Frame( face->cvtSize * 2 ) )
  778.       return error;
  779.  
  780.     limit = face->cvtSize;
  781.  
  782.     for ( n = 0; n < limit; n++ )
  783.       face->cvt[n] = GET_Short();
  784.  
  785.     FORGET_Frame();
  786.  
  787.     DebugTrace(( "loaded\n" ));
  788.  
  789.     return TT_Err_Ok;
  790.   }
  791.  
  792.  
  793. /*******************************************************************
  794.  *
  795.  *  Function    :  Load_TrueType_CMap
  796.  *
  797.  *  Description :  Loads the cmap directory in memory
  798.  *                 The cmaps themselves are loaded in ttcmap.c
  799.  *
  800.  *  Input  :  face
  801.  *
  802.  *  Output :  error code
  803.  *
  804.  ******************************************************************/
  805.  
  806.   TT_Error  Load_TrueType_CMap( PFace  face )
  807.   {
  808.     DEFINE_LOCALS;
  809.  
  810.     long  off, table_start;
  811.     int   n, limit;
  812.  
  813.     TCMapDir         cmap_dir;
  814.     TCMapDirEntry    entry_;
  815.     PCMapTable       cmap;
  816.  
  817.     DebugTrace(( "CMaps " ));
  818.  
  819.     if ( ( n = LookUp_TrueType_Table( face, TTAG_cmap ) ) < 0 )
  820.       return TT_Err_Table_Missing;
  821.  
  822.     table_start = face->dirTables[n].Offset;
  823.  
  824.     if ( ( FILE_Seek( table_start ) ) ||
  825.          ( ACCESS_Frame ( 4L ) ) )           /* 4 bytes cmap header */
  826.       return error;
  827.  
  828.     cmap_dir.tableVersionNumber = GET_UShort();
  829.     cmap_dir.numCMaps           = GET_UShort();
  830.  
  831.     FORGET_Frame();
  832.  
  833.     off = FILE_Pos();  /* save offset to cmapdir[] which follows */
  834.  
  835.     /* save space in face table for cmap tables */
  836.     if ( ALLOC_ARRAY( face->cMaps,
  837.                       cmap_dir.numCMaps,
  838.                       TCMapTable ) )
  839.       return error;
  840.  
  841.     face->numCMaps = cmap_dir.numCMaps;
  842.  
  843.     limit = face->numCMaps;
  844.     cmap  = face->cMaps;
  845.  
  846.     for ( n = 0; n < limit; n++ )
  847.     {
  848.       if ( FILE_Seek( off ) ||
  849.            ACCESS_Frame( 8L ) )
  850.         return error;
  851.  
  852.       /* extra code using entry_ for platxxx could be cleaned up later */
  853.       cmap->loaded             = FALSE;
  854.       cmap->platformID         = entry_.platformID         = GET_UShort();
  855.       cmap->platformEncodingID = entry_.platformEncodingID = GET_UShort();
  856.  
  857.       entry_.offset = GET_Long();
  858.  
  859.       FORGET_Frame();
  860.  
  861.       off = FILE_Pos();
  862.  
  863.       if ( FILE_Seek( table_start + entry_.offset )  ||
  864.            ACCESS_Frame( 6L ) )
  865.         return error;
  866.       
  867.       cmap->format  = GET_UShort();
  868.       cmap->length  = GET_UShort();
  869.       cmap->version = GET_UShort();
  870.  
  871.       FORGET_Frame();
  872.  
  873.       cmap->offset = FILE_Pos();
  874.  
  875.       cmap++;
  876.     }
  877.  
  878.     DebugTrace(( "loaded\n" ));
  879.  
  880.     return TT_Err_Ok;
  881.   }
  882.  
  883.  
  884. /*******************************************************************
  885.  *
  886.  *  Function    :  Load_TrueType_HMTX
  887.  *
  888.  *  Description :  Load the horizontal metrics table into face
  889.  *                 table.
  890.  *
  891.  *  Input  :  face
  892.  *
  893.  *  Output :  error code
  894.  *
  895.  ******************************************************************/
  896.  
  897.   TT_Error  Load_TrueType_HMTX( PFace  face )
  898.   {
  899.     DEFINE_LOCALS;
  900.  
  901.     Long              n, nsmetrics, nhmetrics;
  902.     PTableHorMetrics  plhm;
  903.  
  904.     DebugTrace(( "HMTX " ));
  905.  
  906.     if ( ( n = LookUp_TrueType_Table( face, TTAG_hmtx ) ) < 0 )
  907.       return TT_Err_Table_Missing;
  908.  
  909.     nhmetrics = face->horizontalHeader.number_Of_HMetrics;
  910.     nsmetrics = face->maxProfile.numGlyphs - nhmetrics;
  911.     if ( nsmetrics < 0 )            /* sanity check */
  912.     {
  913.       DebugTrace(( "more hmetrics than glyphs!\n" ));
  914.  
  915.       return TT_Err_Invalid_Horiz_Metrics;
  916.     }
  917.  
  918.     if ( ALLOC_ARRAY( face->longHMetrics,
  919.                       nhmetrics,
  920.                       TLongHorMetric ) )
  921.       return error;
  922.  
  923.     if ( ALLOC_ARRAY( face->shortMetrics,
  924.                       nsmetrics,
  925.                       Long ) )
  926.       return error;
  927.  
  928.     if ( FILE_Seek( face->dirTables[n].Offset )        ||
  929.          ACCESS_Frame( face->dirTables[n].Length ) )
  930.  
  931.       return error;
  932.  
  933.     for ( n = 0; n < nhmetrics; n++ )
  934.     {
  935.       plhm = face->longHMetrics + n;
  936.  
  937.       plhm->advance_Width = GET_Short();
  938.       plhm->lsb           = GET_Short();
  939.     }
  940.  
  941.     for ( n = 0; n < nsmetrics; n++ )
  942.       face->shortMetrics[n] = GET_Short();
  943.  
  944.     FORGET_Frame();
  945.  
  946.     DebugTrace(( "loaded\n" ));
  947.  
  948.     return TT_Err_Ok;
  949.   }
  950.  
  951.  
  952. /*******************************************************************
  953.  *
  954.  *  Function    :  Load_TrueType_Programs
  955.  *
  956.  *  Description :  Load the font (fpgm) and cvt programs into the
  957.  *                 face table.
  958.  *
  959.  *  Input  :  face
  960.  *
  961.  *  Output :  error code
  962.  *
  963.  ******************************************************************/
  964.  
  965.   TT_Error  Load_TrueType_Programs( PFace  face )
  966.   {
  967.     DEFINE_LOCALS_WO_FRAME;
  968.     int  n;
  969.  
  970.     DebugTrace(( "Font program " ));
  971.  
  972.     /* The font program is optional */
  973.     if ( ( n = LookUp_TrueType_Table( face, TTAG_fpgm ) ) < 0 )
  974.     {
  975.       face->fontProgram = NULL;
  976.       face->fontPgmSize = 0;
  977.  
  978.       DebugTrace(( "is missing!\n" ));
  979.     }
  980.     else
  981.     {
  982.       face->fontPgmSize = face->dirTables[n].Length;
  983.  
  984.       if ( ALLOC( face->fontProgram,
  985.                   face->fontPgmSize )              ||
  986.  
  987.            FILE_Read_At( face->dirTables[n].Offset,
  988.                          (void*)face->fontProgram,
  989.                          face->fontPgmSize )       )
  990.         return error;
  991.  
  992.       DebugTrace(( "loaded, %12d bytes\n", face->fontPgmSize ));
  993.     }
  994.  
  995.    DebugTrace(( "Prep program " ));
  996.  
  997.     if ( ( n = LookUp_TrueType_Table( face, TTAG_prep ) ) < 0 )
  998.     {
  999.       face->cvtProgram = NULL;
  1000.       face->cvtPgmSize = 0;
  1001.  
  1002.       DebugTrace(( "is missing!\n" ));
  1003.     }
  1004.     else
  1005.     {
  1006.       face->cvtPgmSize = face->dirTables[n].Length;
  1007.   
  1008.       if ( ALLOC( face->cvtProgram,
  1009.                   face->cvtPgmSize )               ||
  1010.  
  1011.            FILE_Read_At( face->dirTables[n].Offset,
  1012.                          (void*)face->cvtProgram,
  1013.                          face->cvtPgmSize )        )
  1014.         return error;
  1015.   
  1016.       DebugTrace(( "loaded, %12d bytes\n", face->cvtPgmSize ));
  1017.     }
  1018.  
  1019.     return TT_Err_Ok;
  1020.   }
  1021.  
  1022. /*******************************************************************
  1023.  *
  1024.  *  Function    :  Load_TrueType_OS2
  1025.  *
  1026.  *  Description :  Load the OS2 Table
  1027.  *
  1028.  *  Input  :  face
  1029.  *
  1030.  *  Output :  error code
  1031.  *
  1032.  ******************************************************************/
  1033.  
  1034.  TT_Error  Load_TrueType_OS2( PFace  face )
  1035.  {
  1036.    DEFINE_LOCALS;
  1037.  
  1038.    Int      i;
  1039.    TT_OS2*  os2;
  1040.  
  1041.    DebugTrace(( "OS/2 Table " ));
  1042.  
  1043.    if ( (i = LookUp_TrueType_Table( face, TTAG_OS2 )) < 0 )
  1044.    {
  1045.      DebugTrace(( "is missing !!" ));
  1046.      return TT_Err_Table_Missing;
  1047.    }
  1048.  
  1049.    if ( FILE_Seek( face->dirTables[i].Offset ) ||
  1050.         ACCESS_Frame( 78L ) )
  1051.      return error;
  1052.  
  1053.    os2 = &face->os2;
  1054.  
  1055.    os2->version             = GET_UShort();
  1056.    os2->xAvgCharWidth       = GET_Short();
  1057.    os2->usWeightClass       = GET_UShort();
  1058.    os2->usWidthClass        = GET_UShort();
  1059.    os2->fsType              = GET_Short();
  1060.    os2->ySubscriptXSize     = GET_Short();
  1061.    os2->ySubscriptYSize     = GET_Short();
  1062.    os2->ySubscriptXOffset   = GET_Short();
  1063.    os2->ySubscriptYOffset   = GET_Short();
  1064.    os2->ySuperscriptXSize   = GET_Short();
  1065.    os2->ySuperscriptYSize   = GET_Short();
  1066.    os2->ySuperscriptXOffset = GET_Short();
  1067.    os2->ySuperscriptYOffset = GET_Short();
  1068.    os2->yStrikeoutSize      = GET_Short();
  1069.    os2->yStrikeoutPosition  = GET_Short();
  1070.    os2->sFamilyClass        = GET_Short();
  1071.  
  1072.    for ( i = 0; i < 10; i++ )
  1073.      os2->panose[i] = GET_Byte();
  1074.  
  1075.    os2->ulUnicodeRange1     = GET_ULong();
  1076.    os2->ulUnicodeRange2     = GET_ULong();
  1077.    os2->ulUnicodeRange3     = GET_ULong();
  1078.    os2->ulUnicodeRange4     = GET_ULong();
  1079.  
  1080.    for ( i = 0; i < 4; i++ )
  1081.      os2->achVendID[i] = GET_Byte();
  1082.  
  1083.    os2->fsSelection         = GET_UShort();
  1084.    os2->usFirstCharIndex    = GET_UShort();
  1085.    os2->usLastCharIndex     = GET_UShort();
  1086.    os2->sTypoAscender       = GET_UShort();
  1087.    os2->sTypoDescender      = GET_UShort();
  1088.    os2->sTypoLineGap        = GET_UShort();
  1089.    os2->usWinAscent         = GET_UShort();
  1090.    os2->usWinDescent        = GET_UShort();
  1091.  
  1092.    FORGET_Frame();
  1093.  
  1094.    if (os2->version >= 0x0001) 
  1095.    {
  1096.      /* only version 1 tables */
  1097.  
  1098.      if ( ACCESS_Frame( 8L ) )  /* read into frame */
  1099.        return error;
  1100.  
  1101.      os2->ulCodePageRange1 = GET_ULong();
  1102.      os2->ulCodePageRange2 = GET_ULong();
  1103.  
  1104.      FORGET_Frame();
  1105.    }
  1106.    else 
  1107.    {
  1108.      os2->ulCodePageRange1 = 0;
  1109.      os2->ulCodePageRange2 = 0;
  1110.    }
  1111.  
  1112.    DebugTrace(( "loaded\n" ));
  1113.  
  1114.    return TT_Err_Ok;
  1115.  }
  1116.  
  1117. /*******************************************************************
  1118.  *
  1119.  *  Function    :  Load_TrueType_PostScript
  1120.  *
  1121.  *  Description :  Loads the post table into resident table.
  1122.  *
  1123.  *  Input  :  resident     resident table to look for
  1124.  *
  1125.  *  Output :  SUCCESS on success. FAILURE on error.
  1126.  *
  1127.  ******************************************************************/
  1128.  
  1129.   TT_Error  Load_TrueType_PostScript( PFace  face )
  1130.   {
  1131.     DEFINE_LOCALS;
  1132.  
  1133.     Int  i;
  1134.  
  1135.     TT_Postscript* post = &face->postscript;
  1136.  
  1137.     DebugTrace(( "PostScript " ));
  1138.  
  1139.     if ( ( i = LookUp_TrueType_Table( face, TTAG_post ) ) < 0 )
  1140.       return TT_Err_Table_Missing;
  1141.  
  1142.     if ( FILE_Seek( face->dirTables[i].Offset ) ||
  1143.          ACCESS_Frame( 32L ) )                       
  1144.       return error;
  1145.  
  1146.     /* read frame data into resident table */
  1147.  
  1148.     post->FormatType          = GET_ULong();
  1149.     post->italicAngle         = GET_ULong();
  1150.     post->underlinePosition   = GET_Short();
  1151.     post->underlineThickness  = GET_Short();
  1152.     post->isFixedPitch        = GET_ULong();
  1153.     post->minMemType42        = GET_ULong();
  1154.     post->maxMemType42        = GET_ULong();
  1155.     post->minMemType1         = GET_ULong();
  1156.     post->maxMemType1         = GET_ULong();
  1157.  
  1158.     FORGET_Frame();
  1159.  
  1160.     /* we don't load the glyph names, we'd rather do that in a */
  1161.     /* library extension                                       */
  1162.  
  1163.     DebugTrace(( "loaded\n" ));
  1164.  
  1165.     return TT_Err_Ok;
  1166.   }
  1167.  
  1168. /* End */
  1169.