ttgload.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:62k
源码类别:

其他游戏

开发平台:

Visual C++

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ttgload.c                                                              */
  4. /*                                                                         */
  5. /*    TrueType Glyph Loader (body).                                        */
  6. /*                                                                         */
  7. /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 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. #include <ft2build.h>
  18. #include FT_INTERNAL_DEBUG_H
  19. #include FT_INTERNAL_CALC_H
  20. #include FT_INTERNAL_STREAM_H
  21. #include FT_INTERNAL_SFNT_H
  22. #include FT_TRUETYPE_TAGS_H
  23. #include FT_OUTLINE_H
  24. #include "ttgload.h"
  25. #include "ttpload.h"
  26. #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
  27. #include "ttgxvar.h"
  28. #endif
  29. #include "tterrors.h"
  30.   /*************************************************************************/
  31.   /*                                                                       */
  32.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  33.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  34.   /* messages during execution.                                            */
  35.   /*                                                                       */
  36. #undef  FT_COMPONENT
  37. #define FT_COMPONENT  trace_ttgload
  38.   /*************************************************************************/
  39.   /*                                                                       */
  40.   /* Composite font flags.                                                 */
  41.   /*                                                                       */
  42. #define ARGS_ARE_WORDS             0x0001
  43. #define ARGS_ARE_XY_VALUES         0x0002
  44. #define ROUND_XY_TO_GRID           0x0004
  45. #define WE_HAVE_A_SCALE            0x0008
  46. /* reserved                        0x0010 */
  47. #define MORE_COMPONENTS            0x0020
  48. #define WE_HAVE_AN_XY_SCALE        0x0040
  49. #define WE_HAVE_A_2X2              0x0080
  50. #define WE_HAVE_INSTR              0x0100
  51. #define USE_MY_METRICS             0x0200
  52. #define OVERLAP_COMPOUND           0x0400
  53. #define SCALED_COMPONENT_OFFSET    0x0800
  54. #define UNSCALED_COMPONENT_OFFSET  0x1000
  55.   /*************************************************************************/
  56.   /*                                                                       */
  57.   /* Returns the horizontal metrics in font units for a given glyph.  If   */
  58.   /* `check' is true, take care of monospaced fonts by returning the       */
  59.   /* advance width maximum.                                                */
  60.   /*                                                                       */
  61.   static void
  62.   Get_HMetrics( TT_Face     face,
  63.                 FT_UInt     idx,
  64.                 FT_Bool     check,
  65.                 FT_Short*   lsb,
  66.                 FT_UShort*  aw )
  67.   {
  68.     ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );
  69.     if ( check && face->postscript.isFixedPitch )
  70.       *aw = face->horizontal.advance_Width_Max;
  71.   }
  72.   /*************************************************************************/
  73.   /*                                                                       */
  74.   /* Returns the vertical metrics in font units for a given glyph.         */
  75.   /* Greg Hitchcock from Microsoft told us that if there were no `vmtx'    */
  76.   /* table, typoAscender/Descender from the `OS/2' table would be used     */
  77.   /* instead, and if there were no `OS/2' table, use ascender/descender    */
  78.   /* from the `hhea' table.  But that is not what Microsoft's rasterizer   */
  79.   /* apparently does: It uses the ppem value as the advance height, and    */
  80.   /* sets the top side bearing to be zero.                                 */
  81.   /*                                                                       */
  82.   /* The monospace `check' is probably not meaningful here, but we leave   */
  83.   /* it in for a consistent interface.                                     */
  84.   /*                                                                       */
  85.   static void
  86.   Get_VMetrics( TT_Face     face,
  87.                 FT_UInt     idx,
  88.                 FT_Bool     check,
  89.                 FT_Short*   tsb,
  90.                 FT_UShort*  ah )
  91.   {
  92.     FT_UNUSED( check );
  93.     if ( face->vertical_info )
  94.       ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
  95. #if 1             /* Empirically determined, at variance with what MS said */
  96.     else
  97.     {
  98.       *tsb = 0;
  99.       *ah  = face->root.units_per_EM;
  100.     }
  101. #else      /* This is what MS said to do.  It isn't what they do, however. */
  102.     else if ( face->os2.version != 0xFFFFU )
  103.     {
  104.       *tsb = face->os2.sTypoAscender;
  105.       *ah  = face->os2.sTypoAscender - face->os2.sTypoDescender;
  106.     }
  107.     else
  108.     {
  109.       *tsb = face->horizontal.Ascender;
  110.       *ah  = face->horizontal.Ascender - face->horizontal.Descender;
  111.     }
  112. #endif
  113.   }
  114.   /*************************************************************************/
  115.   /*                                                                       */
  116.   /* Translates an array of coordinates.                                   */
  117.   /*                                                                       */
  118.   static void
  119.   translate_array( FT_UInt     n,
  120.                    FT_Vector*  coords,
  121.                    FT_Pos      delta_x,
  122.                    FT_Pos      delta_y )
  123.   {
  124.     FT_UInt  k;
  125.     if ( delta_x )
  126.       for ( k = 0; k < n; k++ )
  127.         coords[k].x += delta_x;
  128.     if ( delta_y )
  129.       for ( k = 0; k < n; k++ )
  130.         coords[k].y += delta_y;
  131.   }
  132. #undef  IS_HINTED
  133. #define IS_HINTED( flags )  ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
  134.   /*************************************************************************/
  135.   /*                                                                       */
  136.   /* The following functions are used by default with TrueType fonts.      */
  137.   /* However, they can be replaced by alternatives if we need to support   */
  138.   /* TrueType-compressed formats (like MicroType) in the future.           */
  139.   /*                                                                       */
  140.   /*************************************************************************/
  141.   FT_CALLBACK_DEF( FT_Error )
  142.   TT_Access_Glyph_Frame( TT_Loader  loader,
  143.                          FT_UInt    glyph_index,
  144.                          FT_ULong   offset,
  145.                          FT_UInt    byte_count )
  146.   {
  147.     FT_Error   error;
  148.     FT_Stream  stream = loader->stream;
  149.     /* for non-debug mode */
  150.     FT_UNUSED( glyph_index );
  151.     FT_TRACE5(( "Glyph %ldn", glyph_index ));
  152.     /* the following line sets the `error' variable through macros! */
  153.     if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
  154.       return error;
  155.     loader->cursor = stream->cursor;
  156.     loader->limit  = stream->limit;
  157.     return TT_Err_Ok;
  158.   }
  159.   FT_CALLBACK_DEF( void )
  160.   TT_Forget_Glyph_Frame( TT_Loader  loader )
  161.   {
  162.     FT_Stream  stream = loader->stream;
  163.     FT_FRAME_EXIT();
  164.   }
  165.   FT_CALLBACK_DEF( FT_Error )
  166.   TT_Load_Glyph_Header( TT_Loader  loader )
  167.   {
  168.     FT_Byte*  p     = loader->cursor;
  169.     FT_Byte*  limit = loader->limit;
  170.     if ( p + 10 > limit )
  171.       return TT_Err_Invalid_Outline;
  172.     loader->n_contours = FT_NEXT_SHORT( p );
  173.     loader->bbox.xMin = FT_NEXT_SHORT( p );
  174.     loader->bbox.yMin = FT_NEXT_SHORT( p );
  175.     loader->bbox.xMax = FT_NEXT_SHORT( p );
  176.     loader->bbox.yMax = FT_NEXT_SHORT( p );
  177.     FT_TRACE5(( "  # of contours: %dn", loader->n_contours ));
  178.     FT_TRACE5(( "  xMin: %4d  xMax: %4dn", loader->bbox.xMin,
  179.                                             loader->bbox.xMax ));
  180.     FT_TRACE5(( "  yMin: %4d  yMax: %4dn", loader->bbox.yMin,
  181.                                             loader->bbox.yMax ));
  182.     loader->cursor = p;
  183.     return TT_Err_Ok;
  184.   }
  185.   FT_CALLBACK_DEF( FT_Error )
  186.   TT_Load_Simple_Glyph( TT_Loader  load )
  187.   {
  188.     FT_Error        error;
  189.     FT_Byte*        p          = load->cursor;
  190.     FT_Byte*        limit      = load->limit;
  191.     FT_GlyphLoader  gloader    = load->gloader;
  192.     FT_Int          n_contours = load->n_contours;
  193.     FT_Outline*     outline;
  194.     TT_Face         face       = (TT_Face)load->face;
  195.     FT_UShort       n_ins;
  196.     FT_Int          n_points;
  197.     FT_Byte         *flag, *flag_limit;
  198.     FT_Byte         c, count;
  199.     FT_Vector       *vec, *vec_limit;
  200.     FT_Pos          x;
  201.     FT_Short        *cont, *cont_limit, prev_cont;
  202.     FT_Int          xy_size = 0;
  203.     /* check that we can add the contours to the glyph */
  204.     error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
  205.     if ( error )
  206.       goto Fail;
  207.     /* reading the contours' endpoints & number of points */
  208.     cont       = gloader->current.outline.contours;
  209.     cont_limit = cont + n_contours;
  210.     /* check space for contours array + instructions count */
  211.     if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit )
  212.       goto Invalid_Outline;
  213.     cont[0] = prev_cont = FT_NEXT_USHORT( p );
  214.     for ( cont++; cont < cont_limit; cont++ )
  215.     {
  216.       cont[0] = FT_NEXT_USHORT( p );
  217.       if ( cont[0] <= prev_cont )
  218.       {
  219.         /* unordered contours: this is invalid */
  220.         error = FT_Err_Invalid_Table;
  221.         goto Fail;
  222.       }
  223.       prev_cont = cont[0];
  224.     }
  225.     n_points = 0;
  226.     if ( n_contours > 0 )
  227.     {
  228.       n_points = cont[-1] + 1;
  229.       if ( n_points < 0 )
  230.         goto Invalid_Outline;
  231.     }
  232.     /* note that we will add four phantom points later */
  233.     error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
  234.     if ( error )
  235.       goto Fail;
  236.     /* we'd better check the contours table right now */
  237.     outline = &gloader->current.outline;
  238.     for ( cont = outline->contours + 1; cont < cont_limit; cont++ )
  239.       if ( cont[-1] >= cont[0] )
  240.         goto Invalid_Outline;
  241.     /* reading the bytecode instructions */
  242.     load->glyph->control_len  = 0;
  243.     load->glyph->control_data = 0;
  244.     if ( p + 2 > limit )
  245.       goto Invalid_Outline;
  246.     n_ins = FT_NEXT_USHORT( p );
  247.     FT_TRACE5(( "  Instructions size: %un", n_ins ));
  248.     if ( n_ins > face->max_profile.maxSizeOfInstructions )
  249.     {
  250.       FT_TRACE0(( "TT_Load_Simple_Glyph: Too many instructions (%d)n",
  251.                   n_ins ));
  252.       error = TT_Err_Too_Many_Hints;
  253.       goto Fail;
  254.     }
  255.     if ( ( limit - p ) < n_ins )
  256.     {
  257.       FT_TRACE0(( "TT_Load_Simple_Glyph: Instruction count mismatch!n" ));
  258.       error = TT_Err_Too_Many_Hints;
  259.       goto Fail;
  260.     }
  261. #ifdef TT_USE_BYTECODE_INTERPRETER
  262.     if ( IS_HINTED( load->load_flags ) )
  263.     {
  264.       load->glyph->control_len  = n_ins;
  265.       load->glyph->control_data = load->exec->glyphIns;
  266.       FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
  267.     }
  268. #endif /* TT_USE_BYTECODE_INTERPRETER */
  269.     p += n_ins;
  270.     /* reading the point tags */
  271.     flag       = (FT_Byte*)outline->tags;
  272.     flag_limit = flag + n_points;
  273.     FT_ASSERT( flag != NULL );
  274.     while ( flag < flag_limit )
  275.     {
  276.       if ( p + 1 > limit )
  277.         goto Invalid_Outline;
  278.       *flag++ = c = FT_NEXT_BYTE( p );
  279.       if ( c & 8 )
  280.       {
  281.         if ( p + 1 > limit )
  282.           goto Invalid_Outline;
  283.         count = FT_NEXT_BYTE( p );
  284.         if ( flag + (FT_Int)count > flag_limit )
  285.           goto Invalid_Outline;
  286.         for ( ; count > 0; count-- )
  287.           *flag++ = c;
  288.       }
  289.     }
  290.     /* reading the X coordinates */
  291.     vec       = outline->points;
  292.     vec_limit = vec + n_points;
  293.     flag      = (FT_Byte*)outline->tags;
  294.     x         = 0;
  295.     if ( p + xy_size > limit )
  296.       goto Invalid_Outline;
  297.     for ( ; vec < vec_limit; vec++, flag++ )
  298.     {
  299.       FT_Pos  y = 0;
  300.       FT_Byte f = *flag;
  301.       if ( f & 2 )
  302.       {
  303.         if ( p + 1 > limit )
  304.           goto Invalid_Outline;
  305.         y = (FT_Pos)FT_NEXT_BYTE( p );
  306.         if ( ( f & 16 ) == 0 )
  307.           y = -y;
  308.       }
  309.       else if ( ( f & 16 ) == 0 )
  310.       {
  311.         if ( p + 2 > limit )
  312.           goto Invalid_Outline;
  313.         y = (FT_Pos)FT_NEXT_SHORT( p );
  314.       }
  315.       x     += y;
  316.       vec->x = x;
  317.       *flag  = f & ~( 2 | 16 );
  318.     }
  319.     /* reading the Y coordinates */
  320.     vec       = gloader->current.outline.points;
  321.     vec_limit = vec + n_points;
  322.     flag      = (FT_Byte*)outline->tags;
  323.     x         = 0;
  324.     for ( ; vec < vec_limit; vec++, flag++ )
  325.     {
  326.       FT_Pos  y = 0;
  327.       FT_Byte f = *flag;
  328.       if ( f & 4 )
  329.       {
  330.         if ( p + 1 > limit )
  331.           goto Invalid_Outline;
  332.         y = (FT_Pos)FT_NEXT_BYTE( p );
  333.         if ( ( f & 32 ) == 0 )
  334.           y = -y;
  335.       }
  336.       else if ( ( f & 32 ) == 0 )
  337.       {
  338.         if ( p + 2 > limit )
  339.           goto Invalid_Outline;
  340.         y = (FT_Pos)FT_NEXT_SHORT( p );
  341.       }
  342.       x     += y;
  343.       vec->y = x;
  344.       *flag  = f & FT_CURVE_TAG_ON;
  345.     }
  346.     outline->n_points   = (FT_UShort)n_points;
  347.     outline->n_contours = (FT_Short) n_contours;
  348.     load->cursor = p;
  349.   Fail:
  350.     return error;
  351.   Invalid_Outline:
  352.     error = TT_Err_Invalid_Outline;
  353.     goto Fail;
  354.   }
  355.   FT_CALLBACK_DEF( FT_Error )
  356.   TT_Load_Composite_Glyph( TT_Loader  loader )
  357.   {
  358.     FT_Error        error;
  359.     FT_Byte*        p       = loader->cursor;
  360.     FT_Byte*        limit   = loader->limit;
  361.     FT_GlyphLoader  gloader = loader->gloader;
  362.     FT_SubGlyph     subglyph;
  363.     FT_UInt         num_subglyphs;
  364.     num_subglyphs = 0;
  365.     do
  366.     {
  367.       FT_Fixed  xx, xy, yy, yx;
  368.       FT_UInt   count;
  369.       /* check that we can load a new subglyph */
  370.       error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
  371.       if ( error )
  372.         goto Fail;
  373.       /* check space */
  374.       if ( p + 4 > limit )
  375.         goto Invalid_Composite;
  376.       subglyph = gloader->current.subglyphs + num_subglyphs;
  377.       subglyph->arg1 = subglyph->arg2 = 0;
  378.       subglyph->flags = FT_NEXT_USHORT( p );
  379.       subglyph->index = FT_NEXT_USHORT( p );
  380.       /* check space */
  381.       count = 2;
  382.       if ( subglyph->flags & ARGS_ARE_WORDS )
  383.         count += 2;
  384.       if ( subglyph->flags & WE_HAVE_A_SCALE )
  385.         count += 2;
  386.       else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
  387.         count += 4;
  388.       else if ( subglyph->flags & WE_HAVE_A_2X2 )
  389.         count += 8;
  390.       if ( p + count > limit )
  391.         goto Invalid_Composite;
  392.       /* read arguments */
  393.       if ( subglyph->flags & ARGS_ARE_WORDS )
  394.       {
  395.         subglyph->arg1 = FT_NEXT_SHORT( p );
  396.         subglyph->arg2 = FT_NEXT_SHORT( p );
  397.       }
  398.       else
  399.       {
  400.         subglyph->arg1 = FT_NEXT_CHAR( p );
  401.         subglyph->arg2 = FT_NEXT_CHAR( p );
  402.       }
  403.       /* read transform */
  404.       xx = yy = 0x10000L;
  405.       xy = yx = 0;
  406.       if ( subglyph->flags & WE_HAVE_A_SCALE )
  407.       {
  408.         xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
  409.         yy = xx;
  410.       }
  411.       else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
  412.       {
  413.         xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
  414.         yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
  415.       }
  416.       else if ( subglyph->flags & WE_HAVE_A_2X2 )
  417.       {
  418.         xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
  419.         yx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
  420.         xy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
  421.         yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
  422.       }
  423.       subglyph->transform.xx = xx;
  424.       subglyph->transform.xy = xy;
  425.       subglyph->transform.yx = yx;
  426.       subglyph->transform.yy = yy;
  427.       num_subglyphs++;
  428.     } while ( subglyph->flags & MORE_COMPONENTS );
  429.     gloader->current.num_subglyphs = num_subglyphs;
  430. #ifdef TT_USE_BYTECODE_INTERPRETER
  431.     {
  432.       FT_Stream  stream = loader->stream;
  433.       /* we must undo the FT_FRAME_ENTER in order to point to the */
  434.       /* composite instructions, if we find some.               */
  435.       /* we will process them later...                          */
  436.       /*                                                        */
  437.       loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
  438.                                     p - limit );
  439.     }
  440. #endif
  441.     loader->cursor = p;
  442.   Fail:
  443.     return error;
  444.   Invalid_Composite:
  445.     error = TT_Err_Invalid_Composite;
  446.     goto Fail;
  447.   }
  448.   FT_LOCAL_DEF( void )
  449.   TT_Init_Glyph_Loading( TT_Face  face )
  450.   {
  451.     face->access_glyph_frame   = TT_Access_Glyph_Frame;
  452.     face->read_glyph_header    = TT_Load_Glyph_Header;
  453.     face->read_simple_glyph    = TT_Load_Simple_Glyph;
  454.     face->read_composite_glyph = TT_Load_Composite_Glyph;
  455.     face->forget_glyph_frame   = TT_Forget_Glyph_Frame;
  456.   }
  457.   static void
  458.   tt_prepare_zone( TT_GlyphZone  zone,
  459.                    FT_GlyphLoad  load,
  460.                    FT_UInt       start_point,
  461.                    FT_UInt       start_contour )
  462.   {
  463.     zone->n_points    = (FT_UShort)( load->outline.n_points - start_point );
  464.     zone->n_contours  = (FT_Short) ( load->outline.n_contours -
  465.                                        start_contour );
  466.     zone->org         = load->extra_points + start_point;
  467.     zone->cur         = load->outline.points + start_point;
  468.     zone->orus        = load->extra_points2 + start_point;
  469.     zone->tags        = (FT_Byte*)load->outline.tags + start_point;
  470.     zone->contours    = (FT_UShort*)load->outline.contours + start_contour;
  471.     zone->first_point = (FT_UShort)start_point;
  472.   }
  473.   /*************************************************************************/
  474.   /*                                                                       */
  475.   /* <Function>                                                            */
  476.   /*    TT_Hint_Glyph                                                      */
  477.   /*                                                                       */
  478.   /* <Description>                                                         */
  479.   /*    Hint the glyph using the zone prepared by the caller.  Note that   */
  480.   /*    the zone is supposed to include four phantom points.               */
  481.   /*                                                                       */
  482.   static FT_Error
  483.   TT_Hint_Glyph( TT_Loader  loader,
  484.                  FT_Bool    is_composite )
  485.   {
  486.     TT_GlyphZone  zone = &loader->zone;
  487.     FT_Pos        origin;
  488. #ifdef TT_USE_BYTECODE_INTERPRETER
  489.     FT_UInt       n_ins;
  490. #else
  491.     FT_UNUSED( is_composite );
  492. #endif
  493. #ifdef TT_USE_BYTECODE_INTERPRETER
  494.     n_ins = loader->glyph->control_len;
  495. #endif
  496.     origin = zone->cur[zone->n_points - 4].x;
  497.     origin = FT_PIX_ROUND( origin ) - origin;
  498.     if ( origin )
  499.       translate_array( zone->n_points, zone->cur, origin, 0 );
  500. #ifdef TT_USE_BYTECODE_INTERPRETER
  501.     /* save original point position in org */
  502.     if ( n_ins > 0 )
  503.       FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
  504. #endif
  505.     /* round pp2 and pp4 */
  506.     zone->cur[zone->n_points - 3].x =
  507.       FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
  508.     zone->cur[zone->n_points - 1].y =
  509.       FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
  510. #ifdef TT_USE_BYTECODE_INTERPRETER
  511.     if ( n_ins > 0 )
  512.     {
  513.       FT_Bool   debug;
  514.       FT_Error  error;
  515.       error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph,
  516.                                 loader->exec->glyphIns, n_ins );
  517.       if ( error )
  518.         return error;
  519.       loader->exec->is_composite = is_composite;
  520.       loader->exec->pts          = *zone;
  521.       debug = FT_BOOL( !( loader->load_flags & FT_LOAD_NO_SCALE ) &&
  522.                        ((TT_Size)loader->size)->debug             );
  523.       error = TT_Run_Context( loader->exec, debug );
  524.       if ( error && loader->exec->pedantic_hinting )
  525.         return error;
  526.     }
  527. #endif
  528.     /* save glyph phantom points */
  529.     if ( !loader->preserve_pps )
  530.     {
  531.       loader->pp1 = zone->cur[zone->n_points - 4];
  532.       loader->pp2 = zone->cur[zone->n_points - 3];
  533.       loader->pp3 = zone->cur[zone->n_points - 2];
  534.       loader->pp4 = zone->cur[zone->n_points - 1];
  535.     }
  536.     return TT_Err_Ok;
  537.   }
  538.   /*************************************************************************/
  539.   /*                                                                       */
  540.   /* <Function>                                                            */
  541.   /*    TT_Process_Simple_Glyph                                            */
  542.   /*                                                                       */
  543.   /* <Description>                                                         */
  544.   /*    Once a simple glyph has been loaded, it needs to be processed.     */
  545.   /*    Usually, this means scaling and hinting through bytecode           */
  546.   /*    interpretation.                                                    */
  547.   /*                                                                       */
  548.   static FT_Error
  549.   TT_Process_Simple_Glyph( TT_Loader  loader )
  550.   {
  551.     FT_GlyphLoader  gloader = loader->gloader;
  552.     FT_Error        error   = TT_Err_Ok;
  553.     FT_Outline*     outline;
  554.     FT_UInt         n_points;
  555.     outline  = &gloader->current.outline;
  556.     n_points = outline->n_points;
  557.     /* set phantom points */
  558.     outline->points[n_points    ] = loader->pp1;
  559.     outline->points[n_points + 1] = loader->pp2;
  560.     outline->points[n_points + 2] = loader->pp3;
  561.     outline->points[n_points + 3] = loader->pp4;
  562.     outline->tags[n_points    ] = 0;
  563.     outline->tags[n_points + 1] = 0;
  564.     outline->tags[n_points + 2] = 0;
  565.     outline->tags[n_points + 3] = 0;
  566.     n_points += 4;
  567. #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
  568.     if ( ((TT_Face)loader->face)->doblend )
  569.     {
  570.       /* Deltas apply to the unscaled data. */
  571.       FT_Vector*  deltas;
  572.       FT_Memory   memory = loader->face->memory;
  573.       FT_UInt     i;
  574.       error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
  575.                                         loader->glyph_index,
  576.                                         &deltas,
  577.                                         n_points );
  578.       if ( error )
  579.         return error;
  580.       for ( i = 0; i < n_points; ++i )
  581.       {
  582.         outline->points[i].x += deltas[i].x;
  583.         outline->points[i].y += deltas[i].y;
  584.       }
  585.       FT_FREE( deltas );
  586.     }
  587. #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
  588.     if ( IS_HINTED( loader->load_flags ) )
  589.     {
  590.       tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
  591.       FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
  592.                      loader->zone.n_points + 4 );
  593.     }
  594.     /* scale the glyph */
  595.     if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
  596.     {
  597.       FT_Vector*  vec     = outline->points;
  598.       FT_Vector*  limit   = outline->points + n_points;
  599.       FT_Fixed    x_scale = ((TT_Size)loader->size)->metrics.x_scale;
  600.       FT_Fixed    y_scale = ((TT_Size)loader->size)->metrics.y_scale;
  601.       for ( ; vec < limit; vec++ )
  602.       {
  603.         vec->x = FT_MulFix( vec->x, x_scale );
  604.         vec->y = FT_MulFix( vec->y, y_scale );
  605.       }
  606.       loader->pp1 = outline->points[n_points - 4];
  607.       loader->pp2 = outline->points[n_points - 3];
  608.       loader->pp3 = outline->points[n_points - 2];
  609.       loader->pp4 = outline->points[n_points - 1];
  610.     }
  611.     if ( IS_HINTED( loader->load_flags ) )
  612.     {
  613.       loader->zone.n_points += 4;
  614.       error = TT_Hint_Glyph( loader, 0 );
  615.     }
  616.     return error;
  617.   }
  618.   /*************************************************************************/
  619.   /*                                                                       */
  620.   /* <Function>                                                            */
  621.   /*    TT_Process_Composite_Component                                     */
  622.   /*                                                                       */
  623.   /* <Description>                                                         */
  624.   /*    Once a composite component has been loaded, it needs to be         */
  625.   /*    processed.  Usually, this means transforming and translating.      */
  626.   /*                                                                       */
  627.   static FT_Error
  628.   TT_Process_Composite_Component( TT_Loader    loader,
  629.                                   FT_SubGlyph  subglyph,
  630.                                   FT_UInt      start_point,
  631.                                   FT_UInt      num_base_points )
  632.   {
  633.     FT_GlyphLoader  gloader    = loader->gloader;
  634.     FT_Vector*      base_vec   = gloader->base.outline.points;
  635.     FT_UInt         num_points = gloader->base.outline.n_points;
  636.     FT_Bool         have_scale;
  637.     FT_Pos          x, y;
  638.     have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE     |
  639.                                               WE_HAVE_AN_XY_SCALE |
  640.                                               WE_HAVE_A_2X2       ) );
  641.     /* perform the transform required for this subglyph */
  642.     if ( have_scale )
  643.     {
  644.       FT_UInt  i;
  645.       for ( i = num_base_points; i < num_points; i++ )
  646.         FT_Vector_Transform( base_vec + i, &subglyph->transform );
  647.     }
  648.     /* get offset */
  649.     if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
  650.     {
  651.       FT_UInt     k = subglyph->arg1;
  652.       FT_UInt     l = subglyph->arg2;
  653.       FT_Vector*  p1;
  654.       FT_Vector*  p2;
  655.       /* match l-th point of the newly loaded component to the k-th point */
  656.       /* of the previously loaded components.                             */
  657.       /* change to the point numbers used by our outline */
  658.       k += start_point;
  659.       l += num_base_points;
  660.       if ( k >= num_base_points ||
  661.            l >= num_points      )
  662.         return TT_Err_Invalid_Composite;
  663.       p1 = gloader->base.outline.points + k;
  664.       p2 = gloader->base.outline.points + l;
  665.       x = p1->x - p2->x;
  666.       y = p1->y - p2->y;
  667.     }
  668.     else
  669.     {
  670.       x = subglyph->arg1;
  671.       y = subglyph->arg2;
  672.       if ( !x && !y )
  673.         return TT_Err_Ok;
  674.   /* Use a default value dependent on                                     */
  675.   /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED.  This is useful for old TT */
  676.   /* fonts which don't set the xxx_COMPONENT_OFFSET bit.                  */
  677.       if ( have_scale &&
  678. #ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
  679.            !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
  680. #else
  681.             ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
  682. #endif
  683.       {
  684. #if 0
  685.   /*************************************************************************/
  686.   /*                                                                       */
  687.   /* This algorithm is what Apple documents.  But it doesn't work.         */
  688.   /*                                                                       */
  689.         int  a = subglyph->transform.xx > 0 ?  subglyph->transform.xx
  690.                                             : -subglyph->transform.xx;
  691.         int  b = subglyph->transform.yx > 0 ?  subglyph->transform.yx
  692.                                             : -subglyph->transform.yx;
  693.         int  c = subglyph->transform.xy > 0 ?  subglyph->transform.xy
  694.                                             : -subglyph->transform.xy;
  695.         int  d = subglyph->transform.yy > 0 ? subglyph->transform.yy
  696.                                             : -subglyph->transform.yy;
  697.         int  m = a > b ? a : b;
  698.         int  n = c > d ? c : d;
  699.         if ( a - b <= 33 && a - b >= -33 )
  700.           m *= 2;
  701.         if ( c - d <= 33 && c - d >= -33 )
  702.           n *= 2;
  703.         x = FT_MulFix( x, m );
  704.         y = FT_MulFix( y, n );
  705. #else /* 0 */
  706.   /*************************************************************************/
  707.   /*                                                                       */
  708.   /* This algorithm is a guess and works much better than the above.       */
  709.   /*                                                                       */
  710.         FT_Fixed  mac_xscale = FT_SqrtFixed(
  711.                                  FT_MulFix( subglyph->transform.xx,
  712.                                             subglyph->transform.xx ) +
  713.                                  FT_MulFix( subglyph->transform.xy,
  714.                                             subglyph->transform.xy ) );
  715.         FT_Fixed  mac_yscale = FT_SqrtFixed(
  716.                                  FT_MulFix( subglyph->transform.yy,
  717.                                             subglyph->transform.yy ) +
  718.                                  FT_MulFix( subglyph->transform.yx,
  719.                                             subglyph->transform.yx ) );
  720.         x = FT_MulFix( x, mac_xscale );
  721.         y = FT_MulFix( y, mac_yscale );
  722. #endif /* 0 */
  723.       }
  724.       if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
  725.       {
  726.         FT_Fixed  x_scale = ((TT_Size)loader->size)->metrics.x_scale;
  727.         FT_Fixed  y_scale = ((TT_Size)loader->size)->metrics.y_scale;
  728.         x = FT_MulFix( x, x_scale );
  729.         y = FT_MulFix( y, y_scale );
  730.         if ( subglyph->flags & ROUND_XY_TO_GRID )
  731.         {
  732.           x = FT_PIX_ROUND( x );
  733.           y = FT_PIX_ROUND( y );
  734.         }
  735.       }
  736.     }
  737.     if ( x || y )
  738.       translate_array( num_points - num_base_points,
  739.                        base_vec + num_base_points,
  740.                        x, y );
  741.     return TT_Err_Ok;
  742.   }
  743.   /*************************************************************************/
  744.   /*                                                                       */
  745.   /* <Function>                                                            */
  746.   /*    TT_Process_Composite_Glyph                                         */
  747.   /*                                                                       */
  748.   /* <Description>                                                         */
  749.   /*    This is slightly different from TT_Process_Simple_Glyph, in that   */
  750.   /*    its sole purpose is to hint the glyph.  Thus this function is      */
  751.   /*    only available when bytecode interpreter is enabled.               */
  752.   /*                                                                       */
  753.   static FT_Error
  754.   TT_Process_Composite_Glyph( TT_Loader  loader,
  755.                               FT_UInt    start_point,
  756.                               FT_UInt    start_contour )
  757.   {
  758.     FT_Error     error;
  759.     FT_Outline*  outline;
  760.     FT_UInt      i;
  761.     outline = &loader->gloader->base.outline;
  762.     /* make room for phantom points */
  763.     error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
  764.                                          outline->n_points + 4,
  765.                                          0 );
  766.     if ( error )
  767.       return error;
  768.     outline->points[outline->n_points    ] = loader->pp1;
  769.     outline->points[outline->n_points + 1] = loader->pp2;
  770.     outline->points[outline->n_points + 2] = loader->pp3;
  771.     outline->points[outline->n_points + 3] = loader->pp4;
  772.     outline->tags[outline->n_points    ] = 0;
  773.     outline->tags[outline->n_points + 1] = 0;
  774.     outline->tags[outline->n_points + 2] = 0;
  775.     outline->tags[outline->n_points + 3] = 0;
  776. #ifdef TT_USE_BYTECODE_INTERPRETER
  777.     {
  778.       FT_Stream  stream = loader->stream;
  779.       FT_UShort  n_ins;
  780.       /* TT_Load_Composite_Glyph only gives us the offset of instructions */
  781.       /* so we read them here                                             */
  782.       if ( FT_STREAM_SEEK( loader->ins_pos ) ||
  783.            FT_READ_USHORT( n_ins )           )
  784.         return error;
  785.       FT_TRACE5(( "  Instructions size = %dn", n_ins ));
  786.       /* check it */
  787.       if ( n_ins > ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions )
  788.       {
  789.         FT_TRACE0(( "TT_Process_Composite_Glyph: Too many instructions (%d)n",
  790.                     n_ins ));
  791.         return TT_Err_Too_Many_Hints;
  792.       }
  793.       else if ( n_ins == 0 )
  794.         return TT_Err_Ok;
  795.       if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) )
  796.         return error;
  797.       loader->glyph->control_data = loader->exec->glyphIns;
  798.       loader->glyph->control_len  = n_ins;
  799.     }
  800. #endif
  801.     tt_prepare_zone( &loader->zone, &loader->gloader->base,
  802.                      start_point, start_contour );
  803.     /* Some points are likely touched during execution of  */
  804.     /* instructions on components.  So let's untouch them. */
  805.     for ( i = start_point; i < loader->zone.n_points; i++ )
  806.       loader->zone.tags[i] &= ~( FT_CURVE_TAG_TOUCH_X |
  807.                                  FT_CURVE_TAG_TOUCH_Y );
  808.     loader->zone.n_points += 4;
  809.     return TT_Hint_Glyph( loader, 1 );
  810.   }
  811.   /* Calculate the four phantom points.                     */
  812.   /* The first two stand for horizontal origin and advance. */
  813.   /* The last two stand for vertical origin and advance.    */
  814. #define TT_LOADER_SET_PP( loader )                                          
  815.           do {                                                              
  816.             (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; 
  817.             (loader)->pp1.y = 0;                                            
  818.             (loader)->pp2.x = (loader)->pp1.x + (loader)->advance;          
  819.             (loader)->pp2.y = 0;                                            
  820.             (loader)->pp3.x = 0;                                            
  821.             (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax;  
  822.             (loader)->pp4.x = 0;                                            
  823.             (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance;         
  824.           } while ( 0 )
  825.   /*************************************************************************/
  826.   /*                                                                       */
  827.   /* <Function>                                                            */
  828.   /*    load_truetype_glyph                                                */
  829.   /*                                                                       */
  830.   /* <Description>                                                         */
  831.   /*    Loads a given truetype glyph.  Handles composites and uses a       */
  832.   /*    TT_Loader object.                                                  */
  833.   /*                                                                       */
  834.   static FT_Error
  835.   load_truetype_glyph( TT_Loader  loader,
  836.                        FT_UInt    glyph_index,
  837.                        FT_UInt    recurse_count )
  838.   {
  839.     FT_Error        error;
  840.     FT_Fixed        x_scale, y_scale;
  841.     FT_ULong        offset;
  842.     TT_Face         face         = (TT_Face)loader->face;
  843.     FT_GlyphLoader  gloader      = loader->gloader;
  844.     FT_Bool         opened_frame = 0;
  845. #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
  846.     FT_Vector*      deltas       = NULL;
  847. #endif
  848. #ifdef FT_CONFIG_OPTION_INCREMENTAL
  849.     FT_StreamRec    inc_stream;
  850.     FT_Data         glyph_data;
  851.     FT_Bool         glyph_data_loaded = 0;
  852. #endif
  853.     if ( recurse_count > face->max_profile.maxComponentDepth )
  854.     {
  855.       error = TT_Err_Invalid_Composite;
  856.       goto Exit;
  857.     }
  858.     /* check glyph index */
  859.     if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
  860.     {
  861.       error = TT_Err_Invalid_Glyph_Index;
  862.       goto Exit;
  863.     }
  864.     loader->glyph_index = glyph_index;
  865.     if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
  866.     {
  867.       x_scale = ((TT_Size)loader->size)->metrics.x_scale;
  868.       y_scale = ((TT_Size)loader->size)->metrics.y_scale;
  869.     }
  870.     else
  871.     {
  872.       x_scale = 0x10000L;
  873.       y_scale = 0x10000L;
  874.     }
  875.     /* get metrics, horizontal and vertical */
  876.     {
  877.       FT_Short   left_bearing = 0, top_bearing = 0;
  878.       FT_UShort  advance_width = 0, advance_height = 0;
  879.       Get_HMetrics( face, glyph_index,
  880.                     (FT_Bool)!( loader->load_flags &
  881.                                 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
  882.                     &left_bearing,
  883.                     &advance_width );
  884.       Get_VMetrics( face, glyph_index,
  885.                     (FT_Bool)!( loader->load_flags &
  886.                                 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
  887.                     &top_bearing,
  888.                     &advance_height );
  889. #ifdef FT_CONFIG_OPTION_INCREMENTAL
  890.       /* If this is an incrementally loaded font see if there are */
  891.       /* overriding metrics for this glyph.                       */
  892.       if ( face->root.internal->incremental_interface &&
  893.            face->root.internal->incremental_interface->funcs->get_glyph_metrics )
  894.       {
  895.         FT_Incremental_MetricsRec  metrics;
  896.         metrics.bearing_x = left_bearing;
  897.         metrics.bearing_y = 0;
  898.         metrics.advance = advance_width;
  899.         error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
  900.                   face->root.internal->incremental_interface->object,
  901.                   glyph_index, FALSE, &metrics );
  902.         if ( error )
  903.           goto Exit;
  904.         left_bearing  = (FT_Short)metrics.bearing_x;
  905.         advance_width = (FT_UShort)metrics.advance;
  906. #if 0
  907.         /* GWW: Do I do the same for vertical metrics? */
  908.         metrics.bearing_x = 0;
  909.         metrics.bearing_y = top_bearing;
  910.         metrics.advance = advance_height;
  911.         error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
  912.                   face->root.internal->incremental_interface->object,
  913.                   glyph_index, TRUE, &metrics );
  914.         if ( error )
  915.           goto Exit;
  916.         top_bearing  = (FT_Short)metrics.bearing_y;
  917.         advance_height = (FT_UShort)metrics.advance;
  918. #endif /* 0 */
  919.       }
  920. #endif /* FT_CONFIG_OPTION_INCREMENTAL */
  921.       loader->left_bearing = left_bearing;
  922.       loader->advance      = advance_width;
  923.       loader->top_bearing  = top_bearing;
  924.       loader->vadvance     = advance_height;
  925.       if ( !loader->linear_def )
  926.       {
  927.         loader->linear_def = 1;
  928.         loader->linear     = advance_width;
  929.       }
  930.     }
  931.     /* Set `offset' to the start of the glyph relative to the start of */
  932.     /* the `glyf' table, and `byte_len' to the length of the glyph in  */
  933.     /* bytes.                                                          */
  934. #ifdef FT_CONFIG_OPTION_INCREMENTAL
  935.     /* If we are loading glyph data via the incremental interface, set */
  936.     /* the loader stream to a memory stream reading the data returned  */
  937.     /* by the interface.                                               */
  938.     if ( face->root.internal->incremental_interface )
  939.     {
  940.       error = face->root.internal->incremental_interface->funcs->get_glyph_data(
  941.                 face->root.internal->incremental_interface->object,
  942.                 glyph_index, &glyph_data );
  943.       if ( error )
  944.         goto Exit;
  945.       glyph_data_loaded = 1;
  946.       offset            = 0;
  947.       loader->byte_len  = glyph_data.length;
  948.       FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
  949.       FT_Stream_OpenMemory( &inc_stream,
  950.                             glyph_data.pointer, glyph_data.length );
  951.       loader->stream = &inc_stream;
  952.     }
  953.     else
  954. #endif /* FT_CONFIG_OPTION_INCREMENTAL */
  955.       offset = tt_face_get_location( face, glyph_index,
  956.                                      (FT_UInt*)&loader->byte_len );
  957.     if ( loader->byte_len == 0 )
  958.     {
  959.       /* as described by Frederic Loyer, these are spaces or */
  960.       /* the unknown glyph.                                  */
  961.       loader->bbox.xMin = 0;
  962.       loader->bbox.xMax = 0;
  963.       loader->bbox.yMin = 0;
  964.       loader->bbox.yMax = 0;
  965.       TT_LOADER_SET_PP( loader );
  966. #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
  967.       if ( ((TT_Face)(loader->face))->doblend )
  968.       {
  969.         /* this must be done before scaling */
  970.         FT_Memory  memory = loader->face->memory;
  971.         error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
  972.                                           glyph_index, &deltas, 4 );
  973.         if ( error )
  974.           goto Exit;
  975.         loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y;
  976.         loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y;
  977.         loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y;
  978.         loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y;
  979.         FT_FREE( deltas );
  980.       }
  981. #endif
  982.       if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
  983.       {
  984.         loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
  985.         loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
  986.         loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
  987.         loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
  988.       }
  989.       error = TT_Err_Ok;
  990.       goto Exit;
  991.     }
  992.     error = face->access_glyph_frame( loader, glyph_index,
  993.                                       loader->glyf_offset + offset,
  994.                                       loader->byte_len );
  995.     if ( error )
  996.       goto Exit;
  997.     opened_frame = 1;
  998.     /* read first glyph header */
  999.     error = face->read_glyph_header( loader );
  1000.     if ( error )
  1001.       goto Exit;
  1002.     TT_LOADER_SET_PP( loader );
  1003.     /***********************************************************************/
  1004.     /***********************************************************************/
  1005.     /***********************************************************************/
  1006.     /* if it is a simple glyph, load it */
  1007.     if ( loader->n_contours >= 0 )
  1008.     {
  1009.       error = face->read_simple_glyph( loader );
  1010.       if ( error )
  1011.         goto Exit;
  1012.       /* all data have been read */
  1013.       face->forget_glyph_frame( loader );
  1014.       opened_frame = 0;
  1015.       error = TT_Process_Simple_Glyph( loader );
  1016.       if ( error )
  1017.         goto Exit;
  1018.       FT_GlyphLoader_Add( gloader );
  1019.     }
  1020.     /***********************************************************************/
  1021.     /***********************************************************************/
  1022.     /***********************************************************************/
  1023.     /* otherwise, load a composite! */
  1024.     else if ( loader->n_contours == -1 )
  1025.     {
  1026.       FT_UInt   start_point;
  1027.       FT_UInt   start_contour;
  1028.       FT_ULong  ins_pos;  /* position of composite instructions, if any */
  1029.       start_point   = gloader->base.outline.n_points;
  1030.       start_contour = gloader->base.outline.n_contours;
  1031.       /* for each subglyph, read composite header */
  1032.       error = face->read_composite_glyph( loader );
  1033.       if ( error )
  1034.         goto Exit;
  1035.       /* store the offset of instructions */
  1036.       ins_pos = loader->ins_pos;
  1037.       /* all data we need are read */
  1038.       face->forget_glyph_frame( loader );
  1039.       opened_frame = 0;
  1040. #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
  1041.       if ( face->doblend )
  1042.       {
  1043.         FT_Int       i, limit;
  1044.         FT_SubGlyph  subglyph;
  1045.         FT_Memory    memory = face->root.memory;
  1046.         /* this provides additional offsets */
  1047.         /* for each component's translation */
  1048.         if ( ( error = TT_Vary_Get_Glyph_Deltas(
  1049.                          face,
  1050.                          glyph_index,
  1051.                          &deltas,
  1052.                          gloader->current.num_subglyphs + 4 )) != 0 )
  1053.           goto Exit;
  1054.         subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
  1055.         limit    = gloader->current.num_subglyphs;
  1056.         for ( i = 0; i < limit; ++i, ++subglyph )
  1057.         {
  1058.           if ( subglyph->flags & ARGS_ARE_XY_VALUES )
  1059.           {
  1060.             subglyph->arg1 += deltas[i].x;
  1061.             subglyph->arg2 += deltas[i].y;
  1062.           }
  1063.         }
  1064.         loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y;
  1065.         loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y;
  1066.         loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y;
  1067.         loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y;
  1068.         FT_FREE( deltas );
  1069.       }
  1070. #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
  1071.       if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
  1072.       {
  1073.         loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
  1074.         loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
  1075.         loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
  1076.         loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
  1077.       }
  1078.       /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
  1079.       /* `as is' in the glyph slot (the client application will be     */
  1080.       /* responsible for interpreting these data)...                   */
  1081.       if ( loader->load_flags & FT_LOAD_NO_RECURSE )
  1082.       {
  1083.         FT_GlyphLoader_Add( gloader );
  1084.         loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
  1085.         goto Exit;
  1086.       }
  1087.       /*********************************************************************/
  1088.       /*********************************************************************/
  1089.       /*********************************************************************/
  1090.       {
  1091.         FT_UInt           n, num_base_points;
  1092.         FT_SubGlyph       subglyph       = 0;
  1093.         FT_UInt           num_points     = start_point;
  1094.         FT_UInt           num_subglyphs  = gloader->current.num_subglyphs;
  1095.         FT_UInt           num_base_subgs = gloader->base.num_subglyphs;
  1096.         FT_Stream         old_stream     = loader->stream;
  1097.         TT_GraphicsState  saved_GS;
  1098.         if ( loader->exec )
  1099.           saved_GS = loader->exec->GS;
  1100.         FT_GlyphLoader_Add( gloader );
  1101.         /* read each subglyph independently */
  1102.         for ( n = 0; n < num_subglyphs; n++ )
  1103.         {
  1104.           FT_Vector  pp[4];
  1105.           /* reinitialize graphics state */
  1106.           if ( loader->exec )
  1107.             loader->exec->GS = saved_GS;
  1108.           /* Each time we call load_truetype_glyph in this loop, the   */
  1109.           /* value of `gloader.base.subglyphs' can change due to table */
  1110.           /* reallocations.  We thus need to recompute the subglyph    */
  1111.           /* pointer on each iteration.                                */
  1112.           subglyph = gloader->base.subglyphs + num_base_subgs + n;
  1113.           pp[0] = loader->pp1;
  1114.           pp[1] = loader->pp2;
  1115.           pp[2] = loader->pp3;
  1116.           pp[3] = loader->pp4;
  1117.           num_base_points = gloader->base.outline.n_points;
  1118.           error = load_truetype_glyph( loader, subglyph->index,
  1119.                                        recurse_count + 1 );
  1120.           if ( error )
  1121.             goto Exit;
  1122.           /* restore subglyph pointer */
  1123.           subglyph = gloader->base.subglyphs + num_base_subgs + n;
  1124.           if ( !( subglyph->flags & USE_MY_METRICS ) )
  1125.           {
  1126.             loader->pp1 = pp[0];
  1127.             loader->pp2 = pp[1];
  1128.             loader->pp3 = pp[2];
  1129.             loader->pp4 = pp[3];
  1130.           }
  1131.           num_points = gloader->base.outline.n_points;
  1132.           if ( num_points == num_base_points )
  1133.             continue;
  1134.           /* gloader->base.outline consists of three parts:               */
  1135.           /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */
  1136.           /*                                                              */
  1137.           /* (1): exists from the beginning                               */
  1138.           /* (2): components that have been loaded so far                 */
  1139.           /* (3): the newly loaded component                              */
  1140.           TT_Process_Composite_Component( loader, subglyph, start_point,
  1141.                                           num_base_points );
  1142.         }
  1143.         loader->stream = old_stream;
  1144.         /* process the glyph */
  1145.         loader->ins_pos = ins_pos;
  1146.         if ( IS_HINTED( loader->load_flags ) &&
  1147. #ifdef TT_USE_BYTECODE_INTERPRETER
  1148.              subglyph->flags & WE_HAVE_INSTR &&
  1149. #endif
  1150.              num_points > start_point )
  1151.           TT_Process_Composite_Glyph( loader, start_point, start_contour );
  1152.       }
  1153.     }
  1154.     else
  1155.     {
  1156.       /* invalid composite count (negative but not -1) */
  1157.       error = TT_Err_Invalid_Outline;
  1158.       goto Exit;
  1159.     }
  1160.     /***********************************************************************/
  1161.     /***********************************************************************/
  1162.     /***********************************************************************/
  1163.   Exit:
  1164.     if ( opened_frame )
  1165.       face->forget_glyph_frame( loader );
  1166. #ifdef FT_CONFIG_OPTION_INCREMENTAL
  1167.     if ( glyph_data_loaded )
  1168.       face->root.internal->incremental_interface->funcs->free_glyph_data(
  1169.         face->root.internal->incremental_interface->object,
  1170.         &glyph_data );
  1171. #endif
  1172.     return error;
  1173.   }
  1174.   static FT_Error
  1175.   compute_glyph_metrics( TT_Loader  loader,
  1176.                          FT_UInt    glyph_index )
  1177.   {
  1178.     FT_BBox       bbox;
  1179.     TT_Face       face = (TT_Face)loader->face;
  1180.     FT_Fixed      y_scale;
  1181.     TT_GlyphSlot  glyph = loader->glyph;
  1182.     TT_Size       size = (TT_Size)loader->size;
  1183.     y_scale = 0x10000L;
  1184.     if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
  1185.       y_scale = size->root.metrics.y_scale;
  1186.     if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
  1187.       FT_Outline_Get_CBox( &glyph->outline, &bbox );
  1188.     else
  1189.       bbox = loader->bbox;
  1190.     /* get the device-independent horizontal advance; it is scaled later */
  1191.     /* by the base layer.                                                */
  1192.     {
  1193.       FT_Pos  advance = loader->linear;
  1194.       /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
  1195.       /* correctly support DynaLab fonts, which have an incorrect       */
  1196.       /* `advance_Width_Max' field!  It is used, to my knowledge,       */
  1197.       /* exclusively in the X-TrueType font server.                     */
  1198.       /*                                                                */
  1199.       if ( face->postscript.isFixedPitch                                     &&
  1200.            ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
  1201.         advance = face->horizontal.advance_Width_Max;
  1202.       /* we need to return the advance in font units in linearHoriAdvance, */
  1203.       /* it will be scaled later by the base layer.                        */
  1204.       glyph->linearHoriAdvance = advance;
  1205.     }
  1206.     glyph->metrics.horiBearingX = bbox.xMin;
  1207.     glyph->metrics.horiBearingY = bbox.yMax;
  1208.     glyph->metrics.horiAdvance  = loader->pp2.x - loader->pp1.x;
  1209.     /* Now take care of vertical metrics.  In the case where there is    */
  1210.     /* no vertical information within the font (relatively common), make */
  1211.     /* up some metrics by `hand'...                                      */
  1212.     {
  1213.       FT_Pos  top;      /* scaled vertical top side bearing  */
  1214.       FT_Pos  advance;  /* scaled vertical advance height    */
  1215.       /* Get the unscaled top bearing and advance height. */
  1216.       if ( face->vertical_info &&
  1217.            face->vertical.number_Of_VMetrics > 0 )
  1218.       {
  1219.         top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax,
  1220.                                    y_scale );
  1221.         if ( loader->pp3.y <= loader->pp4.y )
  1222.           advance = 0;
  1223.         else
  1224.           advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y,
  1225.                                           y_scale );
  1226.       }
  1227.       else
  1228.       {
  1229.         FT_Pos  height;
  1230.         /* XXX Compute top side bearing and advance height in  */
  1231.         /*     Get_VMetrics instead of here.                   */
  1232.         /* NOTE: The OS/2 values are the only `portable' ones, */
  1233.         /*       which is why we use them, if there is an OS/2 */
  1234.         /*       table in the font.  Otherwise, we use the     */
  1235.         /*       values defined in the horizontal header.      */
  1236.         height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin,
  1237.                                       y_scale );
  1238.         if ( face->os2.version != 0xFFFFU )
  1239.           advance = (FT_Pos)( face->os2.sTypoAscender -
  1240.                               face->os2.sTypoDescender );
  1241.         else
  1242.           advance = (FT_Pos)( face->horizontal.Ascender -
  1243.                               face->horizontal.Descender );
  1244.         top = ( advance - height ) / 2;
  1245.       }
  1246. #ifdef FT_CONFIG_OPTION_INCREMENTAL
  1247.       {
  1248.         FT_Incremental_InterfaceRec*  incr;
  1249.         FT_Incremental_MetricsRec     metrics;
  1250.         FT_Error                      error;
  1251.         incr = face->root.internal->incremental_interface;
  1252.         /* If this is an incrementally loaded font see if there are */
  1253.         /* overriding metrics for this glyph.                       */
  1254.         if ( incr && incr->funcs->get_glyph_metrics )
  1255.         {
  1256.           metrics.bearing_x = 0;
  1257.           metrics.bearing_y = top;
  1258.           metrics.advance   = advance;
  1259.           error = incr->funcs->get_glyph_metrics( incr->object,
  1260.                                                   glyph_index,
  1261.                                                   TRUE,
  1262.                                                   &metrics );
  1263.           if ( error )
  1264.             return error;
  1265.           top     = metrics.bearing_y;
  1266.           advance = metrics.advance;
  1267.         }
  1268.       }
  1269.       /* GWW: Do vertical metrics get loaded incrementally too? */
  1270. #endif /* FT_CONFIG_OPTION_INCREMENTAL */
  1271.       glyph->linearVertAdvance = advance;
  1272.       /* scale the metrics */
  1273.       if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
  1274.       {
  1275.         top     = FT_MulFix( top, y_scale );
  1276.         advance = FT_MulFix( advance, y_scale );
  1277.       }
  1278.       /* XXX: for now, we have no better algorithm for the lsb, but it */
  1279.       /*      should work fine.                                        */
  1280.       /*                                                               */
  1281.       glyph->metrics.vertBearingX = ( bbox.xMin - bbox.xMax ) / 2;
  1282.       glyph->metrics.vertBearingY = top;
  1283.       glyph->metrics.vertAdvance  = advance;
  1284.     }
  1285.     /* adjust advance width to the value contained in the hdmx table */
  1286.     if ( !face->postscript.isFixedPitch &&
  1287.          IS_HINTED( loader->load_flags )        )
  1288.     {
  1289.       FT_Byte*  widthp;
  1290.       widthp = tt_face_get_device_metrics( face,
  1291.                                            size->root.metrics.x_ppem,
  1292.                                            glyph_index );
  1293.       if ( widthp )
  1294.         glyph->metrics.horiAdvance = *widthp << 6;
  1295.     }
  1296.     /* set glyph dimensions */
  1297.     glyph->metrics.width  = bbox.xMax - bbox.xMin;
  1298.     glyph->metrics.height = bbox.yMax - bbox.yMin;
  1299.     return 0;
  1300.   }
  1301. #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
  1302.   static FT_Error
  1303.   load_sbit_image( TT_Size       size,
  1304.                    TT_GlyphSlot  glyph,
  1305.                    FT_UInt       glyph_index,
  1306.                    FT_Int32      load_flags )
  1307.   {
  1308.     TT_Face             face;
  1309.     SFNT_Service        sfnt;
  1310.     FT_Stream           stream;
  1311.     FT_Error            error;
  1312.     TT_SBit_MetricsRec  metrics;
  1313.     face   = (TT_Face)glyph->face;
  1314.     sfnt   = (SFNT_Service)face->sfnt;
  1315.     stream = face->root.stream;
  1316.     error = sfnt->load_sbit_image( face,
  1317.                                    size->strike_index,
  1318.                                    glyph_index,
  1319.                                    (FT_Int)load_flags,
  1320.                                    stream,
  1321.                                    &glyph->bitmap,
  1322.                                    &metrics );
  1323.     if ( !error )
  1324.     {
  1325.       glyph->outline.n_points   = 0;
  1326.       glyph->outline.n_contours = 0;
  1327.       glyph->metrics.width  = (FT_Pos)metrics.width  << 6;
  1328.       glyph->metrics.height = (FT_Pos)metrics.height << 6;
  1329.       glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
  1330.       glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
  1331.       glyph->metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;
  1332.       glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
  1333.       glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
  1334.       glyph->metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;
  1335.       glyph->format = FT_GLYPH_FORMAT_BITMAP;
  1336.       if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
  1337.       {
  1338.         glyph->bitmap_left = metrics.vertBearingX;
  1339.         glyph->bitmap_top  = metrics.vertBearingY;
  1340.       }
  1341.       else
  1342.       {
  1343.         glyph->bitmap_left = metrics.horiBearingX;
  1344.         glyph->bitmap_top  = metrics.horiBearingY;
  1345.       }
  1346.     }
  1347.     return error;
  1348.   }
  1349. #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
  1350.   static FT_Error
  1351.   tt_loader_init( TT_Loader     loader,
  1352.                   TT_Size       size,
  1353.                   TT_GlyphSlot  glyph,
  1354.                   FT_Int32      load_flags )
  1355.   {
  1356.     TT_Face    face;
  1357.     FT_Stream  stream;
  1358.     face   = (TT_Face)glyph->face;
  1359.     stream = face->root.stream;
  1360.     FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) );
  1361. #ifdef TT_USE_BYTECODE_INTERPRETER
  1362.     /* load execution context */
  1363.     if ( IS_HINTED( load_flags ) )
  1364.     {
  1365.       TT_ExecContext  exec;
  1366.       FT_Bool         grayscale;
  1367.       if ( !size->cvt_ready )
  1368.       {
  1369.         FT_Error  error = tt_size_ready_bytecode( size );
  1370.         if ( error )
  1371.           return error;
  1372.       }
  1373.       /* query new execution context */
  1374.       exec = size->debug ? size->context
  1375.                          : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
  1376.       if ( !exec )
  1377.         return TT_Err_Could_Not_Find_Context;
  1378.       grayscale =
  1379.         FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO );
  1380.       TT_Load_Context( exec, face, size );
  1381.       /* a change from mono to grayscale rendering (and vice versa) */
  1382.       /* requires a re-execution of the CVT program                 */
  1383.       if ( grayscale != exec->grayscale )
  1384.       {
  1385.         FT_UInt  i;
  1386.         exec->grayscale = grayscale;
  1387.         for ( i = 0; i < size->cvt_size; i++ )
  1388.           size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
  1389.         tt_size_run_prep( size );
  1390.       }
  1391.       /* see whether the cvt program has disabled hinting */
  1392.       if ( exec->GS.instruct_control & 1 )
  1393.         load_flags |= FT_LOAD_NO_HINTING;
  1394.       /* load default graphics state -- if needed */
  1395.       if ( exec->GS.instruct_control & 2 )
  1396.         exec->GS = tt_default_graphics_state;
  1397.       exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
  1398.       loader->exec = exec;
  1399.       loader->instructions = exec->glyphIns;
  1400.     }
  1401. #endif /* TT_USE_BYTECODE_INTERPRETER */
  1402.     /* seek to the beginning of the glyph table -- for Type 42 fonts     */
  1403.     /* the table might be accessed from a Postscript stream or something */
  1404.     /* else...                                                           */
  1405. #ifdef FT_CONFIG_OPTION_INCREMENTAL
  1406.     if ( face->root.internal->incremental_interface )
  1407.       loader->glyf_offset = 0;
  1408.     else
  1409. #endif
  1410.     {
  1411.       FT_Error  error = face->goto_table( face, TTAG_glyf, stream, 0 );
  1412.       if ( error )
  1413.       {
  1414.         FT_ERROR(( "TT_Load_Glyph: could not access glyph tablen" ));
  1415.         return error;
  1416.       }
  1417.       loader->glyf_offset = FT_STREAM_POS();
  1418.     }
  1419.     /* get face's glyph loader */
  1420.     {
  1421.       FT_GlyphLoader  gloader = glyph->internal->loader;
  1422.       FT_GlyphLoader_Rewind( gloader );
  1423.       loader->gloader = gloader;
  1424.     }
  1425.     loader->load_flags    = load_flags;
  1426.     loader->face   = (FT_Face)face;
  1427.     loader->size   = (FT_Size)size;
  1428.     loader->glyph  = (FT_GlyphSlot)glyph;
  1429.     loader->stream = stream;
  1430.     return TT_Err_Ok;
  1431.   }
  1432.   /*************************************************************************/
  1433.   /*                                                                       */
  1434.   /* <Function>                                                            */
  1435.   /*    TT_Load_Glyph                                                      */
  1436.   /*                                                                       */
  1437.   /* <Description>                                                         */
  1438.   /*    A function used to load a single glyph within a given glyph slot,  */
  1439.   /*    for a given size.                                                  */
  1440.   /*                                                                       */
  1441.   /* <Input>                                                               */
  1442.   /*    glyph       :: A handle to a target slot object where the glyph    */
  1443.   /*                   will be loaded.                                     */
  1444.   /*                                                                       */
  1445.   /*    size        :: A handle to the source face size at which the glyph */
  1446.   /*                   must be scaled/loaded.                              */
  1447.   /*                                                                       */
  1448.   /*    glyph_index :: The index of the glyph in the font file.            */
  1449.   /*                                                                       */
  1450.   /*    load_flags  :: A flag indicating what to load for this glyph.  The */
  1451.   /*                   FT_LOAD_XXX constants can be used to control the    */
  1452.   /*                   glyph loading process (e.g., whether the outline    */
  1453.   /*                   should be scaled, whether to load bitmaps or not,   */
  1454.   /*                   whether to hint the outline, etc).                  */
  1455.   /*                                                                       */
  1456.   /* <Return>                                                              */
  1457.   /*    FreeType error code.  0 means success.                             */
  1458.   /*                                                                       */
  1459.   FT_LOCAL_DEF( FT_Error )
  1460.   TT_Load_Glyph( TT_Size       size,
  1461.                  TT_GlyphSlot  glyph,
  1462.                  FT_UInt       glyph_index,
  1463.                  FT_Int32      load_flags )
  1464.   {
  1465.     TT_Face       face;
  1466.     FT_Error      error;
  1467.     TT_LoaderRec  loader;
  1468.     face   = (TT_Face)glyph->face;
  1469.     error  = TT_Err_Ok;
  1470. #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
  1471.     /* try to load embedded bitmap if any              */
  1472.     /*                                                 */
  1473.     /* XXX: The convention should be emphasized in     */
  1474.     /*      the documents because it can be confusing. */
  1475.     if ( size->strike_index != 0xFFFFFFFFUL      &&
  1476.          ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
  1477.     {
  1478.       error = load_sbit_image( size, glyph, glyph_index, load_flags );
  1479.       if ( !error )
  1480.         return TT_Err_Ok;
  1481.     }
  1482. #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
  1483.     /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
  1484.     if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
  1485.       return TT_Err_Invalid_Size_Handle;
  1486.     if ( load_flags & FT_LOAD_SBITS_ONLY )
  1487.       return TT_Err_Invalid_Argument;
  1488.     error = tt_loader_init( &loader, size, glyph, load_flags );
  1489.     if ( error )
  1490.       return error;
  1491.     glyph->format        = FT_GLYPH_FORMAT_OUTLINE;
  1492.     glyph->num_subglyphs = 0;
  1493.     glyph->outline.flags = 0;
  1494.     /* main loading loop */
  1495.     error = load_truetype_glyph( &loader, glyph_index, 0 );
  1496.     if ( !error )
  1497.     {
  1498.       if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
  1499.       {
  1500.         glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
  1501.         glyph->subglyphs     = loader.gloader->base.subglyphs;
  1502.       }
  1503.       else
  1504.       {
  1505.         glyph->outline        = loader.gloader->base.outline;
  1506.         glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
  1507.         /* In case bit 1 of the `flags' field in the `head' table isn't */
  1508.         /* set, translate array so that (0,0) is the glyph's origin.    */
  1509.         if ( ( face->header.Flags & 2 ) == 0 && loader.pp1.x )
  1510.           FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
  1511.       }
  1512.       compute_glyph_metrics( &loader, glyph_index );
  1513.     }
  1514.     /* Set the `high precision' bit flag.                           */
  1515.     /* This is _critical_ to get correct output for monochrome      */
  1516.     /* TrueType glyphs at all sizes using the bytecode interpreter. */
  1517.     /*                                                              */
  1518.     if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
  1519.          size->root.metrics.y_ppem < 24     )
  1520.       glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
  1521.     return error;
  1522.   }
  1523. /* END */