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

  1. /*******************************************************************
  2.  *
  3.  *  ttobjs.c                                                     1.0
  4.  *
  5.  *    Objects manager.        
  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. #include "ttobjs.h"
  19. #include "ttfile.h"
  20. #include "ttcalc.h"
  21. #include "ttmemory.h"
  22. #include "ttload.h"
  23. #include "ttinterp.h"
  24.  
  25. /* Add extensions definition */
  26. #ifdef TT_EXTEND_ENGINE
  27. #include "ttextend.h"
  28. #endif
  29.  
  30.  
  31. /*******************************************************************
  32.  *
  33.  *  Function    :  New_Context
  34.  *
  35.  *  Description :  Creates a new execution context for a given
  36.  *                 face objet.
  37.  *
  38.  ******************************************************************/
  39.  
  40.   PExecution_Context  New_Context( PFace  face )
  41.   {
  42.     PExecution_Context  exec;
  43.  
  44.     if (!face)
  45.       return NULL;
  46.  
  47.     CACHE_New( &face->contexts, exec, face );
  48.     return exec;
  49.   }
  50.  
  51. /*******************************************************************
  52.  *
  53.  *  Function    :  Done_Context
  54.  *
  55.  *  Description :  discards an execution context
  56.  *
  57.  ******************************************************************/
  58.  
  59.   TT_Error  Done_Context( PExecution_Context  exec )
  60.   {
  61.     if (!exec)
  62.       return TT_Err_Ok;
  63.  
  64.     return CACHE_Done( &exec->owner->contexts, exec );
  65.   }
  66.  
  67. /*******************************************************************
  68.  *
  69.  *  Function    :  New_Instance
  70.  *
  71.  *  Description :  Creates a new instance for a given face objet
  72.  *
  73.  ******************************************************************/
  74.  
  75.   PInstance  New_Instance( PFace  face )
  76.   {
  77.     PInstance  ins;
  78.  
  79.     if (!face)
  80.       return NULL;
  81.  
  82.     CACHE_New( &face->instances, ins, face );
  83.     return ins;
  84.   }
  85.  
  86. /*******************************************************************
  87.  *
  88.  *  Function    :  Done_Instance
  89.  *
  90.  *  Description :
  91.  *
  92.  ******************************************************************/
  93.  
  94.   TT_Error  Done_Instance( PInstance instance )
  95.   {
  96.     return CACHE_Done( &instance->owner->instances, instance );
  97.   }
  98.  
  99.  
  100.  
  101. /*******************************************************************
  102.  *                                                                 *
  103.  *                     CODERANGE FUNCTIONS                         *
  104.  *                                                                 *
  105.  *                                                                 *
  106.  *******************************************************************/
  107.  
  108. /*******************************************************************
  109.  *
  110.  *  Function    :  Goto_CodeRange
  111.  *
  112.  *  Description :  Switch to a new code range (updates Code and IP).
  113.  *
  114.  *  Input  :  exec    target execution context
  115.  *            range   new execution code range       
  116.  *            IP      new IP in new code range       
  117.  *
  118.  *  Output :  SUCCESS on success. FAILURE on error (no code range).
  119.  *
  120.  *****************************************************************/
  121.  
  122.   TT_Error  Goto_CodeRange( PExecution_Context exec, Int range, Int IP )
  123.   {
  124.     PCodeRange  cr;
  125.  
  126.     if ( range < 1 || range > 3 )
  127.       return TT_Err_Bad_Argument;
  128.  
  129.     cr = &exec->codeRangeTable[ range-1 ];
  130.  
  131.     if ( cr->Base == NULL )
  132.       return TT_Err_Invalid_Coderange;
  133.  
  134.     /* NOTE : Because the last instruction of a program may be a CALL */
  135.     /*        which will return to the first byte *after* the code    */
  136.     /*        range, we test for IP <= Size, instead of IP < Size.  */
  137.  
  138.     if ( IP > cr->Size )
  139.       return TT_Err_Code_Overflow;
  140.  
  141.     exec->code     = cr->Base;
  142.     exec->codeSize = cr->Size;
  143.     exec->IP       = IP;
  144.     exec->curRange = range;
  145.  
  146.     return TT_Err_Ok;
  147.   }
  148.  
  149. /*******************************************************************
  150.  *
  151.  *  Function    :  Get_CodeRange
  152.  *
  153.  *  Description :  Returns a pointer to a given code range. Should
  154.  *                 be used only by the debugger. Returns NULL if
  155.  *                 'range' is out of current bounds.
  156.  *
  157.  *  Input  :  exec    target execution context
  158.  *            range   new execution code range       
  159.  *
  160.  *  Output :  Pointer to the code range record. NULL on failure.
  161.  *
  162.  *****************************************************************/
  163.  
  164.   PCodeRange  Get_CodeRange( PExecution_Context exec, Int range )
  165.   {
  166.     if ( range < 1 || range > 3 )
  167.       return NULL;
  168.     else                /* arrays start with 1 in pas, and with 0 in c */
  169.       return &exec->codeRangeTable[ range-1 ];
  170.   }
  171.  
  172.  
  173. /*******************************************************************
  174.  *
  175.  *  Function    :  Set_CodeRange
  176.  *
  177.  *  Description :  Sets a code range.
  178.  *
  179.  *  Input  :  exec    target execution context
  180.  *            range   code range index
  181.  *            base    new code base
  182.  *            length  sange size in bytes
  183.  *
  184.  *  Output :  SUCCESS on success. FAILURE on error.
  185.  *
  186.  *****************************************************************/
  187.  
  188.   TT_Error  Set_CodeRange( PExecution_Context exec,
  189.                            Int                range,
  190.                            void*              base,
  191.                            Int                length )
  192.   {
  193.     if ( range < 1 || range > 3 )
  194.       return TT_Err_Bad_Argument;
  195.  
  196.     exec->codeRangeTable[ range-1 ].Base = (unsigned char*)base;
  197.     exec->codeRangeTable[ range-1 ].Size = length;
  198.  
  199.     return TT_Err_Ok;
  200.   }
  201.  
  202. /*******************************************************************
  203.  *
  204.  *  Function    :  Clear_CodeRange
  205.  *
  206.  *  Description :  clears a code range.
  207.  *
  208.  *  Input  :  exec    target execution context
  209.  *            range   code range index
  210.  *
  211.  *  Output :  SUCCESS on success. FAILURE on error.
  212.  *
  213.  *  Notes  : Does not set the Error variable.
  214.  *
  215.  *****************************************************************/
  216.  
  217.   TT_Error Clear_CodeRange( PExecution_Context exec, Int range )
  218.   {
  219.     if ( range < 1 || range > 3 )
  220.       return TT_Err_Bad_Argument;
  221.  
  222.     exec->codeRangeTable[ range-1 ].Base = NULL;
  223.     exec->codeRangeTable[ range-1 ].Size = 0;
  224.  
  225.     return TT_Err_Ok;
  226.   }
  227.  
  228.  
  229.  
  230. /*******************************************************************
  231.  *                                                                 *
  232.  *                EXECUTION CONTEXT ROUTINES                       *
  233.  *                                                                 *
  234.  *                                                                 *
  235.  *******************************************************************/
  236.  
  237. /*******************************************************************
  238.  *
  239.  *  Function    :  Context_Destroy
  240.  *
  241.  *****************************************************************/
  242.  
  243.  TT_Error  Context_Destroy( void* _context )
  244.  {
  245.    PExecution_Context  exec = (PExecution_Context)_context;
  246.  
  247.    if (!exec)
  248.      return TT_Err_Ok;
  249.  
  250.    /* free composite load stack */
  251.    FREE( exec->loadStack );
  252.  
  253.    /* contours array */
  254.    FREE( exec->endContours );
  255.    exec->numContours = 0;
  256.  
  257.    /* points zone */
  258.    FREE( exec->pts.touch );
  259.    FREE( exec->pts.cur_y );
  260.    FREE( exec->pts.cur_x );
  261.    FREE( exec->pts.org_y );
  262.    FREE( exec->pts.org_x );
  263.    exec->pts.n = 0;
  264.  
  265.    /* twilight zone */
  266.    FREE( exec->twilight.touch );
  267.    FREE( exec->twilight.cur_y );
  268.    FREE( exec->twilight.cur_x );
  269.    FREE( exec->twilight.org_y );
  270.    FREE( exec->twilight.org_x );
  271.    exec->twilight.n = 0;
  272.  
  273.    /* free stack */
  274.    FREE( exec->stack );
  275.    exec->stackSize = 0;
  276.  
  277.    /* free storage area */
  278.    FREE( exec->storage );
  279.    exec->storeSize = 0;
  280.  
  281.    /* free call stack */
  282.    FREE( exec->callStack );
  283.    exec->callSize = 0;
  284.    exec->callTop  = 0;
  285.  
  286.    /* free glyph code range */
  287.    FREE( exec->glyphIns );
  288.    exec->glyphSize = 0;
  289.  
  290.    exec->instance = NULL;
  291.    exec->owner    = NULL;
  292.  
  293.    return TT_Err_Ok;
  294.  }
  295.  
  296.  
  297. /*******************************************************************
  298.  *
  299.  *  Function    :  Context_Create
  300.  *
  301.  *****************************************************************/
  302.  
  303.  TT_Error  Context_Create( void* _context, void* _face )
  304.  {
  305.    PExecution_Context  exec = (PExecution_Context)_context;
  306.  
  307.    PFace        face = (PFace)_face;
  308.    TMaxProfile* maxp = &face->maxProfile;
  309.    TT_Error     error;
  310.    Int          n_points, n_twilight;
  311.  
  312.    exec->callSize  = 32;
  313.    exec->storeSize = maxp->maxStorage;
  314.    exec->stackSize = maxp->maxStackElements;
  315.    n_points        = face->maxPoints + 2;
  316.    n_twilight      = maxp->maxTwilightPoints;
  317.  
  318.    if ( ALLOC( exec->glyphIns, maxp->maxSizeOfInstructions )     ||
  319.         /* reserve glyph code range */
  320.  
  321.         ALLOC_ARRAY( exec->callStack, exec->callSize, TCallRecord ) ||
  322.         /* reserve interpreter call stack */
  323.  
  324.         ALLOC_ARRAY( exec->storage, exec->storeSize, Long )      ||
  325.         /* reserve storage area */
  326.  
  327.         ALLOC_ARRAY( exec->stack, exec->stackSize, Long )        ||
  328.         /* reserve interpreter stack */
  329.  
  330.         ALLOC_ARRAY( exec->pts.org_x, n_points, TT_F26Dot6 )  ||
  331.         ALLOC_ARRAY( exec->pts.org_y, n_points, TT_F26Dot6 )  ||
  332.         ALLOC_ARRAY( exec->pts.cur_x, n_points, TT_F26Dot6 )  ||
  333.         ALLOC_ARRAY( exec->pts.cur_y, n_points, TT_F26Dot6 )  ||
  334.  
  335.         ALLOC( exec->pts.touch, n_points )  ||
  336.         /* reserve points zone */
  337.  
  338.         ALLOC_ARRAY( exec->twilight.org_x, n_twilight, TT_F26Dot6 )  ||
  339.         ALLOC_ARRAY( exec->twilight.org_y, n_twilight, TT_F26Dot6 )  ||
  340.         ALLOC_ARRAY( exec->twilight.cur_x, n_twilight, TT_F26Dot6 )  ||
  341.         ALLOC_ARRAY( exec->twilight.cur_y, n_twilight, TT_F26Dot6 )  ||
  342.  
  343.         ALLOC( exec->twilight.touch, n_twilight )  ||
  344.         /* reserve twilight zone */
  345.  
  346.         ALLOC_ARRAY( exec->endContours, face->maxContours, UShort )  ||
  347.         /* reserve contours array */
  348.  
  349.         ALLOC_ARRAY( exec->loadStack, face->maxComponents+1, TSubglyph_Record ))
  350.  
  351.      goto Fail_Memory;
  352.  
  353.      exec->twilight.n = n_twilight;
  354.  
  355.      exec->owner    = face;
  356.      exec->instance = NULL;
  357.  
  358.      return TT_Err_Ok;
  359.  
  360.   Fail_Memory :
  361.     Context_Destroy( exec );
  362.     return error;
  363.  }
  364.  
  365. /*******************************************************************
  366.  *
  367.  *  Function    :  Context_Load
  368.  *
  369.  *****************************************************************/
  370.  
  371.  TT_Error Context_Load( PExecution_Context  exec,
  372.                         PInstance           ins )
  373.  {
  374.    Int i;
  375.  
  376.    exec->instance = ins;
  377.  
  378.    exec->numFDefs = ins->numFDefs;
  379.    exec->numIDefs = ins->numIDefs;
  380.    exec->FDefs    = ins->FDefs;
  381.    exec->IDefs    = ins->IDefs;
  382.  
  383.    exec->metrics  = ins->metrics;
  384.  
  385.    for ( i = 0; i < MAX_CODE_RANGES; i++ )
  386.      exec->codeRangeTable[i] = ins->codeRangeTable[i];
  387.  
  388.    exec->pts.n       = 0;
  389.    exec->numContours = 0;
  390.  
  391.    exec->instruction_trap = FALSE;
  392.  
  393.    /* set default graphics state */
  394.    exec->GS = ins->GS;
  395.  
  396.    exec->cvtSize = ins->cvtSize;
  397.    exec->cvt     = ins->cvt;
  398.  
  399.    return TT_Err_Ok;
  400.  }
  401.  
  402. /*******************************************************************
  403.  *
  404.  *  Function    :  Context_Save
  405.  *
  406.  *****************************************************************/
  407.  
  408.  TT_Error  Context_Save( PExecution_Context  exec,
  409.                          PInstance           ins )
  410.  {
  411.    Int  i;
  412.  
  413.    for ( i = 0; i < MAX_CODE_RANGES; i++ )
  414.      ins->codeRangeTable[i] = exec->codeRangeTable[i];
  415.  
  416.    return TT_Err_Ok;
  417.  }
  418.  
  419. /*******************************************************************
  420.  *
  421.  *  Function    :  Context_Run
  422.  *
  423.  *****************************************************************/
  424.  
  425.  TT_Error  Context_Run( PExecution_Context  exec,
  426.                         Bool                debug )
  427.  {
  428.    TT_Error  error;
  429.  
  430.    if ( (error = Goto_CodeRange( exec, TT_CodeRange_Glyph, 0 ) ))
  431.      return error;
  432.  
  433.    exec->zp0 = exec->pts;
  434.    exec->zp1 = exec->pts;
  435.    exec->zp2 = exec->pts;
  436.  
  437.    exec->GS.gep0 = 1;
  438.    exec->GS.gep1 = 1;
  439.    exec->GS.gep2 = 1;
  440.  
  441.    exec->GS.projVector.x = 0x4000;
  442.    exec->GS.projVector.y = 0x0000;
  443.  
  444.    exec->GS.freeVector = exec->GS.projVector;
  445.    exec->GS.dualVector = exec->GS.projVector;
  446.  
  447.    exec->GS.round_state = 1;
  448.    exec->GS.loop        = 1;
  449.  
  450.    exec->top     = 0;
  451.    exec->callTop = 0;
  452.    /* some glyphs leave something on the stack. so we clean it */
  453.    /* before a new execution..                                 */
  454.  
  455.    if (!debug)
  456.      return RunIns( exec );
  457.    else
  458.      return TT_Err_Ok;
  459.  }
  460.  
  461.  
  462.   const TGraphicsState  Default_GraphicsState =
  463.   {
  464.     0, 0, 0, 
  465.     { 0x4000, 0 },
  466.     { 0x4000, 0 },
  467.     { 0x4000, 0 },
  468.     1, 64, 1,
  469.     TRUE, 68, 0, 0, 9, 3,
  470.     0, FALSE, 2, 1, 1, 1
  471.   };
  472.  
  473.  
  474.  
  475. /*******************************************************************
  476.  *                                                                 *
  477.  *                     INSTANCE  FUNCTIONS                         *
  478.  *                                                                 *
  479.  *                                                                 *
  480.  *******************************************************************/
  481.  
  482. /*******************************************************************
  483.  *
  484.  *  Function    : Instance_Destroy
  485.  *
  486.  *  Description :
  487.  *
  488.  *  Input  :  _instance   the instance object to destroy
  489.  *
  490.  *  Output :  error code.
  491.  *
  492.  ******************************************************************/
  493.  
  494.   TT_Error  Instance_Destroy( void* _instance )
  495.   {
  496.     PInstance  ins = (PInstance)_instance;
  497.  
  498.     if (!_instance)
  499.       return TT_Err_Ok;
  500.  
  501.     if ( ins->debug )
  502.     {
  503.       /* the debug context must be deleted by the debugger itself */
  504.       ins->context = NULL;
  505.       ins->debug   = FALSE;
  506.     }
  507.  
  508.     FREE( ins->cvt );
  509.     ins->cvtSize = 0;
  510.  
  511.     FREE( ins->FDefs );
  512.     FREE( ins->IDefs );
  513.     ins->numFDefs = 0;
  514.     ins->numIDefs = 0;
  515.  
  516.     ins->owner = NULL;
  517.     ins->valid = FALSE;
  518.  
  519.     return TT_Err_Ok;
  520.   }
  521.  
  522. /*******************************************************************
  523.  *
  524.  *  Function    : Instance_Create
  525.  *
  526.  *  Description :
  527.  *
  528.  *  Input  :  _instance    instance record to initialize
  529.  *            _face        parent face object
  530.  *
  531.  *  Output :  Error code. All partially built subtables are
  532.  *            released on error..
  533.  *
  534.  ******************************************************************/
  535.  
  536.   TT_Error  Instance_Create( void* _instance,
  537.                              void* _face )
  538.   {
  539.     PInstance ins  = (PInstance)_instance;
  540.     PFace     face = (PFace)_face;
  541.     TT_Error  error;
  542.     Int       i;
  543.  
  544.     PMaxProfile  maxp = &face->maxProfile;
  545.  
  546.     ins->owner = face;
  547.     ins->valid = FALSE;
  548.  
  549.     ins->numFDefs = maxp->maxFunctionDefs;
  550.     ins->numIDefs = maxp->maxInstructionDefs;
  551.     ins->cvtSize  = face->cvtSize;
  552.  
  553.     ins->metrics.pointSize    = 10 * 64;     /* default pointsize  = 10 pts */
  554.  
  555.     ins->metrics.x_resolution = 96;          /* default resolution = 96 dpi */
  556.     ins->metrics.y_resolution = 96;
  557.  
  558.     ins->metrics.x_ppem = 0;
  559.     ins->metrics.y_ppem = 0;
  560.  
  561.     ins->metrics.rotated   = FALSE;
  562.     ins->metrics.stretched = FALSE;
  563.  
  564.     for (i=0; i <4; i++)
  565.       ins->metrics.compensations[i] = 0;     /* Default compensations */
  566.  
  567.     if ( ALLOC_ARRAY( ins->FDefs, ins->numFDefs, TDefRecord )  ||
  568.  
  569.          ALLOC_ARRAY( ins->IDefs, ins->numIDefs, TDefRecord )  ||
  570.  
  571.          ALLOC_ARRAY( ins->cvt, ins->cvtSize, Long ) )
  572.  
  573.       goto Fail_Memory;
  574.  
  575.     ins->GS = Default_GraphicsState;
  576.  
  577.     return TT_Err_Ok;
  578.  
  579.   Fail_Memory :
  580.     Instance_Destroy( ins );
  581.     return error;
  582.   }
  583.  
  584. /*******************************************************************
  585.  *
  586.  *  Function    : Instance_Init
  587.  *
  588.  *  Description : Initialize a fresh new instance.
  589.  *                Executes the font program if any is found..
  590.  *
  591.  *  Input  :  _instance   the instance object to destroy
  592.  *
  593.  *  Output :  error code.
  594.  *
  595.  ******************************************************************/
  596.  
  597.   TT_Error  Instance_Init( PInstance  ins )
  598.   {
  599.     PExecution_Context  exec;
  600.  
  601.     TT_Error  error;
  602.     PFace     face = ins->owner;
  603.  
  604.     if (ins->debug)
  605.       exec = ins->context;
  606.     else
  607.       exec = New_Context(face);
  608.     /* debugging instances have their own context */
  609.  
  610.     if (!exec)
  611.       return TT_Err_Could_Not_Find_Context;
  612.  
  613.     ins->GS = Default_GraphicsState;
  614.  
  615.     Context_Load( exec, ins );
  616.  
  617.     exec->callTop   = 0;
  618.     exec->top       = 0;
  619.  
  620.     exec->period    = 64;
  621.     exec->phase     = 0;
  622.     exec->threshold = 0;
  623.  
  624.     exec->metrics.x_ppem = 0;
  625.     exec->metrics.y_ppem = 0;
  626.     exec->metrics.pointSize = 0;
  627.     exec->metrics.x_scale1  = 0;
  628.     exec->metrics.x_scale2  = 1;
  629.     exec->metrics.y_scale1  = 0;
  630.     exec->metrics.y_scale2  = 1;
  631.  
  632.     exec->instruction_trap = FALSE;
  633.  
  634.     exec->cvtSize = ins->cvtSize;
  635.     exec->cvt     = ins->cvt;
  636.  
  637.     exec->F_dot_P = 0x10000;
  638.  
  639.     Set_CodeRange( exec,
  640.                    TT_CodeRange_Font,
  641.                    face->fontProgram,
  642.                    face->fontPgmSize );
  643.     /* allow font program execution */
  644.  
  645.     Clear_CodeRange( exec, TT_CodeRange_Cvt );
  646.     Clear_CodeRange( exec, TT_CodeRange_Glyph );
  647.     /* disable CVT and glyph programs coderange */
  648.  
  649.     if ( face->fontPgmSize > 0 )
  650.     {
  651.       error = Goto_CodeRange( exec, TT_CodeRange_Font, 0 );
  652.       if ( error )
  653.         goto Fin;
  654.  
  655.       error = RunIns( exec );
  656.     }
  657.     else
  658.       error = TT_Err_Ok;
  659.  
  660.   Fin:
  661.     Context_Save( exec, ins );
  662.  
  663.     if (!ins->debug)
  664.       Done_Context( exec );
  665.     /* debugging instances keep their context */
  666.  
  667.     ins->valid = FALSE;
  668.  
  669.     return error;
  670.   }
  671.  
  672. /*******************************************************************
  673.  *
  674.  *  Function    : Instance_Reset
  675.  *
  676.  *  Description : Reset an instance to a new pointsize/transform.
  677.  *                Executes the cvt program if any is found..
  678.  *
  679.  *  Input  :  _instance   the instance object to destroy
  680.  *
  681.  *  Output :  error code.
  682.  *
  683.  ******************************************************************/
  684.  
  685.   TT_Error  Instance_Reset( PInstance  ins,
  686.                             Bool       debug )
  687.   {
  688.     PExecution_Context  exec;
  689.  
  690.     TT_Error  error;
  691.     Int       i;
  692.     PFace     face;
  693.  
  694.     if (!ins)
  695.       return TT_Err_Invalid_Instance_Handle;
  696.  
  697.     if ( ins->valid )
  698.       return TT_Err_Ok;
  699.  
  700.     face = ins->owner;
  701.  
  702.     /* compute new transform */
  703.  
  704.     ins->metrics.x_ppem  = ( (ins->metrics.pointSize/64) * 
  705.                               ins->metrics.x_resolution + 36 ) / 72;
  706.  
  707.     ins->metrics.y_ppem = ( (ins->metrics.pointSize/64) *
  708.                              ins->metrics.y_resolution + 36 ) / 72;
  709.  
  710.     ins->metrics.x_scale1 = ins->metrics.x_ppem * 64;
  711.     ins->metrics.y_scale1 = ins->metrics.y_ppem * 64;
  712.     ins->metrics.x_scale2 = face->fontHeader.Units_Per_EM;
  713.     ins->metrics.y_scale2 = face->fontHeader.Units_Per_EM;
  714.  
  715.     /* scale the cvt values to the new ppem */
  716.  
  717.     for ( i = 0; i < ins->cvtSize; i++ )
  718.       ins->cvt[i] = MulDiv_Round( face->cvt[i],
  719.                                   ins->metrics.y_scale1,
  720.                                   ins->metrics.y_scale2 );
  721.     /* We use by default the y ppem to scale the CVT */
  722.  
  723.     ins->GS = Default_GraphicsState;
  724.  
  725.     /* get execution context and run prep program */
  726.  
  727.     if (ins->debug)
  728.       exec = ins->context;
  729.     else
  730.       exec = New_Context(face);
  731.     /* debugging instances have their own context */
  732.  
  733.     if (!exec)
  734.       return TT_Err_Could_Not_Find_Context;
  735.  
  736.     Context_Load( exec, ins );
  737.  
  738.     Set_CodeRange( exec,
  739.                    TT_CodeRange_Cvt,
  740.                    face->cvtProgram,
  741.                    face->cvtPgmSize );
  742.  
  743.     Clear_CodeRange( exec, TT_CodeRange_Glyph );
  744.  
  745.     for ( i = 0; i < exec->storeSize; i++ )
  746.       exec->storage[i] = 0;
  747.  
  748.     exec->instruction_trap = FALSE;
  749.  
  750.     exec->top     = 0;
  751.     exec->callTop = 0;
  752.  
  753.     /* All twilight points are originally zero */
  754.  
  755.     for ( i = 0; i < exec->twilight.n; i++ )
  756.     {
  757.       exec->twilight.org_x[i] = 0;
  758.       exec->twilight.org_y[i] = 0;
  759.       exec->twilight.cur_x[i] = 0;
  760.       exec->twilight.cur_y[i] = 0;
  761.     }
  762.  
  763.     if ( face->cvtPgmSize > 0 )
  764.     {
  765.       error = Goto_CodeRange( exec, TT_CodeRange_Cvt, 0 );
  766.       if (error)
  767.         goto Fin;
  768.  
  769.       if (!ins->debug)
  770.         error = RunIns( exec );
  771.     }
  772.     else
  773.       error = TT_Err_Ok;
  774.  
  775.     ins->GS = exec->GS;
  776.     /* save default graphics state */
  777.  
  778.   Fin:
  779.     Context_Save( exec, ins );
  780.  
  781.     if (!ins->debug)
  782.       Done_Context(exec);
  783.     /* debugging instances keep their context */
  784.  
  785.     if (!error)
  786.       ins->valid = TRUE;
  787.  
  788.     return error;
  789.   }
  790.  
  791.  
  792.  
  793. /*******************************************************************
  794.  *                                                                 *
  795.  *                         FACE  FUNCTIONS                         *
  796.  *                                                                 *
  797.  *                                                                 *
  798.  *******************************************************************/
  799.  
  800. /*******************************************************************
  801.  *
  802.  *  Function    :  Face_Destroy
  803.  *
  804.  *  Description :  The face objet destructor
  805.  *
  806.  *  Input  :  _face   typeless pointer to the face object to destroy
  807.  *
  808.  *  Output :  Error code.                       
  809.  *
  810.  ******************************************************************/
  811.  
  812.   TT_Error  Face_Destroy( void*  _face )
  813.   {
  814.     PFace  face = (PFace)_face;
  815.     Int    n;
  816.  
  817.     if (!face)
  818.       return TT_Err_Ok;
  819.  
  820.     MUTEX_Lock(face->lock);
  821.     /* well, we assume that no other thread is using the face */
  822.     /* at this moment, but one is never sure enough..         */
  823.  
  824.     /* first of all, destroys the cached sub-objects */
  825.     Cache_Destroy( &face->instances );
  826.     Cache_Destroy( &face->contexts );
  827.  
  828.     /* freeing the collection table */
  829.     FREE( face->ttcHeader.TableDirectory );
  830.     face->ttcHeader.DirCount = 0;
  831.  
  832.     /* freeing table directory */
  833.     FREE( face->dirTables );
  834.     face->numTables = 0;
  835.  
  836.     /* freeing the locations table */
  837.     FREE( face->glyphLocations );
  838.     face->numLocations = 0;
  839.  
  840.     /* freeing the character mapping tables */
  841.     for ( n = 0; n < face->numCMaps; n++ )
  842.       CharMap_Free( face->cMaps + n );
  843.  
  844.     FREE( face->cMaps );
  845.     face->numCMaps = 0;
  846.  
  847.     /* freeing the CVT */
  848.     FREE( face->cvt );
  849.     face->cvtSize = 0;
  850.  
  851.     /* freeing the horizontal metrics */
  852.     FREE( face->longHMetrics );
  853.     FREE( face->shortMetrics );
  854.  
  855.     /* freeing the programs */
  856.     FREE( face->fontProgram );
  857.     FREE( face->cvtProgram );
  858.     face->fontPgmSize = 0;
  859.     face->cvtPgmSize  = 0;
  860.  
  861.     /* freeing the gasp table */
  862.     FREE( face->gasp.gaspRanges );
  863.     face->gasp.numRanges = 0;
  864.  
  865.     /* freeing the name table */
  866.     Free_TrueType_Names( face );
  867.  
  868.     #ifdef TT_EXTEND_ENGINE
  869.     Extension_Destroy( face );
  870.     #endif
  871.  
  872.     TT_Close_Stream( &face->stream );
  873.  
  874.     MUTEX_Destroy(face->lock);
  875.     /* destroy the mutex */
  876.  
  877.     return TT_Err_Ok;
  878.   }
  879.  
  880.  
  881. /*******************************************************************
  882.  *
  883.  *  Function    :  Face_Create
  884.  *
  885.  *  Description :  the face object constructor.
  886.  *
  887.  *  Input  :  _face    face record to build
  888.  *            _input   input stream where to load font data
  889.  *
  890.  *  Output :  Error code
  891.  *
  892.  *  NOTE : the input stream is kept in the face object. the
  893.  *         caller shouldn't destroy it after calling Face_Create.
  894.  *
  895.  ******************************************************************/
  896.  
  897.   #define LOAD_( table ) \
  898.             ( error = Load_TrueType_##table (face) )
  899.  
  900.  
  901.   TT_Error  Face_Create( void*  _face,
  902.                          void*  _input )
  903.   {
  904.     TFont_Input* input = (TFont_Input*)_input;
  905.     PFace        face  = (PFace)_face;
  906.     TT_Error     error;
  907.  
  908.     face->stream = input->stream;
  909.  
  910.     MUTEX_Create( face->lock );
  911.  
  912.     Cache_Create( engine.objs_instance_class,  &face->instances, &face->lock );
  913.     Cache_Create( engine.objs_execution_class, &face->contexts, &face->lock );
  914.  
  915.     /* Load collection directory if present, then font directory */
  916.  
  917.     if ( (error = Load_TrueType_Directory( face, input->fontIndex )) )
  918.       goto Fail;
  919.  
  920.     /* Load tables */
  921.  
  922.     if ( LOAD_(Header)                      ||
  923.          LOAD_(MaxProfile)                  ||
  924.          LOAD_(Locations)                   ||
  925.          LOAD_(CMap)                        ||
  926.          LOAD_(CVT)                         ||
  927.          LOAD_(Horizontal_Header)           ||
  928.          LOAD_(Programs)                    ||
  929.          LOAD_(HMTX)                        ||
  930.          LOAD_(Gasp)                        ||
  931.          LOAD_(Names)                       ||
  932.          LOAD_(OS2)                         ||
  933.          LOAD_(PostScript) )
  934.  
  935.       goto Fail;
  936.  
  937.     #ifdef TT_EXTEND_ENGINE
  938.     if ( (error = Extension_Create( face )) )
  939.       return error;
  940.     #endif
  941.  
  942.     return TT_Err_Ok;
  943.  
  944.   Fail :
  945.     Face_Destroy( face );
  946.     return error;
  947.   }
  948.  
  949.  
  950. /*******************************************************************
  951.  *
  952.  *  Function    :  Glyph_Destroy
  953.  *
  954.  *  Description :  The glyph objet destructor
  955.  *
  956.  *  Input  :  _glyph  typeless pointer to the glyph record to destroy
  957.  *
  958.  *  Output :  Error code.                       
  959.  *
  960.  ******************************************************************/
  961.  
  962.   TT_Error  Glyph_Destroy( void*  _glyph )
  963.   {
  964.     PGlyph  glyph = (PGlyph)_glyph;
  965.  
  966.     if (!glyph)
  967.       return TT_Err_Ok;
  968.  
  969.     FREE( glyph->endContours );
  970.     FREE( glyph->touch );
  971.     FREE( glyph->y_coord );
  972.     FREE( glyph->x_coord );
  973.  
  974.     return TT_Err_Ok;
  975.   }
  976.  
  977.  
  978. /*******************************************************************
  979.  *
  980.  *  Function    :  Glyph_Create
  981.  *
  982.  *  Description :  the face object constructor.
  983.  *
  984.  *  Input  :  _glyph   gylph record to build.
  985.  *            _face    the glyph's parent face.              
  986.  *
  987.  *  Output :  Error code
  988.  *
  989.  ******************************************************************/
  990.  
  991.   TT_Error  Glyph_Create( void*  _glyph,
  992.                           void*  _face )
  993.   {
  994.     TT_Error  error;
  995.     PFace     face  = (PFace)_face;
  996.     PGlyph    glyph = (PGlyph)_glyph;
  997.  
  998.     if (!face)
  999.       return TT_Err_Invalid_Face_Handle;
  1000.  
  1001.     if (!glyph)
  1002.       return TT_Err_Invalid_Glyph_Handle;
  1003.  
  1004.     glyph->face         = face;
  1005.     glyph->num_points   = 0;
  1006.     glyph->num_contours = 0;
  1007.  
  1008.     glyph->high_precision = TRUE;
  1009.     glyph->scan_type      = 2;
  1010.  
  1011.     if ( ALLOC_ARRAY( glyph->x_coord, face->maxPoints+2, TT_F26Dot6 ) ||
  1012.  
  1013.          ALLOC_ARRAY( glyph->y_coord, face->maxPoints+2, TT_F26Dot6 ) ||
  1014.  
  1015.          ALLOC_ARRAY( glyph->touch,   face->maxPoints+2, Byte )       ||
  1016.  
  1017.          ALLOC_ARRAY( glyph->endContours, face->maxContours, UShort ) )
  1018.  
  1019.       goto Fail;
  1020.  
  1021.     return TT_Err_Ok;
  1022.  
  1023.     Fail:
  1024.       Glyph_Destroy(glyph);
  1025.       return error;
  1026.   }
  1027.  
  1028.  
  1029. /*******************************************************************
  1030.  *
  1031.  *  Function    :  TTObjs_Init
  1032.  *
  1033.  *  Description :  TTObjs component initializer. Creates the
  1034.  *                 object cache classes, as well as the face record
  1035.  *                 cache.
  1036.  *
  1037.  *  Input  :  None
  1038.  *
  1039.  *  Output :  Error code.                       
  1040.  *
  1041.  ******************************************************************/
  1042.  
  1043.   TT_Error  TTObjs_Init()
  1044.   {
  1045.     PCache_Class  instances, contexts, faces, glyphs;
  1046.     PCache        face_cache, glyph_cache;
  1047.     TT_Error      error;
  1048.  
  1049.     instances = NULL;
  1050.     contexts  = NULL;
  1051.     faces     = NULL;
  1052.     glyphs    = NULL;
  1053.  
  1054.     glyph_cache = NULL;
  1055.     face_cache  = NULL;
  1056.  
  1057.     if ( !ALLOC( instances, sizeof(TCache_Class) )   && 
  1058.          !ALLOC( contexts,  sizeof(TCache_Class) )   &&
  1059.          !ALLOC( faces,     sizeof(TCache_Class) )   &&
  1060.          !ALLOC( glyphs,    sizeof(TCache_Class) )   &&
  1061.  
  1062.          !ALLOC( glyph_cache, sizeof(TCache) )       &&
  1063.          !ALLOC( face_cache,  sizeof(TCache) ) )
  1064.     {
  1065.       /* create the face cache class */
  1066.  
  1067.       faces->object_size = sizeof(TFace);
  1068.       faces->idle_limit  = -1;            /* no recycling of face objects */
  1069.       faces->init        = Face_Create;
  1070.       faces->done        = Face_Destroy;
  1071.  
  1072.       engine.objs_face_class = faces;
  1073.  
  1074.       /* create the instance cache class */
  1075.  
  1076.       instances->object_size = sizeof(TInstance);
  1077.       instances->idle_limit  = 2;
  1078.       instances->init        = Instance_Create;
  1079.       instances->done        = Instance_Destroy;
  1080.  
  1081.       engine.objs_instance_class = instances;
  1082.  
  1083.       /* create the execution context cache class */
  1084.  
  1085.       contexts->object_size = sizeof(TExecution_Context);
  1086.       contexts->idle_limit  = 1;
  1087.       contexts->init        = Context_Create;
  1088.       contexts->done        = Context_Destroy;
  1089.  
  1090.       engine.objs_execution_class = contexts;
  1091.  
  1092.       glyphs->object_size = sizeof(TGlyph);
  1093.       glyphs->idle_limit  = -1;  /* no recycling of glyph objects */
  1094.       glyphs->init        = Glyph_Create;
  1095.       glyphs->done        = Glyph_Destroy;
  1096.  
  1097.       engine.objs_glyph_class = glyphs;
  1098.  
  1099.       /* create face and glyph 'caches'. These are used only */
  1100.       /* for tracking purpose. No recycling is performed     */
  1101.  
  1102.       Cache_Create( faces, face_cache, &engine.lock );
  1103.       Cache_Create( glyphs, glyph_cache, &engine.lock );
  1104.  
  1105.       engine.objs_face_cache  = face_cache;
  1106.       engine.objs_glyph_cache = glyph_cache;
  1107.  
  1108.     }
  1109.     else
  1110.     {
  1111.       FREE( face_cache );
  1112.       FREE( glyph_cache );
  1113.  
  1114.       FREE( glyphs );
  1115.       FREE( faces );
  1116.       FREE( contexts );
  1117.       FREE( instances );
  1118.     }
  1119.  
  1120.     return error;
  1121.   }
  1122.  
  1123.  
  1124.   TT_Error  TTObjs_Done()
  1125.   {
  1126.     /* destroy all active faces and glyphs before releasing the */
  1127.     /* caches                                                   */
  1128.  
  1129.     Cache_Destroy( (TCache*)engine.objs_face_cache );
  1130.     Cache_Destroy( (TCache*)engine.objs_glyph_cache );
  1131.  
  1132.     /* No frees caches and cache classes */
  1133.  
  1134.     FREE( engine.objs_face_cache );
  1135.     FREE( engine.objs_glyph_cache );
  1136.  
  1137.     FREE( engine.objs_glyph_class );
  1138.     FREE( engine.objs_execution_class );
  1139.     FREE( engine.objs_instance_class );
  1140.     FREE( engine.objs_face_class );
  1141.  
  1142.     return TT_Err_Ok;
  1143.   }
  1144.  
  1145.  
  1146.