Subversion Repositories Kolibri OS

Rev

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

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ttpload.c                                                              */
  4. /*                                                                         */
  5. /*    TrueType-specific tables loader (body).                              */
  6. /*                                                                         */
  7. /*  Copyright 1996-2002, 2004-2013 by                                      */
  8. /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  9. /*                                                                         */
  10. /*  This file is part of the FreeType project, and may only be used,       */
  11. /*  modified, and distributed under the terms of the FreeType project      */
  12. /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  13. /*  this file you indicate that you have read the license and              */
  14. /*  understand and accept it fully.                                        */
  15. /*                                                                         */
  16. /***************************************************************************/
  17.  
  18.  
  19. #include <ft2build.h>
  20. #include FT_INTERNAL_DEBUG_H
  21. #include FT_INTERNAL_OBJECTS_H
  22. #include FT_INTERNAL_STREAM_H
  23. #include FT_TRUETYPE_TAGS_H
  24.  
  25. #include "ttpload.h"
  26.  
  27. #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
  28. #include "ttgxvar.h"
  29. #endif
  30.  
  31. #include "tterrors.h"
  32.  
  33.  
  34.   /*************************************************************************/
  35.   /*                                                                       */
  36.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  37.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  38.   /* messages during execution.                                            */
  39.   /*                                                                       */
  40. #undef  FT_COMPONENT
  41. #define FT_COMPONENT  trace_ttpload
  42.  
  43.  
  44.   /*************************************************************************/
  45.   /*                                                                       */
  46.   /* <Function>                                                            */
  47.   /*    tt_face_load_loca                                                  */
  48.   /*                                                                       */
  49.   /* <Description>                                                         */
  50.   /*    Load the locations table.                                          */
  51.   /*                                                                       */
  52.   /* <InOut>                                                               */
  53.   /*    face   :: A handle to the target face object.                      */
  54.   /*                                                                       */
  55.   /* <Input>                                                               */
  56.   /*    stream :: The input stream.                                        */
  57.   /*                                                                       */
  58.   /* <Return>                                                              */
  59.   /*    FreeType error code.  0 means success.                             */
  60.   /*                                                                       */
  61.   FT_LOCAL_DEF( FT_Error )
  62.   tt_face_load_loca( TT_Face    face,
  63.                      FT_Stream  stream )
  64.   {
  65.     FT_Error  error;
  66.     FT_ULong  table_len;
  67.     FT_Int    shift;
  68.  
  69.  
  70.     /* we need the size of the `glyf' table for malformed `loca' tables */
  71.     error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len );
  72.  
  73.     /* it is possible that a font doesn't have a glyf table at all */
  74.     /* or its size is zero                                         */
  75.     if ( FT_ERR_EQ( error, Table_Missing ) )
  76.       face->glyf_len = 0;
  77.     else if ( error )
  78.       goto Exit;
  79.  
  80.     FT_TRACE2(( "Locations " ));
  81.     error = face->goto_table( face, TTAG_loca, stream, &table_len );
  82.     if ( error )
  83.     {
  84.       error = FT_THROW( Locations_Missing );
  85.       goto Exit;
  86.     }
  87.  
  88.     if ( face->header.Index_To_Loc_Format != 0 )
  89.     {
  90.       shift = 2;
  91.  
  92.       if ( table_len >= 0x40000L )
  93.       {
  94.         FT_TRACE2(( "table too large\n" ));
  95.         error = FT_THROW( Invalid_Table );
  96.         goto Exit;
  97.       }
  98.       face->num_locations = table_len >> shift;
  99.     }
  100.     else
  101.     {
  102.       shift = 1;
  103.  
  104.       if ( table_len >= 0x20000L )
  105.       {
  106.         FT_TRACE2(( "table too large\n" ));
  107.         error = FT_THROW( Invalid_Table );
  108.         goto Exit;
  109.       }
  110.       face->num_locations = table_len >> shift;
  111.     }
  112.  
  113.     if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 )
  114.     {
  115.       FT_TRACE2(( "glyph count mismatch!  loca: %d, maxp: %d\n",
  116.                   face->num_locations - 1, face->root.num_glyphs ));
  117.  
  118.       /* we only handle the case where `maxp' gives a larger value */
  119.       if ( face->num_locations <= (FT_ULong)face->root.num_glyphs )
  120.       {
  121.         FT_Long   new_loca_len =
  122.                     ( (FT_Long)( face->root.num_glyphs ) + 1 ) << shift;
  123.  
  124.         TT_Table  entry = face->dir_tables;
  125.         TT_Table  limit = entry + face->num_tables;
  126.  
  127.         FT_Long   pos  = FT_Stream_Pos( stream );
  128.         FT_Long   dist = 0x7FFFFFFFL;
  129.  
  130.  
  131.         /* compute the distance to next table in font file */
  132.         for ( ; entry < limit; entry++ )
  133.         {
  134.           FT_Long  diff = entry->Offset - pos;
  135.  
  136.  
  137.           if ( diff > 0 && diff < dist )
  138.             dist = diff;
  139.         }
  140.  
  141.         if ( entry == limit )
  142.         {
  143.           /* `loca' is the last table */
  144.           dist = stream->size - pos;
  145.         }
  146.  
  147.         if ( new_loca_len <= dist )
  148.         {
  149.           face->num_locations = face->root.num_glyphs + 1;
  150.           table_len           = new_loca_len;
  151.  
  152.           FT_TRACE2(( "adjusting num_locations to %d\n",
  153.                       face->num_locations ));
  154.         }
  155.       }
  156.     }
  157.  
  158.     /*
  159.      * Extract the frame.  We don't need to decompress it since
  160.      * we are able to parse it directly.
  161.      */
  162.     if ( FT_FRAME_EXTRACT( table_len, face->glyph_locations ) )
  163.       goto Exit;
  164.  
  165.     FT_TRACE2(( "loaded\n" ));
  166.  
  167.   Exit:
  168.     return error;
  169.   }
  170.  
  171.  
  172.   FT_LOCAL_DEF( FT_ULong )
  173.   tt_face_get_location( TT_Face   face,
  174.                         FT_UInt   gindex,
  175.                         FT_UInt  *asize )
  176.   {
  177.     FT_ULong  pos1, pos2;
  178.     FT_Byte*  p;
  179.     FT_Byte*  p_limit;
  180.  
  181.  
  182.     pos1 = pos2 = 0;
  183.  
  184.     if ( gindex < face->num_locations )
  185.     {
  186.       if ( face->header.Index_To_Loc_Format != 0 )
  187.       {
  188.         p       = face->glyph_locations + gindex * 4;
  189.         p_limit = face->glyph_locations + face->num_locations * 4;
  190.  
  191.         pos1 = FT_NEXT_ULONG( p );
  192.         pos2 = pos1;
  193.  
  194.         if ( p + 4 <= p_limit )
  195.           pos2 = FT_NEXT_ULONG( p );
  196.       }
  197.       else
  198.       {
  199.         p       = face->glyph_locations + gindex * 2;
  200.         p_limit = face->glyph_locations + face->num_locations * 2;
  201.  
  202.         pos1 = FT_NEXT_USHORT( p );
  203.         pos2 = pos1;
  204.  
  205.         if ( p + 2 <= p_limit )
  206.           pos2 = FT_NEXT_USHORT( p );
  207.  
  208.         pos1 <<= 1;
  209.         pos2 <<= 1;
  210.       }
  211.     }
  212.  
  213.     /* Check broken location data */
  214.     if ( pos1 > face->glyf_len )
  215.     {
  216.       FT_TRACE1(( "tt_face_get_location:"
  217.                   " too large offset=0x%08lx found for gid=0x%04lx,"
  218.                   " exceeding the end of glyf table (0x%08lx)\n",
  219.                   pos1, gindex, face->glyf_len ));
  220.       *asize = 0;
  221.       return 0;
  222.     }
  223.  
  224.     if ( pos2 > face->glyf_len )
  225.     {
  226.       FT_TRACE1(( "tt_face_get_location:"
  227.                   " too large offset=0x%08lx found for gid=0x%04lx,"
  228.                   " truncate at the end of glyf table (0x%08lx)\n",
  229.                   pos2, gindex + 1, face->glyf_len ));
  230.       pos2 = face->glyf_len;
  231.     }
  232.  
  233.     /* The `loca' table must be ordered; it refers to the length of */
  234.     /* an entry as the difference between the current and the next  */
  235.     /* position.  However, there do exist (malformed) fonts which   */
  236.     /* don't obey this rule, so we are only able to provide an      */
  237.     /* upper bound for the size.                                    */
  238.     /*                                                              */
  239.     /* We get (intentionally) a wrong, non-zero result in case the  */
  240.     /* `glyf' table is missing.                                     */
  241.     if ( pos2 >= pos1 )
  242.       *asize = (FT_UInt)( pos2 - pos1 );
  243.     else
  244.       *asize = (FT_UInt)( face->glyf_len - pos1 );
  245.  
  246.     return pos1;
  247.   }
  248.  
  249.  
  250.   FT_LOCAL_DEF( void )
  251.   tt_face_done_loca( TT_Face  face )
  252.   {
  253.     FT_Stream  stream = face->root.stream;
  254.  
  255.  
  256.     FT_FRAME_RELEASE( face->glyph_locations );
  257.     face->num_locations = 0;
  258.   }
  259.  
  260.  
  261.  
  262.   /*************************************************************************/
  263.   /*                                                                       */
  264.   /* <Function>                                                            */
  265.   /*    tt_face_load_cvt                                                   */
  266.   /*                                                                       */
  267.   /* <Description>                                                         */
  268.   /*    Load the control value table into a face object.                   */
  269.   /*                                                                       */
  270.   /* <InOut>                                                               */
  271.   /*    face   :: A handle to the target face object.                      */
  272.   /*                                                                       */
  273.   /* <Input>                                                               */
  274.   /*    stream :: A handle to the input stream.                            */
  275.   /*                                                                       */
  276.   /* <Return>                                                              */
  277.   /*    FreeType error code.  0 means success.                             */
  278.   /*                                                                       */
  279.   FT_LOCAL_DEF( FT_Error )
  280.   tt_face_load_cvt( TT_Face    face,
  281.                     FT_Stream  stream )
  282.   {
  283. #ifdef TT_USE_BYTECODE_INTERPRETER
  284.  
  285.     FT_Error   error;
  286.     FT_Memory  memory = stream->memory;
  287.     FT_ULong   table_len;
  288.  
  289.  
  290.     FT_TRACE2(( "CVT " ));
  291.  
  292.     error = face->goto_table( face, TTAG_cvt, stream, &table_len );
  293.     if ( error )
  294.     {
  295.       FT_TRACE2(( "is missing\n" ));
  296.  
  297.       face->cvt_size = 0;
  298.       face->cvt      = NULL;
  299.       error          = FT_Err_Ok;
  300.  
  301.       goto Exit;
  302.     }
  303.  
  304.     face->cvt_size = table_len / 2;
  305.  
  306.     if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) )
  307.       goto Exit;
  308.  
  309.     if ( FT_FRAME_ENTER( face->cvt_size * 2L ) )
  310.       goto Exit;
  311.  
  312.     {
  313.       FT_Short*  cur   = face->cvt;
  314.       FT_Short*  limit = cur + face->cvt_size;
  315.  
  316.  
  317.       for ( ; cur < limit; cur++ )
  318.         *cur = FT_GET_SHORT();
  319.     }
  320.  
  321.     FT_FRAME_EXIT();
  322.     FT_TRACE2(( "loaded\n" ));
  323.  
  324. #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
  325.     if ( face->doblend )
  326.       error = tt_face_vary_cvt( face, stream );
  327. #endif
  328.  
  329.   Exit:
  330.     return error;
  331.  
  332. #else /* !TT_USE_BYTECODE_INTERPRETER */
  333.  
  334.     FT_UNUSED( face   );
  335.     FT_UNUSED( stream );
  336.  
  337.     return FT_Err_Ok;
  338.  
  339. #endif
  340.   }
  341.  
  342.  
  343.   /*************************************************************************/
  344.   /*                                                                       */
  345.   /* <Function>                                                            */
  346.   /*    tt_face_load_fpgm                                                  */
  347.   /*                                                                       */
  348.   /* <Description>                                                         */
  349.   /*    Load the font program.                                             */
  350.   /*                                                                       */
  351.   /* <InOut>                                                               */
  352.   /*    face   :: A handle to the target face object.                      */
  353.   /*                                                                       */
  354.   /* <Input>                                                               */
  355.   /*    stream :: A handle to the input stream.                            */
  356.   /*                                                                       */
  357.   /* <Return>                                                              */
  358.   /*    FreeType error code.  0 means success.                             */
  359.   /*                                                                       */
  360.   FT_LOCAL_DEF( FT_Error )
  361.   tt_face_load_fpgm( TT_Face    face,
  362.                      FT_Stream  stream )
  363.   {
  364. #ifdef TT_USE_BYTECODE_INTERPRETER
  365.  
  366.     FT_Error  error;
  367.     FT_ULong  table_len;
  368.  
  369.  
  370.     FT_TRACE2(( "Font program " ));
  371.  
  372.     /* The font program is optional */
  373.     error = face->goto_table( face, TTAG_fpgm, stream, &table_len );
  374.     if ( error )
  375.     {
  376.       face->font_program      = NULL;
  377.       face->font_program_size = 0;
  378.       error                   = FT_Err_Ok;
  379.  
  380.       FT_TRACE2(( "is missing\n" ));
  381.     }
  382.     else
  383.     {
  384.       face->font_program_size = table_len;
  385.       if ( FT_FRAME_EXTRACT( table_len, face->font_program ) )
  386.         goto Exit;
  387.  
  388.       FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size ));
  389.     }
  390.  
  391.   Exit:
  392.     return error;
  393.  
  394. #else /* !TT_USE_BYTECODE_INTERPRETER */
  395.  
  396.     FT_UNUSED( face   );
  397.     FT_UNUSED( stream );
  398.  
  399.     return FT_Err_Ok;
  400.  
  401. #endif
  402.   }
  403.  
  404.  
  405.   /*************************************************************************/
  406.   /*                                                                       */
  407.   /* <Function>                                                            */
  408.   /*    tt_face_load_prep                                                  */
  409.   /*                                                                       */
  410.   /* <Description>                                                         */
  411.   /*    Load the cvt program.                                              */
  412.   /*                                                                       */
  413.   /* <InOut>                                                               */
  414.   /*    face   :: A handle to the target face object.                      */
  415.   /*                                                                       */
  416.   /* <Input>                                                               */
  417.   /*    stream :: A handle to the input stream.                            */
  418.   /*                                                                       */
  419.   /* <Return>                                                              */
  420.   /*    FreeType error code.  0 means success.                             */
  421.   /*                                                                       */
  422.   FT_LOCAL_DEF( FT_Error )
  423.   tt_face_load_prep( TT_Face    face,
  424.                      FT_Stream  stream )
  425.   {
  426. #ifdef TT_USE_BYTECODE_INTERPRETER
  427.  
  428.     FT_Error  error;
  429.     FT_ULong  table_len;
  430.  
  431.  
  432.     FT_TRACE2(( "Prep program " ));
  433.  
  434.     error = face->goto_table( face, TTAG_prep, stream, &table_len );
  435.     if ( error )
  436.     {
  437.       face->cvt_program      = NULL;
  438.       face->cvt_program_size = 0;
  439.       error                  = FT_Err_Ok;
  440.  
  441.       FT_TRACE2(( "is missing\n" ));
  442.     }
  443.     else
  444.     {
  445.       face->cvt_program_size = table_len;
  446.       if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) )
  447.         goto Exit;
  448.  
  449.       FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size ));
  450.     }
  451.  
  452.   Exit:
  453.     return error;
  454.  
  455. #else /* !TT_USE_BYTECODE_INTERPRETER */
  456.  
  457.     FT_UNUSED( face   );
  458.     FT_UNUSED( stream );
  459.  
  460.     return FT_Err_Ok;
  461.  
  462. #endif
  463.   }
  464.  
  465.  
  466.   /*************************************************************************/
  467.   /*                                                                       */
  468.   /* <Function>                                                            */
  469.   /*    tt_face_load_hdmx                                                  */
  470.   /*                                                                       */
  471.   /* <Description>                                                         */
  472.   /*    Load the `hdmx' table into the face object.                        */
  473.   /*                                                                       */
  474.   /* <Input>                                                               */
  475.   /*    face   :: A handle to the target face object.                      */
  476.   /*                                                                       */
  477.   /*    stream :: A handle to the input stream.                            */
  478.   /*                                                                       */
  479.   /* <Return>                                                              */
  480.   /*    FreeType error code.  0 means success.                             */
  481.   /*                                                                       */
  482.  
  483.   FT_LOCAL_DEF( FT_Error )
  484.   tt_face_load_hdmx( TT_Face    face,
  485.                      FT_Stream  stream )
  486.   {
  487.     FT_Error   error;
  488.     FT_Memory  memory = stream->memory;
  489.     FT_UInt    version, nn, num_records;
  490.     FT_ULong   table_size, record_size;
  491.     FT_Byte*   p;
  492.     FT_Byte*   limit;
  493.  
  494.  
  495.     /* this table is optional */
  496.     error = face->goto_table( face, TTAG_hdmx, stream, &table_size );
  497.     if ( error || table_size < 8 )
  498.       return FT_Err_Ok;
  499.  
  500.     if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) )
  501.       goto Exit;
  502.  
  503.     p     = face->hdmx_table;
  504.     limit = p + table_size;
  505.  
  506.     version     = FT_NEXT_USHORT( p );
  507.     num_records = FT_NEXT_USHORT( p );
  508.     record_size = FT_NEXT_ULONG( p );
  509.  
  510.     /* The maximum number of bytes in an hdmx device record is the */
  511.     /* maximum number of glyphs + 2; this is 0xFFFF + 2; this is   */
  512.     /* the reason why `record_size' is a long (which we read as    */
  513.     /* unsigned long for convenience).  In practice, two bytes     */
  514.     /* sufficient to hold the size value.                          */
  515.     /*                                                             */
  516.     /* There are at least two fonts, HANNOM-A and HANNOM-B version */
  517.     /* 2.0 (2005), which get this wrong: The upper two bytes of    */
  518.     /* the size value are set to 0xFF instead of 0x00.  We catch   */
  519.     /* and fix this.                                               */
  520.  
  521.     if ( record_size >= 0xFFFF0000UL )
  522.       record_size &= 0xFFFFU;
  523.  
  524.     /* The limit for `num_records' is a heuristic value. */
  525.  
  526.     if ( version != 0 || num_records > 255 || record_size > 0x10001L )
  527.     {
  528.       error = FT_THROW( Invalid_File_Format );
  529.       goto Fail;
  530.     }
  531.  
  532.     if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) )
  533.       goto Fail;
  534.  
  535.     for ( nn = 0; nn < num_records; nn++ )
  536.     {
  537.       if ( p + record_size > limit )
  538.         break;
  539.  
  540.       face->hdmx_record_sizes[nn] = p[0];
  541.       p                          += record_size;
  542.     }
  543.  
  544.     face->hdmx_record_count = nn;
  545.     face->hdmx_table_size   = table_size;
  546.     face->hdmx_record_size  = record_size;
  547.  
  548.   Exit:
  549.     return error;
  550.  
  551.   Fail:
  552.     FT_FRAME_RELEASE( face->hdmx_table );
  553.     face->hdmx_table_size = 0;
  554.     goto Exit;
  555.   }
  556.  
  557.  
  558.   FT_LOCAL_DEF( void )
  559.   tt_face_free_hdmx( TT_Face  face )
  560.   {
  561.     FT_Stream  stream = face->root.stream;
  562.     FT_Memory  memory = stream->memory;
  563.  
  564.  
  565.     FT_FREE( face->hdmx_record_sizes );
  566.     FT_FRAME_RELEASE( face->hdmx_table );
  567.   }
  568.  
  569.  
  570.   /*************************************************************************/
  571.   /*                                                                       */
  572.   /* Return the advance width table for a given pixel size if it is found  */
  573.   /* in the font's `hdmx' table (if any).                                  */
  574.   /*                                                                       */
  575.   FT_LOCAL_DEF( FT_Byte* )
  576.   tt_face_get_device_metrics( TT_Face  face,
  577.                               FT_UInt  ppem,
  578.                               FT_UInt  gindex )
  579.   {
  580.     FT_UInt   nn;
  581.     FT_Byte*  result      = NULL;
  582.     FT_ULong  record_size = face->hdmx_record_size;
  583.     FT_Byte*  record      = face->hdmx_table + 8;
  584.  
  585.  
  586.     for ( nn = 0; nn < face->hdmx_record_count; nn++ )
  587.       if ( face->hdmx_record_sizes[nn] == ppem )
  588.       {
  589.         gindex += 2;
  590.         if ( gindex < record_size )
  591.           result = record + nn * record_size + gindex;
  592.         break;
  593.       }
  594.  
  595.     return result;
  596.   }
  597.  
  598.  
  599. /* END */
  600.