tt_driver_done( FT_Module ttdriver ) /* TT_Driver */ { #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER TT_Driver driver = (TT_Driver)ttdriver; /* destroy the execution context */ if ( driver->context ) { TT_Done_Context( driver->context ); driver->context = NULL; } #else FT_UNUSED( ttdriver ); #endif }
static void tt_size_done_bytecode( FT_Size ftsize ) { TT_Size size = (TT_Size)ftsize; TT_Face face = (TT_Face)ftsize->face; FT_Memory memory = face->root.memory; if ( size->context ) { TT_Done_Context( size->context ); size->context = NULL; } FT_FREE( size->cvt ); size->cvt_size = 0; /* free storage area */ FT_FREE( size->storage ); size->storage_size = 0; /* twilight zone */ tt_glyphzone_done( &size->twilight ); FT_FREE( size->function_defs ); FT_FREE( size->instruction_defs ); size->num_function_defs = 0; size->max_function_defs = 0; size->num_instruction_defs = 0; size->max_instruction_defs = 0; size->max_func = 0; size->max_ins = 0; size->bytecode_ready = -1; size->cvt_ready = -1; }
LOCAL_DEF FT_Error TT_Reset_Size(TT_Size size) { TT_Face face; FT_Error error = TT_Err_Ok; FT_Size_Metrics *metrics; if(size->ttmetrics.valid) { return TT_Err_Ok; } face = (TT_Face)size->root.face; metrics = &size->root.metrics; if(metrics->x_ppem < 1 || metrics->y_ppem < 1) { return TT_Err_Invalid_PPem; } /* compute new transformation */ if(metrics->x_ppem >= metrics->y_ppem) { size->ttmetrics.scale = metrics->x_scale; size->ttmetrics.ppem = metrics->x_ppem; size->ttmetrics.x_ratio = 0x10000L; size->ttmetrics.y_ratio = FT_MulDiv(metrics->y_ppem, 0x10000L, metrics->x_ppem); } else { size->ttmetrics.scale = metrics->y_scale; size->ttmetrics.ppem = metrics->y_ppem; size->ttmetrics.x_ratio = FT_MulDiv(metrics->x_ppem, 0x10000L, metrics->y_ppem); size->ttmetrics.y_ratio = 0x10000L; } /* Compute root ascender, descender, test height, and max_advance */ metrics->ascender = (FT_MulFix(face->root.ascender, metrics->y_scale) + 32) & - 64; metrics->descender = (FT_MulFix(face->root.descender, metrics->y_scale) + 32) & - 64; metrics->height = (FT_MulFix(face->root.height, metrics->y_scale) + 32) & - 64; metrics->max_advance = (FT_MulFix(face->root.max_advance_width, metrics->x_scale) + 32) & - 64; #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER { TT_ExecContext exec; FT_UInt i, j; /* Scale the cvt values to the new ppem. */ /* We use by default the y ppem to scale the CVT. */ for(i = 0; i < size->cvt_size; i++) size->cvt[i] = FT_MulFix(face->cvt[i], size->ttmetrics.scale); /* All twilight points are originally zero */ for(j = 0; j < size->twilight.n_points; j++) { size->twilight.org[j].x = 0; size->twilight.org[j].y = 0; size->twilight.cur[j].x = 0; size->twilight.cur[j].y = 0; } /* clear storage area */ for(i = 0; i < size->storage_size; i++) size->storage[i] = 0; size->GS = tt_default_graphics_state; /* get execution context and run prep program */ if(size->debug) { exec = size->context; } else { exec = TT_New_Context(face); } /* debugging instances have their own context */ if(!exec) { return TT_Err_Could_Not_Find_Context; } TT_Load_Context(exec, face, size); TT_Set_CodeRange(exec, tt_coderange_cvt, face->cvt_program, face->cvt_program_size); TT_Clear_CodeRange(exec, tt_coderange_glyph); exec->instruction_trap = FALSE; exec->top = 0; exec->callTop = 0; if(face->cvt_program_size > 0) { error = TT_Goto_CodeRange(exec, tt_coderange_cvt, 0); if(error) { goto End; } if(!size->debug) { error = face->interpreter(exec); } } else { error = TT_Err_Ok; } size->GS = exec->GS; /* save default graphics state */ End: TT_Save_Context(exec, size); if(!size->debug) { TT_Done_Context(exec); } /* debugging instances keep their context */ } #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ if(!error) { size->ttmetrics.valid = TRUE; } return error; }
LOCAL_DEF FT_Error TT_Init_Size(TT_Size size) { FT_Error error = TT_Err_Ok; #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER TT_Face face = (TT_Face)size->root.face; FT_Memory memory = face->root.memory; FT_Int i; TT_ExecContext exec; FT_UShort n_twilight; TT_MaxProfile *maxp = &face->max_profile; size->ttmetrics.valid = FALSE; size->max_function_defs = maxp->maxFunctionDefs; size->max_instruction_defs = maxp->maxInstructionDefs; size->num_function_defs = 0; size->num_instruction_defs = 0; size->max_func = 0; size->max_ins = 0; size->cvt_size = face->cvt_size; size->storage_size = maxp->maxStorage; /* Set default metrics */ { FT_Size_Metrics *metrics = &size->root.metrics; TT_Size_Metrics *metrics2 = &size->ttmetrics; metrics->x_ppem = 0; metrics->y_ppem = 0; metrics2->rotated = FALSE; metrics2->stretched = FALSE; /* set default compensation (all 0) */ for(i = 0; i < 4; i++) metrics2->compensations[i] = 0; } /* allocate function defs, instruction defs, cvt, and storage area */ if(ALLOC_ARRAY(size->function_defs, size->max_function_defs, TT_DefRecord) || ALLOC_ARRAY(size->instruction_defs, size->max_instruction_defs, TT_DefRecord) || ALLOC_ARRAY(size->cvt, size->cvt_size, FT_Long) || ALLOC_ARRAY(size->storage, size->storage_size, FT_Long)) { goto Fail_Memory; } /* reserve twilight zone */ n_twilight = maxp->maxTwilightPoints; error = TT_New_GlyphZone(memory, n_twilight, 0, &size->twilight); if(error) { goto Fail_Memory; } size->twilight.n_points = n_twilight; /* set `face->interpreter' according to the debug hook present */ { FT_Library library = face->root.driver->root.library; face->interpreter = (TT_Interpreter) library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE]; if(!face->interpreter) { face->interpreter = (TT_Interpreter)TT_RunIns; } } /* Fine, now execute the font program! */ exec = size->context; /* size objects used during debugging have their own context */ if(!size->debug) { exec = TT_New_Context(face); } if(!exec) { error = TT_Err_Could_Not_Find_Context; goto Fail_Memory; } size->GS = tt_default_graphics_state; TT_Load_Context(exec, face, size); exec->callTop = 0; exec->top = 0; exec->period = 64; exec->phase = 0; exec->threshold = 0; { FT_Size_Metrics *metrics = &exec->metrics; TT_Size_Metrics *tt_metrics = &exec->tt_metrics; metrics->x_ppem = 0; metrics->y_ppem = 0; metrics->x_scale = 0; metrics->y_scale = 0; tt_metrics->ppem = 0; tt_metrics->scale = 0; tt_metrics->ratio = 0x10000L; } exec->instruction_trap = FALSE; exec->cvtSize = size->cvt_size; exec->cvt = size->cvt; exec->F_dot_P = 0x10000L; /* allow font program execution */ TT_Set_CodeRange(exec, tt_coderange_font, face->font_program, face->font_program_size); /* disable CVT and glyph programs coderange */ TT_Clear_CodeRange(exec, tt_coderange_cvt); TT_Clear_CodeRange(exec, tt_coderange_glyph); if(face->font_program_size > 0) { error = TT_Goto_CodeRange(exec, tt_coderange_font, 0); if(!error) { error = face->interpreter(exec); } if(error) { goto Fail_Exec; } } else { error = TT_Err_Ok; } TT_Save_Context(exec, size); if(!size->debug) { TT_Done_Context(exec); } #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ size->ttmetrics.valid = FALSE; return error; #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER Fail_Exec: if(!size->debug) { TT_Done_Context(exec); } Fail_Memory: #endif TT_Done_Size(size); return error; }
/* We do this only if bytecode interpretation is really needed. */ static FT_Error tt_size_init_bytecode( FT_Size ftsize, FT_Bool pedantic ) { FT_Error error; TT_Size size = (TT_Size)ftsize; TT_Face face = (TT_Face)ftsize->face; FT_Memory memory = face->root.memory; FT_UShort n_twilight; TT_MaxProfile* maxp = &face->max_profile; /* clean up bytecode related data */ FT_FREE( size->function_defs ); FT_FREE( size->instruction_defs ); FT_FREE( size->cvt ); FT_FREE( size->storage ); if ( size->context ) TT_Done_Context( size->context ); tt_glyphzone_done( &size->twilight ); size->bytecode_ready = -1; size->cvt_ready = -1; size->context = TT_New_Context( (TT_Driver)face->root.driver ); size->max_function_defs = maxp->maxFunctionDefs; size->max_instruction_defs = maxp->maxInstructionDefs; size->num_function_defs = 0; size->num_instruction_defs = 0; size->max_func = 0; size->max_ins = 0; size->cvt_size = face->cvt_size; size->storage_size = maxp->maxStorage; /* Set default metrics */ { TT_Size_Metrics* metrics = &size->ttmetrics; metrics->rotated = FALSE; metrics->stretched = FALSE; /* set default engine compensation */ metrics->compensations[0] = 0; /* gray */ metrics->compensations[1] = 0; /* black */ metrics->compensations[2] = 0; /* white */ metrics->compensations[3] = 0; /* reserved */ } /* allocate function defs, instruction defs, cvt, and storage area */ if ( FT_NEW_ARRAY( size->function_defs, size->max_function_defs ) || FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) || FT_NEW_ARRAY( size->cvt, size->cvt_size ) || FT_NEW_ARRAY( size->storage, size->storage_size ) ) goto Exit; /* reserve twilight zone */ n_twilight = maxp->maxTwilightPoints; /* there are 4 phantom points (do we need this?) */ n_twilight += 4; error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight ); if ( error ) goto Exit; size->twilight.n_points = n_twilight; size->GS = tt_default_graphics_state; /* set `face->interpreter' according to the debug hook present */ { FT_Library library = face->root.driver->root.library; face->interpreter = (TT_Interpreter) library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE]; if ( !face->interpreter ) face->interpreter = (TT_Interpreter)TT_RunIns; } /* Fine, now run the font program! */ /* In case of an error while executing `fpgm', we intentionally don't */ /* clean up immediately – bugs in the `fpgm' are so fundamental that */ /* all following hinting calls should fail. Additionally, `fpgm' is */ /* to be executed just once; calling it again is completely useless */ /* and might even lead to extremely slow behaviour if it is malformed */ /* (containing an infinite loop, for example). */ error = tt_size_run_fpgm( size, pedantic ); return error; Exit: if ( error ) tt_size_done_bytecode( ftsize ); return error; }