summaryrefslogtreecommitdiff
path: root/Build/source/libs/libttf/ttobjs.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/libttf/ttobjs.c')
-rw-r--r--Build/source/libs/libttf/ttobjs.c1495
1 files changed, 1495 insertions, 0 deletions
diff --git a/Build/source/libs/libttf/ttobjs.c b/Build/source/libs/libttf/ttobjs.c
new file mode 100644
index 00000000000..9ce11013ae8
--- /dev/null
+++ b/Build/source/libs/libttf/ttobjs.c
@@ -0,0 +1,1495 @@
+/*******************************************************************
+ *
+ * ttobjs.c 1.0
+ *
+ * Objects manager.
+ *
+ * Copyright 1996-1999 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ ******************************************************************/
+
+#include "ttobjs.h"
+#include "ttfile.h"
+#include "ttcalc.h"
+#include "ttmemory.h"
+#include "ttload.h"
+#include "ttinterp.h"
+#include "ttdebug.h"
+
+
+/* Add extensions definition */
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+#include "ttextend.h"
+#endif
+
+/* Required by tracing mode */
+#undef TT_COMPONENT
+#define TT_COMPONENT trace_objs
+
+/*******************************************************************
+ *
+ * Function : New_Context
+ *
+ * Description : Creates a new execution context for a given
+ * face object.
+ *
+ ******************************************************************/
+
+ LOCAL_FUNC
+ PExecution_Context New_Context( PFace face )
+ {
+ PEngine_Instance engine;
+ PExecution_Context exec;
+
+
+ if ( !face )
+ return NULL;
+
+ engine = face->engine;
+ CACHE_New( engine->objs_exec_cache, exec, face );
+ return exec;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : Done_Context
+ *
+ * Description : Discards an execution context.
+ *
+ ******************************************************************/
+
+ LOCAL_FUNC
+ TT_Error Done_Context( PExecution_Context exec )
+ {
+ PEngine_Instance engine;
+
+
+ if ( !exec )
+ return TT_Err_Ok;
+
+ engine = exec->face->engine;
+ return CACHE_Done( engine->objs_exec_cache, exec );
+ }
+
+
+#if 0
+
+/*******************************************************************
+ *
+ * Function : New_Instance
+ *
+ * Description : Creates a new instance for a given face object.
+ *
+ ******************************************************************/
+
+ LOCAL_FUNC
+ PInstance New_Instance( PFace face )
+ {
+ PInstance ins;
+
+
+ if ( !face )
+ return NULL;
+
+ CACHE_New( &face->instances, ins, face );
+
+ return ins;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : Done_Instance
+ *
+ * Description : Discards an instance.
+ *
+ ******************************************************************/
+
+ LOCAL_FUNC
+ TT_Error Done_Instance( PInstance instance )
+ {
+ return CACHE_Done( &instance->owner->instances, instance );
+ }
+
+#endif
+
+
+/*******************************************************************
+ * *
+ * GLYPH ZONE FUNCTIONS *
+ * *
+ * *
+ *******************************************************************/
+
+/*******************************************************************
+ *
+ * Function : New_Glyph_Zone
+ *
+ * Description : Allocates a new glyph zone
+ *
+ * Input : pts pointer to the target glyph zone record
+ * maxPoints capacity of glyph zone in points
+ * maxContours capacity of glyph zone in contours
+ *
+ * Return : Error code.
+ *
+ *****************************************************************/
+
+ static
+ TT_Error New_Glyph_Zone( PGlyph_Zone pts,
+ UShort maxPoints,
+ UShort maxContours )
+ {
+ TT_Error error;
+
+
+ if ( ALLOC( pts->org, maxPoints * 2 * sizeof ( TT_F26Dot6 ) ) ||
+ ALLOC( pts->cur, maxPoints * 2 * sizeof ( TT_F26Dot6 ) ) ||
+ ALLOC( pts->touch, maxPoints * sizeof ( Byte ) ) ||
+ ALLOC( pts->contours, maxContours * sizeof ( Short ) ) )
+ return error;
+
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : Done_Glyph_Zone
+ *
+ * Description : Deallocates a glyph zone
+ *
+ * Input : pts pointer to the target glyph zone record
+ *
+ * Return : Error code.
+ *
+ *****************************************************************/
+
+ static
+ TT_Error Done_Glyph_Zone( PGlyph_Zone pts )
+ {
+ FREE( pts->contours );
+ FREE( pts->touch );
+ FREE( pts->cur );
+ FREE( pts->org );
+
+ return TT_Err_Ok;
+ }
+
+
+
+/*******************************************************************
+ * *
+ * CODERANGE FUNCTIONS *
+ * *
+ *******************************************************************/
+
+/*******************************************************************
+ *
+ * Function : Goto_CodeRange
+ *
+ * Description : Switch to a new code range (updates Code and IP).
+ *
+ * Input : exec target execution context
+ * range new execution code range
+ * IP new IP in new code range
+ *
+ * Output : SUCCESS on success. FAILURE on error (no code range).
+ *
+ *****************************************************************/
+
+ LOCAL_FUNC
+ TT_Error Goto_CodeRange( PExecution_Context exec,
+ Int range,
+ ULong IP )
+ {
+ PCodeRange cr;
+
+
+ if ( range < 1 || range > 3 )
+ return TT_Err_Bad_Argument;
+
+ cr = &exec->codeRangeTable[range - 1];
+
+ if ( cr->Base == NULL )
+ return TT_Err_Invalid_CodeRange;
+
+ /* NOTE: Because the last instruction of a program may be a CALL */
+ /* which will return to the first byte *after* the code */
+ /* range, we test for IP <= Size, instead of IP < Size. */
+
+ if ( IP > cr->Size )
+ return TT_Err_Code_Overflow;
+
+ exec->code = cr->Base;
+ exec->codeSize = cr->Size;
+ exec->IP = IP;
+ exec->curRange = range;
+
+ return TT_Err_Ok;
+ }
+
+
+#if 0
+
+/*******************************************************************
+ *
+ * Function : Get_CodeRange
+ *
+ * Description : Returns a pointer to a given code range. Should
+ * be used only by the debugger. Returns NULL if
+ * 'range' is out of current bounds.
+ *
+ * Input : exec target execution context
+ * range new execution code range
+ *
+ * Output : Pointer to the code range record. NULL on failure.
+ *
+ *****************************************************************/
+
+ LOCAL_FUNC
+ PCodeRange Get_CodeRange( PExecution_Context exec, Int range )
+ {
+ if ( range < 1 || range > 3 )
+ return NULL;
+ else /* arrays start with 1 in Pascal, and with 0 in C */
+ return &exec->codeRangeTable[range - 1];
+ }
+
+#endif
+
+
+/*******************************************************************
+ *
+ * Function : Set_CodeRange
+ *
+ * Description : Sets a code range.
+ *
+ * Input : exec target execution context
+ * range code range index
+ * base new code base
+ * length range size in bytes
+ *
+ * Output : SUCCESS on success. FAILURE on error.
+ *
+ *****************************************************************/
+
+ LOCAL_FUNC
+ TT_Error Set_CodeRange( PExecution_Context exec,
+ Int range,
+ void* base,
+ ULong length )
+ {
+ if ( range < 1 || range > 3 )
+ return TT_Err_Bad_Argument;
+
+ exec->codeRangeTable[range - 1].Base = (Byte*)base;
+ exec->codeRangeTable[range - 1].Size = length;
+
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : Clear_CodeRange
+ *
+ * Description : Clears a code range.
+ *
+ * Input : exec target execution context
+ * range code range index
+ *
+ * Output : SUCCESS on success. FAILURE on error.
+ *
+ * Note : Does not set the Error variable.
+ *
+ *****************************************************************/
+
+ LOCAL_FUNC
+ TT_Error Clear_CodeRange( PExecution_Context exec, Int range )
+ {
+ if ( range < 1 || range > 3 )
+ return TT_Err_Bad_Argument;
+
+ exec->codeRangeTable[range - 1].Base = NULL;
+ exec->codeRangeTable[range - 1].Size = 0;
+
+ return TT_Err_Ok;
+ }
+
+
+
+/*******************************************************************
+ * *
+ * EXECUTION CONTEXT ROUTINES *
+ * *
+ *******************************************************************/
+
+/*******************************************************************
+ *
+ * Function : Context_Destroy
+ *
+ *****************************************************************/
+
+ LOCAL_FUNC
+ TT_Error Context_Destroy( void* _context )
+ {
+ PExecution_Context exec = (PExecution_Context)_context;
+
+ if ( !exec )
+ return TT_Err_Ok;
+
+ /* free composite load stack */
+ FREE( exec->loadStack );
+ exec->loadSize = 0;
+
+ /* points zone */
+ Done_Glyph_Zone( &exec->pts );
+ exec->maxPoints = 0;
+ exec->maxContours = 0;
+
+ /* free stack */
+ FREE( exec->stack );
+ exec->stackSize = 0;
+
+ /* free call stack */
+ FREE( exec->callStack );
+ exec->callSize = 0;
+ exec->callTop = 0;
+
+ /* free glyph code range */
+ FREE( exec->glyphIns );
+ exec->glyphSize = 0;
+
+ exec->instance = NULL;
+ exec->face = NULL;
+
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : Context_Create
+ *
+ *****************************************************************/
+
+ LOCAL_FUNC
+ TT_Error Context_Create( void* _context, void* _face )
+ {
+ PExecution_Context exec = (PExecution_Context)_context;
+
+ PFace face = (PFace)_face;
+ TT_Error error;
+
+
+ /* XXX : We don't reserve arrays anymore, this is done automatically */
+ /* during a "Context_Load".. */
+
+ exec->callSize = 32;
+ if ( ALLOC_ARRAY( exec->callStack, exec->callSize, TCallRecord ) )
+ goto Fail_Memory;
+
+ /* all values in the context are set to 0 already, but this is */
+ /* here as a remainder */
+ exec->maxPoints = 0;
+ exec->maxContours = 0;
+
+ exec->stackSize = 0;
+ exec->loadSize = 0;
+ exec->glyphSize = 0;
+
+ exec->stack = NULL;
+ exec->loadStack = NULL;
+ exec->glyphIns = NULL;
+
+ exec->face = face;
+ exec->instance = NULL;
+
+ return TT_Err_Ok;
+
+ Fail_Memory:
+ Context_Destroy( exec );
+ return error;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : Context_Load
+ *
+ *****************************************************************/
+
+/****************************************************************/
+/* */
+/* Update_Max : Reallocate a buffer if it needs to */
+/* */
+/* input: size address of buffer's current size */
+/* expressed in elements */
+/* */
+/* multiplier size in bytes of each element in the */
+/* buffer */
+/* */
+/* buff address of the buffer base pointer */
+/* */
+/* new_max new capacity (size) of the buffer */
+
+ static
+ TT_Error Update_Max( ULong* size,
+ ULong multiplier,
+ void** buff,
+ ULong new_max )
+ {
+ TT_Error error;
+
+ if ( *size < new_max )
+ {
+ FREE( *buff );
+ if ( ALLOC( *buff, new_max * multiplier ) )
+ return error;
+ *size = new_max;
+ }
+ return TT_Err_Ok;
+ }
+
+
+/****************************************************************/
+/* */
+/* Update_Zone: Reallocate a zone if it needs to */
+/* */
+/* input: zone address of the target zone */
+/* */
+/* maxPoints address of the zone's current capacity */
+/* in points */
+/* */
+/* maxContours address of the zone's current capacity */
+/* in contours */
+/* */
+/* newPoints new capacity in points */
+/* */
+/* newContours new capacity in contours */
+/* */
+
+ static
+ TT_Error Update_Zone( PGlyph_Zone zone,
+ UShort* maxPoints,
+ UShort* maxContours,
+ UShort newPoints,
+ UShort newContours )
+ {
+ if ( *maxPoints < newPoints || *maxContours < newContours )
+ {
+ TT_Error error;
+
+
+ Done_Glyph_Zone( zone );
+
+ error = New_Glyph_Zone( zone, newPoints, newContours );
+ if ( error )
+ return error;
+
+ *maxPoints = newPoints;
+ *maxContours = newContours;
+ }
+ return TT_Err_Ok;
+ }
+
+
+ LOCAL_FUNC
+ TT_Error Context_Load( PExecution_Context exec,
+ PFace face,
+ PInstance ins )
+ {
+ Int i;
+ TMaxProfile* maxp;
+ TT_Error error;
+
+ exec->face = face;
+ maxp = &face->maxProfile;
+
+ exec->instance = ins;
+
+ if ( ins )
+ {
+ exec->numFDefs = ins->numFDefs;
+ exec->numIDefs = ins->numIDefs;
+ exec->maxFDefs = ins->maxFDefs;
+ exec->maxIDefs = ins->maxIDefs;
+ exec->FDefs = ins->FDefs;
+ exec->IDefs = ins->IDefs;
+ exec->metrics = ins->metrics;
+
+ exec->maxFunc = ins->maxFunc;
+ exec->maxIns = ins->maxIns;
+
+ for ( i = 0; i < MAX_CODE_RANGES; i++ )
+ exec->codeRangeTable[i] = ins->codeRangeTable[i];
+
+ /* set graphics state */
+ exec->GS = ins->GS;
+
+ exec->cvtSize = ins->cvtSize;
+ exec->cvt = ins->cvt;
+
+ exec->storeSize = ins->storeSize;
+ exec->storage = ins->storage;
+
+ exec->twilight = ins->twilight;
+ }
+
+ error = Update_Max( &exec->loadSize,
+ sizeof ( TSubglyph_Record ),
+ (void**)&exec->loadStack,
+ face->maxComponents + 1 );
+ if ( error )
+ return error;
+
+ error = Update_Max( &exec->stackSize,
+ sizeof ( TT_F26Dot6 ),
+ (void**)&exec->stack,
+ maxp->maxStackElements + 32 );
+ /* XXX : We reserve a little more elements on the stack to deal safely */
+ /* with broken fonts like arialbs, courbs, timesbs... */
+ if ( error )
+ return error;
+
+ error = Update_Max( &exec->glyphSize,
+ sizeof ( Byte ),
+ (void**)&exec->glyphIns,
+ maxp->maxSizeOfInstructions );
+ if ( error )
+ return error;
+
+ error = Update_Zone( &exec->pts,
+ &exec->maxPoints,
+ &exec->maxContours,
+ exec->face->maxPoints + 2,
+ exec->face->maxContours );
+ /* XXX : We reserve two positions for the phantom points! */
+ if ( error )
+ return error;
+
+ exec->pts.n_points = 0;
+ exec->pts.n_contours = 0;
+
+ exec->instruction_trap = FALSE;
+
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : Context_Save
+ *
+ *****************************************************************/
+
+ LOCAL_FUNC
+ TT_Error Context_Save( PExecution_Context exec,
+ PInstance ins )
+ {
+ Int i;
+
+ /* XXXX : Will probably disappear soon with all the coderange */
+ /* management, which is now rather obsolete. */
+
+ ins->numFDefs = exec->numFDefs;
+ ins->numIDefs = exec->numIDefs;
+ ins->maxFunc = exec->maxFunc;
+ ins->maxIns = exec->maxIns;
+
+ for ( i = 0; i < MAX_CODE_RANGES; i++ )
+ ins->codeRangeTable[i] = exec->codeRangeTable[i];
+
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : Context_Run
+ *
+ *****************************************************************/
+
+ LOCAL_FUNC
+ TT_Error Context_Run( PExecution_Context exec,
+ Bool debug )
+ {
+ TT_Error error;
+
+
+ if ( (error = Goto_CodeRange( exec,
+ TT_CodeRange_Glyph, 0 )) != TT_Err_Ok )
+ return error;
+
+ exec->zp0 = exec->pts;
+ exec->zp1 = exec->pts;
+ exec->zp2 = exec->pts;
+
+ exec->GS.gep0 = 1;
+ exec->GS.gep1 = 1;
+ exec->GS.gep2 = 1;
+
+ exec->GS.projVector.x = 0x4000;
+ exec->GS.projVector.y = 0x0000;
+
+ exec->GS.freeVector = exec->GS.projVector;
+ exec->GS.dualVector = exec->GS.projVector;
+
+ exec->GS.round_state = 1;
+ exec->GS.loop = 1;
+
+ /* some glyphs leave something on the stack. so we clean it */
+ /* before a new execution. */
+ exec->top = 0;
+ exec->callTop = 0;
+
+ if ( !debug )
+ return RunIns( exec );
+ else
+ return TT_Err_Ok;
+ }
+
+
+ LOCAL_FUNC
+ const TGraphicsState Default_GraphicsState =
+ {
+ 0, 0, 0,
+ { 0x4000, 0 },
+ { 0x4000, 0 },
+ { 0x4000, 0 },
+ 1, 64, 1,
+ TRUE, 68, 0, 0, 9, 3,
+ 0, FALSE, 2, 1, 1, 1
+ };
+
+
+
+/*******************************************************************
+ * *
+ * INSTANCE FUNCTIONS *
+ * *
+ * *
+ *******************************************************************/
+
+/*******************************************************************
+ *
+ * Function : Instance_Destroy
+ *
+ * Description :
+ *
+ * Input : _instance the instance object to destroy
+ *
+ * Output : error code.
+ *
+ ******************************************************************/
+
+ LOCAL_FUNC
+ TT_Error Instance_Destroy( void* _instance )
+ {
+ PInstance ins = (PInstance)_instance;
+
+
+ if ( !_instance )
+ return TT_Err_Ok;
+
+ if ( ins->debug )
+ {
+ /* the debug context must be deleted by the debugger itself */
+ ins->context = NULL;
+ ins->debug = FALSE;
+ }
+
+ FREE( ins->cvt );
+ ins->cvtSize = 0;
+
+ /* free storage area */
+ FREE( ins->storage );
+ ins->storeSize = 0;
+
+ /* twilight zone */
+ Done_Glyph_Zone( &ins->twilight );
+
+ FREE( ins->FDefs );
+ FREE( ins->IDefs );
+ ins->numFDefs = 0;
+ ins->numIDefs = 0;
+ ins->maxFDefs = 0;
+ ins->maxIDefs = 0;
+ ins->maxFunc = -1;
+ ins->maxIns = -1;
+
+ ins->owner = NULL;
+ ins->valid = FALSE;
+
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : Instance_Create
+ *
+ * Description :
+ *
+ * Input : _instance instance record to initialize
+ * _face parent face object
+ *
+ * Output : Error code. All partially built subtables are
+ * released on error.
+ *
+ ******************************************************************/
+
+ LOCAL_FUNC
+ TT_Error Instance_Create( void* _instance,
+ void* _face )
+ {
+ PInstance ins = (PInstance)_instance;
+ PFace face = (PFace)_face;
+ TT_Error error;
+ Int i;
+ UShort n_twilight;
+
+ PMaxProfile maxp = &face->maxProfile;
+
+
+ ins->owner = face;
+ ins->valid = FALSE;
+
+ ins->maxFDefs = maxp->maxFunctionDefs;
+ ins->maxIDefs = maxp->maxInstructionDefs;
+ ins->cvtSize = face->cvtSize;
+ ins->storeSize = maxp->maxStorage;
+
+ /* Set default metrics */
+ {
+ PIns_Metrics metrics = &ins->metrics;
+
+
+ metrics->pointSize = 10 * 64; /* default pointsize = 10pts */
+
+ metrics->x_resolution = 96; /* default resolution = 96dpi */
+ metrics->y_resolution = 96;
+
+ metrics->x_ppem = 0;
+ metrics->y_ppem = 0;
+
+ metrics->rotated = FALSE;
+ metrics->stretched = FALSE;
+
+ /* set default compensation ( all 0 ) */
+ for ( i = 0; i < 4; i++ )
+ metrics->compensations[i] = 0;
+ }
+
+ /* allocate function defs, instruction defs, cvt and storage area */
+ if ( ALLOC_ARRAY( ins->FDefs, ins->maxFDefs, TDefRecord ) ||
+ ALLOC_ARRAY( ins->IDefs, ins->maxIDefs, TDefRecord ) ||
+ ALLOC_ARRAY( ins->cvt, ins->cvtSize, Long ) ||
+ ALLOC_ARRAY( ins->storage, ins->storeSize, Long ) )
+ goto Fail_Memory;
+
+ /* reserve twilight zone */
+ n_twilight = maxp->maxTwilightPoints;
+ error = New_Glyph_Zone( &ins->twilight, n_twilight, 0 );
+ if (error)
+ goto Fail_Memory;
+
+ ins->twilight.n_points = n_twilight;
+
+ return TT_Err_Ok;
+
+ Fail_Memory:
+ Instance_Destroy( ins );
+ return error;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : Instance_Init
+ *
+ * Description : Initialize a fresh new instance.
+ * Executes the font program if any is found.
+ *
+ * Input : _instance the instance object to destroy
+ *
+ * Output : Error code.
+ *
+ ******************************************************************/
+
+ LOCAL_FUNC
+ TT_Error Instance_Init( PInstance ins )
+ {
+ PExecution_Context exec;
+
+ TT_Error error;
+ PFace face = ins->owner;
+
+
+ if ( ins->debug )
+ exec = ins->context;
+ else
+ exec = New_Context( face );
+ /* debugging instances have their own context */
+
+ if ( !exec )
+ return TT_Err_Could_Not_Find_Context;
+
+ ins->GS = Default_GraphicsState;
+
+ ins->numFDefs = 0;
+ ins->numIDefs = 0;
+ ins->maxFunc = -1;
+ ins->maxIns = -1;
+
+ Context_Load( exec, face, ins );
+
+ exec->callTop = 0;
+ exec->top = 0;
+
+ exec->period = 64;
+ exec->phase = 0;
+ exec->threshold = 0;
+
+ {
+ PIns_Metrics metrics = &exec->metrics;
+
+
+ metrics->x_ppem = 0;
+ metrics->y_ppem = 0;
+ metrics->pointSize = 0;
+ metrics->x_scale1 = 0;
+ metrics->x_scale2 = 1;
+ metrics->y_scale1 = 0;
+ metrics->y_scale2 = 1;
+
+ metrics->ppem = 0;
+ metrics->scale1 = 0;
+ metrics->scale2 = 1;
+ metrics->ratio = 1L << 16;
+ }
+
+ exec->instruction_trap = FALSE;
+
+ exec->cvtSize = ins->cvtSize;
+ exec->cvt = ins->cvt;
+
+ exec->F_dot_P = 0x10000;
+
+ /* allow font program execution */
+ Set_CodeRange( exec,
+ TT_CodeRange_Font,
+ face->fontProgram,
+ face->fontPgmSize );
+
+ /* disable CVT and glyph programs coderange */
+ Clear_CodeRange( exec, TT_CodeRange_Cvt );
+ Clear_CodeRange( exec, TT_CodeRange_Glyph );
+
+ if ( face->fontPgmSize > 0 )
+ {
+ error = Goto_CodeRange( exec, TT_CodeRange_Font, 0 );
+ if ( error )
+ goto Fin;
+
+ error = RunIns( exec );
+ }
+ else
+ error = TT_Err_Ok;
+
+ Fin:
+ Context_Save( exec, ins );
+
+ if ( !ins->debug )
+ Done_Context( exec );
+ /* debugging instances keep their context */
+
+ ins->valid = FALSE;
+
+ return error;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : Instance_Reset
+ *
+ * Description : Resets an instance to a new pointsize/transform.
+ * Executes the cvt program if any is found.
+ *
+ * Input : _instance the instance object to destroy
+ *
+ * Output : Error code.
+ *
+ ******************************************************************/
+
+ LOCAL_FUNC
+ TT_Error Instance_Reset( PInstance ins )
+ {
+ PExecution_Context exec;
+
+ TT_Error error;
+ ULong i;
+ UShort j;
+ PFace face;
+
+
+ if ( !ins )
+ return TT_Err_Invalid_Instance_Handle;
+
+ if ( ins->valid )
+ return TT_Err_Ok;
+
+ face = ins->owner;
+
+ if ( ins->metrics.x_ppem < 1 ||
+ ins->metrics.y_ppem < 1 )
+ return TT_Err_Invalid_PPem;
+
+ /* compute new transformation */
+ if ( ins->metrics.x_ppem >= ins->metrics.y_ppem )
+ {
+ ins->metrics.scale1 = ins->metrics.x_scale1;
+ ins->metrics.scale2 = ins->metrics.x_scale2;
+ ins->metrics.ppem = ins->metrics.x_ppem;
+ ins->metrics.x_ratio = 1L << 16;
+ ins->metrics.y_ratio = TT_MulDiv( ins->metrics.y_ppem,
+ 0x10000,
+ ins->metrics.x_ppem );
+ }
+ else
+ {
+ ins->metrics.scale1 = ins->metrics.y_scale1;
+ ins->metrics.scale2 = ins->metrics.y_scale2;
+ ins->metrics.ppem = ins->metrics.y_ppem;
+ ins->metrics.x_ratio = TT_MulDiv( ins->metrics.x_ppem,
+ 0x10000,
+ ins->metrics.y_ppem );
+ ins->metrics.y_ratio = 1L << 16;
+ }
+
+ /* Scale the cvt values to the new ppem. */
+ /* We use by default the y ppem to scale the CVT. */
+
+ for ( i = 0; i < ins->cvtSize; i++ )
+ ins->cvt[i] = TT_MulDiv( face->cvt[i],
+ ins->metrics.scale1,
+ ins->metrics.scale2 );
+
+ /* All twilight points are originally zero */
+ for ( j = 0; j < ins->twilight.n_points; j++ )
+ {
+ ins->twilight.org[j].x = 0;
+ ins->twilight.org[j].y = 0;
+ ins->twilight.cur[j].x = 0;
+ ins->twilight.cur[j].y = 0;
+ }
+
+ /* clear storage area */
+ for ( i = 0; i < ins->storeSize; i++ )
+ ins->storage[i] = 0;
+
+ ins->GS = Default_GraphicsState;
+
+ /* get execution context and run prep program */
+
+ if ( ins->debug )
+ exec = ins->context;
+ else
+ exec = New_Context(face);
+ /* debugging instances have their own context */
+
+ if ( !exec )
+ return TT_Err_Could_Not_Find_Context;
+
+ Context_Load( exec, face, ins );
+
+ Set_CodeRange( exec,
+ TT_CodeRange_Cvt,
+ face->cvtProgram,
+ face->cvtPgmSize );
+
+ Clear_CodeRange( exec, TT_CodeRange_Glyph );
+
+ exec->instruction_trap = FALSE;
+
+ exec->top = 0;
+ exec->callTop = 0;
+
+ if ( face->cvtPgmSize > 0 )
+ {
+ error = Goto_CodeRange( exec, TT_CodeRange_Cvt, 0 );
+ if ( error )
+ goto Fin;
+
+ if ( !ins->debug )
+ error = RunIns( exec );
+ }
+ else
+ error = TT_Err_Ok;
+
+ ins->GS = exec->GS;
+ /* save default graphics state */
+
+ Fin:
+ Context_Save( exec, ins );
+
+ if ( !ins->debug )
+ Done_Context( exec );
+ /* debugging instances keep their context */
+
+ if ( !error )
+ ins->valid = TRUE;
+
+ return error;
+ }
+
+
+
+/*******************************************************************
+ * *
+ * FACE FUNCTIONS *
+ * *
+ * *
+ *******************************************************************/
+
+/*******************************************************************
+ *
+ * Function : Face_Destroy
+ *
+ * Description : The face object destructor.
+ *
+ * Input : _face typeless pointer to the face object to destroy
+ *
+ * Output : Error code.
+ *
+ ******************************************************************/
+
+ LOCAL_FUNC
+ TT_Error Face_Destroy( void* _face )
+ {
+ PFace face = (PFace)_face;
+ UShort n;
+
+
+ if ( !face )
+ return TT_Err_Ok;
+
+ /* well, we assume that no other thread is using the face */
+ /* at this moment, but one is never sure enough. */
+ MUTEX_Lock( face->lock );
+
+ /* first of all, destroys the cached sub-objects */
+ Cache_Destroy( &face->instances );
+ Cache_Destroy( &face->glyphs );
+
+ /* destroy the extensions */
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+ Extension_Destroy( face );
+#endif
+
+ /* freeing the collection table */
+ FREE( face->ttcHeader.TableDirectory );
+ face->ttcHeader.DirCount = 0;
+
+ /* freeing table directory */
+ FREE( face->dirTables );
+ face->numTables = 0;
+
+ /* freeing the locations table */
+ FREE( face->glyphLocations );
+ face->numLocations = 0;
+
+ /* freeing the character mapping tables */
+ for ( n = 0; n < face->numCMaps; n++ )
+ CharMap_Free( face->cMaps + n );
+
+ FREE( face->cMaps );
+ face->numCMaps = 0;
+
+ /* freeing the CVT */
+ FREE( face->cvt );
+ face->cvtSize = 0;
+
+ /* freeing the horizontal metrics */
+ FREE( face->horizontalHeader.long_metrics );
+ FREE( face->horizontalHeader.short_metrics );
+
+ /* freeing the vertical ones, if any */
+ if (face->verticalInfo)
+ {
+ FREE( face->verticalHeader.long_metrics );
+ FREE( face->verticalHeader.short_metrics );
+ face->verticalInfo = 0;
+ }
+
+ /* freeing the programs */
+ FREE( face->fontProgram );
+ FREE( face->cvtProgram );
+ face->fontPgmSize = 0;
+ face->cvtPgmSize = 0;
+
+ /* freeing the gasp table */
+ FREE( face->gasp.gaspRanges );
+ face->gasp.numRanges = 0;
+
+ /* freeing the name table */
+ Free_TrueType_Names( face );
+
+ /* freeing the hdmx table */
+ Free_TrueType_Hdmx( face );
+
+ /* TT_Close_Stream( &face->stream ); -- this is performed by the API */
+
+ /* destroy the mutex */
+ MUTEX_Destroy(face->lock);
+
+ return TT_Err_Ok;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : Face_Create
+ *
+ * Description : The face object constructor.
+ *
+ * Input : _face face record to build
+ * _input input stream where to load font data
+ *
+ * Output : Error code.
+ *
+ * NOTE : The input stream is kept in the face object. The
+ * caller shouldn't destroy it after calling Face_Create().
+ *
+ ******************************************************************/
+
+#undef LOAD_
+#define LOAD_( table ) \
+ (error = Load_TrueType_##table (face)) != TT_Err_Ok
+
+
+ LOCAL_FUNC
+ TT_Error Face_Create( void* _face,
+ void* _input )
+ {
+ PEngine_Instance engine;
+
+ TFont_Input* input = (TFont_Input*)_input;
+ PFace face = (PFace)_face;
+ TT_Error error;
+
+
+ face->stream = input->stream;
+ face->engine = input->engine;
+
+ engine = face->engine;
+
+ MUTEX_Create( face->lock );
+
+ Cache_Create( engine,
+ engine->objs_instance_class,
+ &face->instances,
+ &face->lock );
+
+ Cache_Create( engine,
+ engine->objs_glyph_class,
+ &face->glyphs,
+ &face->lock );
+
+ /* Load collection directory if present, then font directory */
+
+ error = Load_TrueType_Directory( face, input->fontIndex );
+ if ( error )
+ goto Fail;
+
+ /* Load tables */
+
+ if ( LOAD_( Header ) ||
+ LOAD_( MaxProfile ) ||
+ LOAD_( Locations ) ||
+
+ (error = Load_TrueType_Metrics_Header( face, 0 )) != TT_Err_Ok ||
+ /* load the 'hhea' & 'hmtx' tables at once */
+
+ LOAD_( CMap ) ||
+ LOAD_( CVT ) ||
+ LOAD_( Programs ) ||
+ LOAD_( Gasp ) ||
+ LOAD_( Names ) ||
+ LOAD_( OS2 ) ||
+ LOAD_( PostScript ) ||
+
+ (error = Load_TrueType_Metrics_Header( face, 1 )) != TT_Err_Ok ||
+ /* try to load the 'vhea' & 'vmtx' at once if present */
+
+ LOAD_( Hdmx ) )
+
+ goto Fail;
+
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+ if ( ( error = Extension_Create( face ) ) != TT_Err_Ok )
+ return error;
+#endif
+
+ return TT_Err_Ok;
+
+ Fail :
+ Face_Destroy( face );
+ return error;
+ }
+
+#undef LOAD_
+
+
+/*******************************************************************
+ *
+ * Function : Glyph_Destroy
+ *
+ * Description : The glyph object destructor.
+ *
+ * Input : _glyph typeless pointer to the glyph record to destroy
+ *
+ * Output : Error code.
+ *
+ ******************************************************************/
+
+ LOCAL_FUNC
+ TT_Error Glyph_Destroy( void* _glyph )
+ {
+ PGlyph glyph = (PGlyph)_glyph;
+
+
+ if ( !glyph )
+ return TT_Err_Ok;
+
+ glyph->outline.owner = TRUE;
+ return TT_Done_Outline( &glyph->outline );
+ }
+
+
+/*******************************************************************
+ *
+ * Function : Glyph_Create
+ *
+ * Description : The glyph object constructor.
+ *
+ * Input : _glyph glyph record to build.
+ * _face the glyph's parent face.
+ *
+ * Output : Error code.
+ *
+ ******************************************************************/
+
+ LOCAL_FUNC
+ TT_Error Glyph_Create( void* _glyph,
+ void* _face )
+ {
+ PFace face = (PFace)_face;
+ PGlyph glyph = (PGlyph)_glyph;
+
+
+ if ( !face )
+ return TT_Err_Invalid_Face_Handle;
+
+ if ( !glyph )
+ return TT_Err_Invalid_Glyph_Handle;
+
+ glyph->face = face;
+
+ /* XXX: Don't forget the space for the 2 phantom points */
+ return TT_New_Outline( glyph->face->maxPoints + 2,
+ glyph->face->maxContours,
+ &glyph->outline );
+ }
+
+
+/*******************************************************************
+ *
+ * Function : Scale_X
+ *
+ * Description : scale an horizontal distance from font
+ * units to 26.6 pixels
+ *
+ * Input : metrics pointer to metrics
+ * x value to scale
+ *
+ * Output : scaled value
+ *
+ ******************************************************************/
+
+ LOCAL_FUNC
+ TT_Pos Scale_X( PIns_Metrics metrics, TT_Pos x )
+ {
+ return TT_MulDiv( x, metrics->x_scale1, metrics->x_scale2 );
+ }
+
+
+/*******************************************************************
+ *
+ * Function : Scale_Y
+ *
+ * Description : scale a vertical distance from font
+ * units to 26.6 pixels
+ *
+ * Input : metrics pointer to metrics
+ * y value to scale
+ *
+ * Output : scaled value
+ *
+ ******************************************************************/
+
+ LOCAL_FUNC
+ TT_Pos Scale_Y( PIns_Metrics metrics, TT_Pos y )
+ {
+ return TT_MulDiv( y, metrics->y_scale1, metrics->y_scale2 );
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TTObjs_Init
+ *
+ * Description : The TTObjs component initializer. Creates the
+ * object cache classes, as well as the face record
+ * cache.
+ *
+ * Input : engine engine instance
+ *
+ * Output : Error code.
+ *
+ ******************************************************************/
+
+ static
+ const TCache_Class objs_face_class =
+ {
+ sizeof ( TFace ),
+ -1,
+ Face_Create,
+ Face_Destroy,
+ NULL,
+ NULL
+ };
+
+ static
+ const TCache_Class objs_instance_class =
+ {
+ sizeof ( TInstance ),
+ -1,
+ Instance_Create,
+ Instance_Destroy,
+ NULL,
+ NULL
+ };
+
+ /* Note that we use a cache size of 1 for the execution context. */
+ /* This is to avoid re-creating a new context each time we */
+ /* change one instance's attribute (resolution and/or char sizes) */
+ /* or when we load a glyph. */
+
+ static
+ const TCache_Class objs_exec_class =
+ {
+ sizeof ( TExecution_Context ),
+ 1,
+ Context_Create,
+ Context_Destroy,
+ NULL,
+ NULL
+ };
+
+ static
+ const TCache_Class objs_glyph_class =
+ {
+ sizeof ( TGlyph ),
+ -1,
+ Glyph_Create,
+ Glyph_Destroy,
+ NULL,
+ NULL
+ };
+
+
+ LOCAL_FUNC
+ TT_Error TTObjs_Init( PEngine_Instance engine )
+ {
+ PCache face_cache, exec_cache;
+ TT_Error error;
+
+
+ face_cache = 0;
+ exec_cache = 0;
+
+ if ( ALLOC( face_cache, sizeof ( TCache ) ) ||
+ ALLOC( exec_cache, sizeof ( TCache ) ) )
+ goto Fail;
+
+ /* create face cache */
+ error = Cache_Create( engine, (PCache_Class)&objs_face_class,
+ face_cache, &engine->lock );
+ if ( error )
+ goto Fail;
+
+ engine->objs_face_cache = face_cache;
+
+ error = Cache_Create( engine, (PCache_Class)&objs_exec_class,
+ exec_cache, &engine->lock );
+ if ( error )
+ goto Fail;
+
+ engine->objs_exec_cache = exec_cache;
+
+ engine->objs_face_class = (PCache_Class)&objs_face_class;
+ engine->objs_instance_class = (PCache_Class)&objs_instance_class;
+ engine->objs_execution_class = (PCache_Class)&objs_exec_class;
+ engine->objs_glyph_class = (PCache_Class)&objs_glyph_class;
+
+ goto Exit;
+
+ Fail:
+ FREE( face_cache );
+ FREE( exec_cache );
+
+ Exit:
+ return error;
+ }
+
+
+/*******************************************************************
+ *
+ * Function : TTObjs_Done
+ *
+ * Description : The TTObjs component finalizer.
+ *
+ * Input : engine engine instance
+ *
+ * Output : Error code.
+ *
+ ******************************************************************/
+
+ LOCAL_FUNC
+ TT_Error TTObjs_Done( PEngine_Instance engine )
+ {
+ /* destroy all active faces and contexts before releasing the */
+ /* caches */
+ Cache_Destroy( (TCache*)engine->objs_exec_cache );
+ Cache_Destroy( (TCache*)engine->objs_face_cache );
+
+ /* Now frees caches and cache classes */
+ FREE( engine->objs_exec_cache );
+ FREE( engine->objs_face_cache );
+
+ return TT_Err_Ok;
+ }
+
+
+/* END */