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

  1. /*******************************************************************
  2.  *
  3.  *  ttgload.c                                                   1.0
  4.  *
  5.  *    TrueType Glyph Loader.                           
  6.  *
  7.  *  Copyright 1996, 1997 by
  8.  *  David Turner, Robert Wilhelm, and Werner Lemberg.
  9.  *
  10.  *  This file is part of the FreeType project, and may only be used
  11.  *  modified and distributed under the terms of the FreeType project
  12.  *  license, LICENSE.TXT. By continuing to use, modify or distribute
  13.  *  this file you indicate that you have read the license and
  14.  *  understand and accept it fully.
  15.  *
  16.  *
  17.  ******************************************************************/
  18.  
  19. #include "tttypes.h"
  20. #include "tterror.h"
  21. #include "ttcalc.h"
  22. #include "ttfile.h"
  23.  
  24. #include "tttables.h"
  25. #include "ttobjs.h"
  26. #include "ttgload.h"
  27.  
  28. #include "ttmemory.h"
  29. #include "tttags.h"
  30. #include "ttload.h"
  31.  
  32.   /* composite font flags */
  33.   
  34.   #define ARGS_ARE_WORDS       0x001
  35.   #define ARGS_ARE_XY_VALUES   0x002
  36.   #define ROUND_XY_TO_GRID     0x004
  37.   #define WE_HAVE_A_SCALE      0x008
  38.   /* reserved                  0x010 */
  39.   #define MORE_COMPONENTS      0x020
  40.   #define WE_HAVE_AN_XY_SCALE  0x040
  41.   #define WE_HAVE_A_2X2        0x080
  42.   #define WE_HAVE_INSTR        0x100
  43.   #define USE_MY_METRICS       0x200
  44.   
  45.   /* end composite */
  46.  
  47.  
  48.  static void  Get_HMetrics( PFace  face,
  49.                             Int    index,
  50.                             Int*   lsb,
  51.                             Int*   aw    )
  52.  {
  53.    Int k;
  54.  
  55.    k = face->horizontalHeader.number_Of_HMetrics;
  56.    if ( index < k )
  57.    {
  58.      *lsb = face->longHMetrics[index].lsb;
  59.      *aw  = face->longHMetrics[index].advance_Width;
  60.    }
  61.    else
  62.    {
  63.      *lsb = face->shortMetrics[index-k];
  64.      *aw  = face->longHMetrics[k-1].advance_Width;
  65.    }
  66.  }
  67.  
  68.  
  69.  
  70.  static
  71.  TT_Error  Load_Simple_Glyph( PExecution_Context  exec,
  72.                               TT_Stream           input,
  73.                               Int                 n_contours,
  74.                               Int                 left_contours,
  75.                               Int                 left_points,
  76.                               Int                 load_flags,
  77.                               PSubglyph_Record    subg )
  78.  {
  79.    DEFINE_LOAD_LOCALS(input);
  80.  
  81.    Int   k, n_points, n_ins;
  82.    Byte  c, cnt;
  83.  
  84.    PFace  face;
  85.  
  86.    PCoordinates  xs, ys;
  87.    PTouchTable   flag;
  88.  
  89.    TT_F26Dot6  x, y, xmin, ymin, xmax, ymax;
  90.  
  91.    PVecRecord  pts;
  92.  
  93.    Int  leftSideBearing;
  94.    Int  advanceWidth;
  95.  
  96.    face   = exec->owner;
  97.  
  98.    /* simple check */
  99.  
  100.    if ( n_contours > left_contours )
  101.    {
  102.      DebugTrace(( "ERROR: Glyph index %d has %d contours > left %d\n",
  103.                   subg->index, n_contours, left_contours ));
  104.      return TT_Err_Too_Many_Contours;
  105.    }
  106.  
  107.    /* preparing the execution context */
  108.  
  109.    exec->pts.n     = 0;
  110.    exec->pts.org_x = subg->org_x + subg->n_points;
  111.    exec->pts.org_y = subg->org_y + subg->n_points;
  112.    exec->pts.cur_x = subg->cur_x + subg->n_points;
  113.    exec->pts.cur_y = subg->cur_y + subg->n_points;
  114.    exec->pts.touch = subg->flag  + subg->n_points;
  115.  
  116.    exec->numContours = 0;
  117.    exec->endContours = subg->contours + subg->n_contours;
  118.  
  119.    /* reading the contours endpoints */
  120.  
  121.    if ( ACCESS_Frame( (n_contours+1)*2L ) )
  122.      return error;
  123.  
  124.    n_points = 0;
  125.  
  126.    for ( k=0; k < n_contours; k++ )
  127.    {
  128.      DebugTrace(( "%d ", n_points ));
  129.      exec->endContours[k] = n_points = GET_Short();
  130.      n_points++;
  131.    }
  132.  
  133.    n_ins = GET_Short();
  134.  
  135.    FORGET_Frame();
  136.  
  137.    if ( n_points > left_points )
  138.    {
  139.      DebugTrace(( "ERROR : Too many points in glyph %d\n", subg->index ));
  140.      return TT_Err_Too_Many_Points;
  141.    }
  142.  
  143.    /* loading instructions */
  144.  
  145.    DebugTrace(("Instructions size : %d\n", n_ins ));
  146.  
  147.    if ( n_ins > face->maxProfile.maxSizeOfInstructions )
  148.    {
  149.      DebugTrace(("That's too many !!\n"));
  150.      return TT_Err_Too_Many_Ins;
  151.    }
  152.  
  153.    if ( FILE_Read( exec->glyphIns,  n_ins ) )
  154.      return error;
  155.  
  156.    exec->glyphSize = n_ins;
  157.  
  158.    if ( (error = Set_CodeRange( exec, 
  159.                                 TT_CodeRange_Glyph, 
  160.                                 exec->glyphIns, 
  161.                                 exec->glyphSize )) )
  162.      return error;  
  163.  
  164.    /* read the flags */
  165.  
  166.    if ( CHECK_ACCESS_Frame( n_points * 5L ) )
  167.      return error;
  168.  
  169.    k    = 0;
  170.    flag = exec->pts.touch;
  171.  
  172.    while ( k < n_points )
  173.    {
  174.      flag[k] = c = GET_Byte();
  175.      k++;
  176.  
  177.      if ( c & 8 )
  178.      {
  179.        cnt = GET_Byte();
  180.        while( cnt > 0 )
  181.        {
  182.          flag[k++] = c;
  183.          cnt--;
  184.        }
  185.      }
  186.    }
  187.  
  188.    /* read the X */
  189.  
  190.    x    = 0;
  191.    xmin = 0;
  192.    xmax = 0;
  193.    xs   = exec->pts.org_x;
  194.  
  195.    for ( k = 0; k < n_points; k++ )
  196.    {
  197.      if ( flag[k] & 2 )
  198.      {
  199.        if ( flag[k] & 16 )
  200.          x += GET_Byte();
  201.        else
  202.          x -= GET_Byte();
  203.      }
  204.      else
  205.      {
  206.        if ( (flag[k] & 16) == 0 )
  207.          x += GET_Short();
  208.      }
  209.  
  210.      xs[k] = x;
  211.  
  212.      if ( x < xmin ) xmin = x;
  213.      if ( x > xmax ) xmax = x;
  214.    }
  215.  
  216.    /* read the Y */
  217.  
  218.    y    = 0;
  219.    ymin = 0;
  220.    ymax = 0;
  221.    ys   = exec->pts.org_y;
  222.  
  223.    for ( k = 0; k < n_points; k++ )
  224.    {
  225.      if ( flag[k] & 4 )
  226.      {
  227.        if ( flag[k] & 32 )
  228.          y += GET_Byte();
  229.        else
  230.          y -= GET_Byte();
  231.      }
  232.      else
  233.      {
  234.        if ( (flag[k] & 32) == 0 )
  235.          y += GET_Short();
  236.      }
  237.  
  238.      ys[k] = y;
  239.  
  240.      if ( y < ymin ) ymin = y;
  241.      if ( y > ymax ) ymax = y;
  242.    }
  243.  
  244.    FORGET_Frame();
  245.  
  246.    /* Now adds the two shadow points at n and n+1     */
  247.    /* We need the left side bearing and advance width */
  248.  
  249.    Get_HMetrics( face, subg->index, &leftSideBearing, &advanceWidth );
  250.  
  251.    subg->leftSideBearing = leftSideBearing;
  252.    subg->advanceWidth    = advanceWidth;
  253.  
  254.    xs[n_points] = subg->xMin - leftSideBearing;
  255.    ys[n_points] = 0;
  256.    /* pp1 = xMin - lsb */
  257.  
  258.    xs[n_points+1] = xs[n_points] + advanceWidth;
  259.    ys[n_points+1] = 0;
  260.    /* pp2 = pp1 + aw */
  261.  
  262.    /* clear the touch flags */
  263.  
  264.    for ( k = 0; k < n_points; k++ )
  265.      exec->pts.touch[k] &= TT_Flag_On_Curve;
  266.  
  267.    exec->pts.touch[n_points  ] = 0;
  268.    exec->pts.touch[n_points+1] = 0;
  269.  
  270.    /* Note that we return two more points that are not */
  271.    /* part of the glyph outline                        */
  272.  
  273.    n_points += 2;
  274.  
  275.    /* now eventually scale and hint the glyph */
  276.  
  277.    pts    = &exec->pts;
  278.    pts->n = n_points;
  279.  
  280.    exec->numContours = n_contours;
  281.  
  282.    if ( (load_flags & TTLOAD_SCALE_GLYPH) == 0 )
  283.    {
  284.      /* no scaling, just copy the org arrays into the cur ones */
  285.  
  286.      for ( k = 0; k < n_points; k++ )
  287.      {
  288.        pts->cur_x[k] = pts->org_x[k];
  289.        pts->cur_y[k] = pts->org_y[k];
  290.      }
  291.    }
  292.    else
  293.    {
  294.      /* first scale the glyph points */
  295.  
  296.      for ( k = 0; k < n_points; k++ )
  297.      {
  298.        x = MulDiv_Round( pts->org_x[k],
  299.              exec->metrics.x_scale1, 
  300.              exec->metrics.x_scale2 );
  301.  
  302.        y = MulDiv_Round( pts->org_y[k], 
  303.              exec->metrics.y_scale1, 
  304.              exec->metrics.y_scale2 );
  305.  
  306.        pts->org_x[k] = x;
  307.        pts->org_y[k] = y;
  308.        pts->cur_x[k] = x;
  309.        pts->cur_y[k] = y;
  310.      }
  311.  
  312.      /* scale advance width and left side bearing too */
  313.  
  314.      subg->leftSideBearing = MulDiv_Round( leftSideBearing,
  315.                        exec->metrics.x_scale1,
  316.                        exec->metrics.x_scale2 ) & -64;
  317.  
  318.      subg->advanceWidth = ( MulDiv_Round( advanceWidth,
  319.                       exec->metrics.x_scale1,
  320.                       exec->metrics.x_scale2 )+32 ) & -64;
  321.  
  322.      /* then round the phantom points. This is critical for correct */
  323.      /* hinting at low ppems                                        */
  324.  
  325.      pts->cur_x[n_points-2] =   pts->cur_x[n_points-2] & -64;
  326.      pts->cur_x[n_points-1] = ( pts->cur_x[n_points-1] + 32 ) & -64;
  327.  
  328.      /* now consider hinting */
  329.  
  330.      if ( subg->is_hinted && n_ins > 0 )
  331.        if ( (error = Context_Run( exec, FALSE )) )
  332.          return error;
  333.  
  334.      /* adjust advance width to its grid-fitted value */
  335.  
  336.      subg->advanceWidth += pts->cur_x[n_points-1] -
  337.                            pts->org_x[n_points-1];
  338.    }
  339.  
  340.    return TT_Err_Ok;
  341.  }
  342.  
  343.  
  344.  static
  345.  TT_Error  Load_Composite_Instructions( Int                 n_points,
  346.                                         Int                 n_contours,
  347.                                         PExecution_Context  exec,
  348.                                         PSubglyph_Record    subg )
  349.  {
  350.    Int  k;
  351.  
  352.    PVecRecord  pts;
  353.    TT_Error       error;
  354.  
  355.    /* prepare the execution context */
  356.  
  357.    exec->pts.n     = n_points+2;
  358.    exec->pts.org_x = subg->org_x;
  359.    exec->pts.org_y = subg->org_y;
  360.    exec->pts.cur_x = subg->cur_x;
  361.    exec->pts.cur_y = subg->cur_y;
  362.    exec->pts.touch = subg->flag;
  363.  
  364.    exec->numContours = n_contours;
  365.    exec->endContours = subg->contours;
  366.  
  367.    pts = &exec->pts;
  368.  
  369.    /* add phantom points */
  370.  
  371.    pts->cur_x[n_points] = subg->xMin - subg->leftSideBearing;
  372.    pts->cur_y[n_points] = 0;
  373.    /* pp1 = xMin - lsb */
  374.  
  375.    pts->cur_x[n_points+1] = subg->xMin - subg->leftSideBearing +
  376.                             subg->advanceWidth;
  377.    pts->cur_y[n_points+1] = 0;
  378.    /* pp2 = pp1 + aw */
  379.  
  380.    for ( k = 0; k < n_points+2; k++ )
  381.    {
  382.      pts->org_x[k] = pts->cur_x[k];
  383.      pts->org_y[k] = pts->cur_y[k];
  384.      pts->touch[k] = pts->touch[k] & TT_Flag_On_Curve;
  385.    }
  386.  
  387.    if ( (error = Set_CodeRange( exec, 
  388.                                 TT_CodeRange_Glyph, 
  389.                                 exec->glyphIns, 
  390.                                 exec->glyphSize )) )
  391.      return error;  
  392.  
  393.    /* now consider hinting */
  394.  
  395.    if ( subg->is_hinted && 
  396.         exec->glyphSize > 0 )
  397.      return Context_Run( exec, FALSE );
  398.    else
  399.      return TT_Err_Ok;
  400.  }
  401.  
  402.  
  403.  static
  404.  void Init_Glyph_Component( PSubglyph_Record    element,
  405.                             PSubglyph_Record    original,
  406.                             PExecution_Context  exec )
  407.  {
  408.    Int  n;
  409.  
  410.    element->index     = -1;
  411.    element->is_scaled = FALSE;
  412.  
  413.    element->n_contours = 0;
  414.    element->n_points   = 0;
  415.  
  416.    if (original)
  417.    {
  418.      element->is_hinted = original->is_hinted;
  419.  
  420.      n = original->n_points;
  421.      element->org_x = original->org_x + n;
  422.      element->org_y = original->org_y + n;
  423.      element->cur_x = original->cur_x + n;
  424.      element->cur_y = original->cur_y + n;
  425.      element->flag  = original->flag  + n;
  426.  
  427.      n = original->n_contours;
  428.      element->contours = original->contours + n;
  429.    }
  430.    else
  431.    {
  432.      element->is_hinted = FALSE;
  433.  
  434.      element->org_x = exec->pts.org_x;
  435.      element->org_y = exec->pts.org_y;
  436.      element->cur_x = exec->pts.cur_x;
  437.      element->cur_y = exec->pts.cur_y;
  438.      element->flag  = exec->pts.touch;
  439.  
  440.      element->contours = exec->endContours;
  441.    }
  442.  
  443.    element->arg1 = 0;
  444.    element->arg2 = 0;
  445.  
  446.    element->element_flag = 0;
  447.  
  448.    element->transform.xx = 1 << 16;
  449.    element->transform.xy = 0;
  450.    element->transform.yx = 0;
  451.    element->transform.yy = 1 << 16;
  452.  
  453.    element->transform.ox = 0;
  454.    element->transform.oy = 0;
  455.  
  456.    element->leftSideBearing = 0;
  457.    element->advanceWidth    = 0;
  458.  }
  459.  
  460.  
  461.   TT_Error  Load_TrueType_Glyph(  PInstance   instance,
  462.                                   PGlyph      glyph,
  463.                                   Int         glyph_index,
  464.                                   Int         load_flags )
  465.   {
  466.     enum _TPhases
  467.     {
  468.       Load_Exit,
  469.       Load_Glyph,
  470.       Load_Simple,
  471.       Load_Composite,
  472.       Load_End
  473.     };
  474.     typedef enum _TPhases  TPhases;
  475.  
  476.     DEFINE_ALL_LOCALS;
  477.  
  478.     PFace   face;
  479.  
  480.     Int  num_points;
  481.     Int  num_contours;
  482.     Int  left_points;
  483.     Int  left_contours;
  484.  
  485.     Int  table, index, load_top, new_flags, k, l;
  486.  
  487.     Long  glyph_offset, offset;
  488.  
  489.     TT_F26Dot6  x, y, nx, ny;
  490.  
  491.     TT_F26Dot6  xmin, xmax, ymin, ymax;
  492.  
  493.     Fixed  xx, xy, yx, yy;
  494.  
  495.     PExecution_Context  exec;
  496.  
  497.     PSubglyph_Record  subglyph, subglyph2;
  498.  
  499.     TVecRecord  base_pts;
  500.     Int           base_n_contours;
  501.     PUShort       base_contours;
  502.  
  503.     TPhases       phase;
  504.  
  505.     /* first of all, check arguments */
  506.  
  507.     if ( !instance || !instance->owner )
  508.       return TT_Err_Invalid_Face_Handle;
  509.  
  510.     face = instance->owner;
  511.  
  512.     if (glyph_index < 0 || glyph_index >= face->numGlyphs )
  513.       return TT_Err_Invalid_Glyph_Index;
  514.  
  515.     table = LookUp_TrueType_Table( face, TTAG_glyf );
  516.     if (table < 0)
  517.     {
  518.       DebugTrace(( "ERROR : there is no glyph table in this font file !!\n" ));
  519.       return TT_Err_Table_Missing;
  520.     }
  521.  
  522.     glyph_offset = face->dirTables[table].Offset;
  523.  
  524.     /* query new execution context */
  525.  
  526.     if (instance->debug)
  527.       exec = instance->context;
  528.     else
  529.       exec = New_Context(face);
  530.  
  531.     if (!exec)
  532.       return TT_Err_Out_Of_Memory;
  533.  
  534.     Context_Load( exec, instance );
  535.  
  536.     if ( instance->GS.instruct_control & 2 )
  537.       exec->GS = Default_GraphicsState;
  538.     else
  539.       exec->GS = instance->GS;
  540.     /* load default graphics state */
  541.  
  542.     /* save its critical pointers, as they'll be modified during load */
  543.  
  544.     base_pts        = exec->pts;
  545.     base_n_contours = exec->numContours;
  546.     base_contours   = exec->endContours;
  547.  
  548.     /* init variables */
  549.  
  550.     left_points   = face->maxPoints;
  551.     left_contours = face->maxContours;
  552.  
  553.     num_points   = 0;
  554.     num_contours = 0;
  555.  
  556.     load_top = 0;
  557.     subglyph = exec->loadStack;
  558.  
  559.     Init_Glyph_Component( subglyph, NULL, exec );
  560.  
  561.     subglyph->index     = glyph_index;
  562.     subglyph->is_hinted = load_flags & TTLOAD_HINT_GLYPH;
  563.  
  564.     /* when the cvt program has disabled hinting, the argument */
  565.     /* is ignored                                              */
  566.     if ( instance->GS.instruct_control & 1 )
  567.       subglyph->is_hinted = FALSE;
  568.  
  569.     /* now access stream */
  570.  
  571.     if ( USE_Stream( face->stream, stream ) )
  572.       goto Fin;
  573.  
  574.     /* Main loading loop */
  575.  
  576.     phase = Load_Glyph;
  577.  
  578.     while ( phase != Load_Exit )
  579.     {
  580.       subglyph = exec->loadStack + load_top;
  581.  
  582.       switch (phase)
  583.       {
  584.         /************************************************************/
  585.         /*                                                          */
  586.         /* Load_Glyph state                                         */
  587.         /*                                                          */
  588.         /*   reading a glyph's generic header to determine          */
  589.         /*   wether it's simple or composite                        */
  590.         /*                                                          */
  591.         /* exit states : Load_Simple and Load_Composite             */
  592.         /*                                                          */
  593.   
  594.         case Load_Glyph:
  595.           /* check glyph index and table */
  596.  
  597.           index = subglyph->index;
  598.  
  599.           if ( index < 0 || index >= face->numGlyphs)
  600.           {
  601.             error = TT_Err_Invalid_Glyph_Index;
  602.             goto Fail;
  603.           }
  604.  
  605.           /* get horizontal metrics */
  606.  
  607.           Get_HMetrics( face, index, &k, &l );
  608.  
  609.           if (load_flags & TTLOAD_SCALE_GLYPH)
  610.           {
  611.             k = MulDiv_Round( k, 
  612.                   exec->metrics.x_scale1, 
  613.                   exec->metrics.x_scale2 );
  614.  
  615.             l = MulDiv_Round( l, 
  616.                   exec->metrics.x_scale1, 
  617.                   exec->metrics.x_scale2 );
  618.           }
  619.  
  620.           subglyph->leftSideBearing = k;
  621.           subglyph->advanceWidth    = l;
  622.  
  623.           /* load glyph */
  624.  
  625.           if ( index+1 < face->numLocations &&
  626.                face->glyphLocations[index] == face->glyphLocations[index+1] )
  627.           {
  628.             /* as described by Frederic Loyer, these are spaces, and */
  629.             /* not the unknown glyph                                 */
  630.  
  631.             num_contours = 0;
  632.             num_points   = 0;
  633.  
  634.             subglyph->xMin = 0;
  635.             subglyph->xMax = 0;
  636.             subglyph->yMin = 0;
  637.             subglyph->yMax = 0;
  638.  
  639.             phase = Load_End;
  640.  
  641.             break;
  642.           }
  643.  
  644.           offset = glyph_offset + face->glyphLocations[index];
  645.  
  646.           /* read first glyph header */
  647.           if ( FILE_Seek( offset ) ||
  648.                ACCESS_Frame( 10L ) )
  649.             goto Fail_File;
  650.  
  651.           num_contours   = GET_Short();
  652.           subglyph->xMin = GET_Short();
  653.           subglyph->yMin = GET_Short();
  654.           subglyph->xMax = GET_Short();
  655.           subglyph->yMax = GET_Short();
  656.  
  657.           FORGET_Frame();
  658.  
  659.           DebugTrace(( "Glyph %d\n", index ));
  660.           DebugTrace(( " # of contours : %d\n", num_contours ));
  661.           DebugTrace(( " xMin : %4d  xMax : %4d\n", 
  662.                        subglyph->xMin, 
  663.                        subglyph->xMax ));
  664.           DebugTrace(( " yMin : %4d  yMax : %4d\n", 
  665.                        subglyph->yMin, 
  666.                        subglyph->yMax ));
  667.           DebugTrace(( "-" ));
  668.  
  669.           if ( num_contours > left_contours )
  670.           {
  671.             DebugTrace(( "ERROR : Too many contours for glyph %d\n", index ));
  672.             error = TT_Err_Too_Many_Contours;
  673.             goto Fail;
  674.           }
  675.  
  676.           /* is it a simple glyph ? */
  677.  
  678.           if ( num_contours > 0 )
  679.             phase = Load_Simple;
  680.           else
  681.             phase = Load_Composite;
  682.  
  683.           break;
  684.  
  685.         /************************************************************/
  686.         /*                                                          */
  687.         /* Load_Simple state                                        */
  688.         /*                                                          */
  689.         /*   reading a simple glyph (num_contours must be set to    */
  690.         /*   the glyph's number of contours..)                      */
  691.         /*                                                          */
  692.         /* exit states : Load_End                                   */
  693.         /*                                                          */
  694.  
  695.         case Load_Simple:
  696.           new_flags = load_flags;
  697.  
  698.           if ( !subglyph->is_hinted )
  699.             new_flags &= ~TTLOAD_HINT_GLYPH;
  700.           /* disable hinting when scaling */
  701.  
  702.           error = Load_Simple_Glyph(
  703.                       exec,
  704.               stream,
  705.                       num_contours,
  706.                       left_contours,
  707.                       left_points,
  708.                       new_flags,
  709.                       subglyph );
  710.  
  711.           if (error)
  712.             goto Fail;
  713.           /* Note : We could have put the simple loader source there */
  714.           /*        but the code is fat enough already :-)           */
  715.  
  716.           num_points = exec->pts.n - 2;
  717.  
  718.           phase = Load_End;
  719.           break;
  720.  
  721.         /************************************************************/
  722.         /*                                                          */
  723.         /* Load_Composite state                                     */
  724.         /*                                                          */
  725.         /*   reading a composite glyph header a pushing a new       */
  726.         /*   load element on the stack..                            */
  727.         /*                                                          */
  728.         /* exit states : Load_Glyph                                 */
  729.         /*                                                          */
  730.  
  731.         case Load_Composite:
  732.  
  733.           /* create a new element on the stack */
  734.           load_top++;
  735.  
  736.           if ( load_top > face->maxComponents )
  737.           {
  738.             error = TT_Err_Invalid_Composite;
  739.             goto Fail;
  740.           }
  741.  
  742.           subglyph2 = exec->loadStack + load_top;
  743.  
  744.           Init_Glyph_Component( subglyph2, subglyph, NULL );
  745.  
  746.           /* now read composite header */
  747.  
  748.           if ( ACCESS_Frame(4) )
  749.             goto Fail_File;
  750.  
  751.           subglyph->element_flag = new_flags = GET_UShort();
  752.  
  753.           subglyph2->index = GET_UShort();
  754.  
  755.           FORGET_Frame();
  756.  
  757.           k = 2;
  758.  
  759.           if ( new_flags & ARGS_ARE_WORDS )
  760.             k += 2;
  761.  
  762.           if ( new_flags & WE_HAVE_A_SCALE )
  763.             k += 2;
  764.  
  765.           if ( new_flags & WE_HAVE_AN_XY_SCALE )
  766.             k += 4;
  767.  
  768.           if ( new_flags & WE_HAVE_A_2X2 )
  769.             k += 8;
  770.  
  771.           if ( ACCESS_Frame( k ) )
  772.             goto Fail_File;
  773.  
  774.           if ( new_flags & ARGS_ARE_WORDS )
  775.           {
  776.             k = GET_Short();
  777.             l = GET_Short();
  778.           }
  779.           else
  780.           {
  781.             l = GET_UShort();
  782.             k = (signed char)(l >> 8);
  783.             l = (signed char)(l & 0xFF);
  784.           }
  785.  
  786.           subglyph->arg1 = k;
  787.           subglyph->arg2 = l;
  788.  
  789.           if ( new_flags & ARGS_ARE_XY_VALUES )
  790.           {
  791.             subglyph->transform.ox = k;
  792.             subglyph->transform.oy = l;
  793.           }
  794.  
  795.           xx = 1 << 16;
  796.           xy = 0;
  797.           yx = 0;
  798.           yy = 1 << 16;
  799.  
  800.           if ( new_flags & WE_HAVE_A_SCALE )
  801.           {
  802.             xx = (Fixed)GET_Short() << 2;
  803.             yy = xx;
  804.             subglyph2->is_scaled = TRUE;
  805.           }
  806.           else if ( new_flags & WE_HAVE_AN_XY_SCALE )
  807.           {
  808.             xx = (Fixed)GET_Short() << 2;
  809.             yy = (Fixed)GET_Short() << 2;
  810.             subglyph2->is_scaled = TRUE;
  811.           }
  812.           else if ( new_flags & WE_HAVE_A_2X2 )
  813.           {
  814.             xx = (Fixed)GET_Short() << 2;
  815.             xy = (Fixed)GET_Short() << 2;
  816.             yx = (Fixed)GET_Short() << 2;
  817.             yy = (Fixed)GET_Short() << 2;
  818.             subglyph2->is_scaled = TRUE;
  819.           }
  820.  
  821.           FORGET_Frame();
  822.  
  823.           subglyph->transform.xx = xx;
  824.           subglyph->transform.xy = xy;
  825.           subglyph->transform.yx = yx;
  826.           subglyph->transform.yy = yy;
  827.  
  828.           k = MulDiv_Round( xx, yy, 1 << 16 ) -
  829.               MulDiv_Round( xy, yx, 1 << 16 );
  830.  
  831.           if ( k < -(1 << 16) || k > (1 << 16) )
  832.             subglyph2->is_hinted = FALSE;
  833.           /* disable hinting in case of scaling/slanting */
  834.  
  835.           subglyph->file_offset = FILE_Pos();
  836.  
  837.           phase = Load_Glyph;
  838.           break;
  839.  
  840.         /************************************************************/
  841.         /*                                                          */
  842.         /* Load_End state                                           */
  843.         /*                                                          */
  844.         /*   after loading a glyph, apply transform and offset      */
  845.         /*   where necessary, pops element and continue or          */
  846.         /*   stop process..                                         */
  847.         /*                                                          */
  848.         /* exit states : Load_Composite and Load_Exit               */
  849.         /*                                                          */
  850.  
  851.         case Load_End:
  852.           if (load_top > 0)
  853.           {
  854.             subglyph2 = subglyph;
  855.  
  856.             load_top--;
  857.             subglyph = exec->loadStack + load_top;
  858.  
  859.             /* check advance width and left side bearing */
  860.  
  861.             if ( subglyph->element_flag & USE_MY_METRICS  ||
  862.                  subglyph->advanceWidth == 0 )
  863.             {
  864.               subglyph->leftSideBearing = subglyph2->leftSideBearing;
  865.               subglyph->advanceWidth    = subglyph2->advanceWidth;
  866.             }
  867.  
  868.             /* apply scale */
  869.  
  870.             if (subglyph2->is_scaled)
  871.             {
  872.               for ( k = 0; k < num_points; k++ )
  873.               {
  874.                 x = subglyph2->cur_x[k];
  875.                 y = subglyph2->cur_y[k];
  876.  
  877.                 nx = MulDiv_Round( x, subglyph->transform.xx, 1 << 16 ) +
  878.                      MulDiv_Round( y, subglyph->transform.yx, 1 << 16 );
  879.  
  880.                 ny = MulDiv_Round( x, subglyph->transform.xy, 1 << 16 ) +
  881.                      MulDiv_Round( y, subglyph->transform.yy, 1 << 16 );
  882.  
  883.                 subglyph2->cur_x[k] = nx;
  884.                 subglyph2->cur_y[k] = ny;
  885.  
  886.                 x = subglyph2->org_x[k];
  887.                 y = subglyph2->org_y[k];
  888.  
  889.                 nx = MulDiv_Round( x, subglyph->transform.xx, 1 << 16 ) +
  890.                      MulDiv_Round( y, subglyph->transform.yx, 1 << 16 );
  891.  
  892.                 ny = MulDiv_Round( x, subglyph->transform.xy, 1 << 16 ) +
  893.                      MulDiv_Round( y, subglyph->transform.yy, 1 << 16 );
  894.  
  895.                 subglyph2->org_x[k] = nx;
  896.                 subglyph2->org_y[k] = ny;
  897.               }
  898.             }
  899.  
  900.             /* adjust counts */
  901.  
  902.             for ( k = 0; k < num_contours; k++ )
  903.               subglyph2->contours[k] += subglyph->n_points;
  904.  
  905.             subglyph->n_points   += num_points;
  906.             subglyph->n_contours += num_contours;
  907.  
  908.             left_points   -= num_points;
  909.             left_contours -= num_contours;
  910.  
  911.             /* apply offset */
  912.  
  913.             if ( !(subglyph->element_flag & ARGS_ARE_XY_VALUES) )
  914.             {
  915.               k = subglyph->arg1;
  916.               l = subglyph->arg2;
  917.  
  918.               if ( k < 0 || k >= subglyph->n_points ||
  919.                    l < 0 || l >= subglyph->n_points )
  920.               {
  921.                 error = TT_Err_Invalid_Composite;
  922.                 goto Fail;
  923.               }
  924.  
  925.               subglyph->transform.ox = subglyph->org_x[l] -
  926.                                        subglyph->org_x[k];
  927.  
  928.               subglyph->transform.oy = subglyph->org_y[l] -
  929.                                        subglyph->org_y[k];
  930.             }
  931.  
  932.             x = subglyph->transform.ox;
  933.             y = subglyph->transform.oy;
  934.  
  935.             if ( load_flags & TTLOAD_SCALE_GLYPH )
  936.             {
  937.               x = MulDiv_Round( x, 
  938.                 exec->metrics.x_scale1, 
  939.                 exec->metrics.x_scale2 );
  940.  
  941.               y = MulDiv_Round( y, 
  942.                 exec->metrics.y_scale1, 
  943.                 exec->metrics.y_scale2 );
  944.             }
  945.  
  946.             if ( subglyph->element_flag & ARGS_ARE_XY_VALUES  &&
  947.                  subglyph->element_flag & ROUND_XY_TO_GRID )
  948.             {
  949.               x = ROUND_F26DOT6(x);
  950.               y = ROUND_F26DOT6(y);
  951.             }
  952.  
  953.             for ( k = 0; k < num_points; k++ )
  954.             {
  955.               subglyph2->org_x[k] += x;
  956.               subglyph2->org_y[k] += y;
  957.               subglyph2->cur_x[k] += x;
  958.               subglyph2->cur_y[k] += y;
  959.             }
  960.  
  961.             num_points   = subglyph->n_points;
  962.             num_contours = subglyph->n_contours;
  963.  
  964.             /* check for last component */
  965.  
  966.             if ( FILE_Seek( subglyph->file_offset ) )
  967.               goto Fail_File;
  968.  
  969.             if ( subglyph->element_flag & MORE_COMPONENTS )
  970.               phase = Load_Composite;
  971.             else
  972.             {
  973.               if ( subglyph->is_hinted    &&
  974.                    subglyph->element_flag & WE_HAVE_INSTR )
  975.               {
  976.                 if ( ACCESS_Frame(2) )
  977.                   goto Fail;
  978.  
  979.                 k = GET_UShort();
  980.                 /* read size of instructions */
  981.  
  982.                 FORGET_Frame();
  983.  
  984.                 DebugTrace(( "Instructions size = %d\n", k ));
  985.  
  986.                 if ( k > face->maxProfile.maxSizeOfInstructions )
  987.                 {
  988.                   DebugTrace(( "Too many instructions\n" ));
  989.                   error = TT_Err_Too_Many_Ins;
  990.                   goto Fail;
  991.                 }
  992.  
  993.                 if ( FILE_Read( exec->glyphIns, k ) )
  994.                   goto Fail;
  995.  
  996.                 exec->glyphSize = k;
  997.                 
  998.                 error = Load_Composite_Instructions( num_points,
  999.                                                      num_contours,
  1000.                                                      exec,
  1001.                                                      subglyph );
  1002.                 if (error) goto Fail;
  1003.               }
  1004.  
  1005.               phase = Load_End;
  1006.             }
  1007.  
  1008.           }
  1009.           else
  1010.             phase = Load_Exit;
  1011.  
  1012.           break;
  1013.  
  1014.       case Load_Exit:
  1015.     break;
  1016.       } 
  1017.     }
  1018.  
  1019.     /* finally, copy the points arrays to the glyph object */
  1020.  
  1021.     exec->pts         = base_pts;
  1022.     exec->numContours = base_n_contours;
  1023.     exec->endContours = base_contours;
  1024.  
  1025.     if (num_points > 0)
  1026.     {
  1027.       xmin = xmax = exec->pts.cur_x[0];
  1028.       ymin = ymax = exec->pts.cur_y[0];
  1029.  
  1030.       for ( k = 1; k < num_points; k++ )
  1031.       {
  1032.         x = exec->pts.cur_x[k];
  1033.         if ( x < xmin ) xmin = x;
  1034.         if ( x > xmax ) xmax = x;
  1035.  
  1036.         y = exec->pts.cur_y[k];
  1037.         if ( y < ymin ) ymin = y;
  1038.         if ( y > ymax ) ymax = y;
  1039.       }
  1040.  
  1041.       subglyph->xMin = xmin;
  1042.       subglyph->xMax = xmax;
  1043.       subglyph->yMin = ymin;
  1044.       subglyph->yMax = ymax;
  1045.     }
  1046.  
  1047.     num_points += 2;
  1048.  
  1049.     for ( k = 0; k < num_points-1; k++ )
  1050.     {
  1051.       glyph->x_coord[k] = exec->pts.cur_x[k];
  1052.       glyph->y_coord[k] = exec->pts.cur_y[k];
  1053.       glyph->touch  [k] = exec->pts.touch[k];
  1054.     }
  1055.  
  1056.     for ( k = 0; k < num_contours; k++ )
  1057.       glyph->endContours[k] = exec->endContours[k];
  1058.  
  1059.     glyph->num_points   = num_points;
  1060.     glyph->num_contours = num_contours;
  1061.  
  1062.     glyph->leftSideBearing = subglyph->leftSideBearing;
  1063.     glyph->advanceWidth    = subglyph->advanceWidth;
  1064.  
  1065.     glyph->scan_type = exec->GS.scan_type;
  1066.  
  1067.     glyph->high_precision = ( instance->metrics.y_ppem < 24 );
  1068.     /* We use high precision whenever the render size is below 24 ppems */
  1069.  
  1070.     glyph->xMin = subglyph->xMin;
  1071.     glyph->yMin = subglyph->yMin;
  1072.     glyph->xMax = subglyph->xMax;
  1073.     glyph->yMax = subglyph->yMax;
  1074.  
  1075.     error = TT_Err_Ok;
  1076.  
  1077.   Fail_File:
  1078.   Fail:
  1079.     TT_Done_Stream( &stream );
  1080.  
  1081.   Fin:
  1082.  
  1083.     /* reset the execution context */
  1084.  
  1085.     exec->pts         = base_pts;
  1086.     exec->numContours = base_n_contours;
  1087.     exec->endContours = base_contours;
  1088.  
  1089.     if ( !instance->debug )
  1090.       Done_Context(exec);
  1091.  
  1092.     return error;
  1093.   }
  1094.  
  1095.