Initial revision

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1475 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2002-10-10 00:11:16 +00:00
parent e5670b2d08
commit 98f8b76574
44 changed files with 17695 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,317 @@
/***************************************************************************/
/* */
/* ttinterp.h */
/* */
/* TrueType bytecode interpreter (specification). */
/* */
/* Copyright 1996-2001, 2002 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. */
/* */
/***************************************************************************/
#ifndef __TTINTERP_H__
#define __TTINTERP_H__
#include <ft2build.h>
#include "ttobjs.h"
FT_BEGIN_HEADER
#ifndef TT_CONFIG_OPTION_STATIC_INTEPRETER /* indirect implementation */
#define EXEC_OP_ TT_ExecContext exc,
#define EXEC_OP TT_ExecContext exc
#define EXEC_ARG_ exc,
#define EXEC_ARG exc
#else /* static implementation */
#define EXEC_OP_ /* void */
#define EXEC_OP /* void */
#define EXEC_ARG_ /* void */
#define EXEC_ARG /* void */
#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
/*************************************************************************/
/* */
/* Rounding mode constants. */
/* */
#define TT_Round_Off 5
#define TT_Round_To_Half_Grid 0
#define TT_Round_To_Grid 1
#define TT_Round_To_Double_Grid 2
#define TT_Round_Up_To_Grid 4
#define TT_Round_Down_To_Grid 3
#define TT_Round_Super 6
#define TT_Round_Super_45 7
/*************************************************************************/
/* */
/* Function types used by the interpreter, depending on various modes */
/* (e.g. the rounding mode, whether to render a vertical or horizontal */
/* line etc). */
/* */
/*************************************************************************/
/* Rounding function */
typedef FT_F26Dot6
(*TT_Round_Func)( EXEC_OP_ FT_F26Dot6 distance,
FT_F26Dot6 compensation );
/* Point displacement along the freedom vector routine */
typedef void
(*TT_Move_Func)( EXEC_OP_ TT_GlyphZone zone,
FT_UShort point,
FT_F26Dot6 distance );
/* Distance projection along one of the projection vectors */
typedef FT_F26Dot6
(*TT_Project_Func)( EXEC_OP_ FT_Vector* v1,
FT_Vector* v2 );
/* reading a cvt value. Take care of non-square pixels if necessary */
typedef FT_F26Dot6
(*TT_Get_CVT_Func)( EXEC_OP_ FT_ULong idx );
/* setting or moving a cvt value. Take care of non-square pixels */
/* if necessary */
typedef void
(*TT_Set_CVT_Func)( EXEC_OP_ FT_ULong idx,
FT_F26Dot6 value );
/*************************************************************************/
/* */
/* This structure defines a call record, used to manage function calls. */
/* */
typedef struct TT_CallRec_
{
FT_Int Caller_Range;
FT_Long Caller_IP;
FT_Long Cur_Count;
FT_Long Cur_Restart;
} TT_CallRec, *TT_CallStack;
/*************************************************************************/
/* */
/* The main structure for the interpreter which collects all necessary */
/* variables and states. */
/* */
typedef struct TT_ExecContextRec_
{
TT_Face face;
TT_Size size;
FT_Memory memory;
/* instructions state */
FT_Error error; /* last execution error */
FT_Long top; /* top of exec. stack */
FT_UInt stackSize; /* size of exec. stack */
FT_Long* stack; /* current exec. stack */
FT_Long args;
FT_UInt new_top; /* new top after exec. */
TT_GlyphZoneRec zp0, /* zone records */
zp1,
zp2,
pts,
twilight;
FT_Size_Metrics metrics;
TT_Size_Metrics tt_metrics; /* size metrics */
TT_GraphicsState GS; /* current graphics state */
FT_Int curRange; /* current code range number */
FT_Byte* code; /* current code range */
FT_Long IP; /* current instruction pointer */
FT_Long codeSize; /* size of current range */
FT_Byte opcode; /* current opcode */
FT_Int length; /* length of current opcode */
FT_Bool step_ins; /* true if the interpreter must */
/* increment IP after ins. exec */
FT_Long cvtSize;
FT_Long* cvt;
FT_UInt glyphSize; /* glyph instructions buffer size */
FT_Byte* glyphIns; /* glyph instructions buffer */
FT_UInt numFDefs; /* number of function defs */
FT_UInt maxFDefs; /* maximum number of function defs */
TT_DefArray FDefs; /* table of FDefs entries */
FT_UInt numIDefs; /* number of instruction defs */
FT_UInt maxIDefs; /* maximum number of ins defs */
TT_DefArray IDefs; /* table of IDefs entries */
FT_UInt maxFunc; /* maximum function index */
FT_UInt maxIns; /* maximum instruction index */
FT_Int callTop, /* top of call stack during execution */
callSize; /* size of call stack */
TT_CallStack callStack; /* call stack */
FT_UShort maxPoints; /* capacity of this context's `pts' */
FT_Short maxContours; /* record, expressed in points and */
/* contours. */
TT_CodeRangeTable codeRangeTable; /* table of valid code ranges */
/* useful for the debugger */
FT_UShort storeSize; /* size of current storage */
FT_Long* storage; /* storage area */
FT_F26Dot6 period; /* values used for the */
FT_F26Dot6 phase; /* `SuperRounding' */
FT_F26Dot6 threshold;
#if 0
/* this seems to be unused */
FT_Int cur_ppem; /* ppem along the current proj vector */
#endif
FT_Bool instruction_trap; /* If `True', the interpreter will */
/* exit after each instruction */
TT_GraphicsState default_GS; /* graphics state resulting from */
/* the prep program */
FT_Bool is_composite; /* true if the glyph is composite */
FT_Bool pedantic_hinting; /* true if pedantic interpretation */
/* latest interpreter additions */
FT_Long F_dot_P; /* dot product of freedom and projection */
/* vectors */
TT_Round_Func func_round; /* current rounding function */
TT_Project_Func func_project, /* current projection function */
func_dualproj, /* current dual proj. function */
func_freeProj; /* current freedom proj. func */
TT_Move_Func func_move; /* current point move function */
TT_Get_CVT_Func func_read_cvt; /* read a cvt entry */
TT_Set_CVT_Func func_write_cvt; /* write a cvt entry (in pixels) */
TT_Set_CVT_Func func_move_cvt; /* incr a cvt entry (in pixels) */
FT_ULong loadSize;
TT_SubGlyph_Stack loadStack; /* loading subglyph stack */
} TT_ExecContextRec;
extern const TT_GraphicsState tt_default_graphics_state;
FT_LOCAL( FT_Error )
TT_Goto_CodeRange( TT_ExecContext exec,
FT_Int range,
FT_Long IP );
FT_LOCAL( FT_Error )
TT_Set_CodeRange( TT_ExecContext exec,
FT_Int range,
void* base,
FT_Long length );
FT_LOCAL( FT_Error )
TT_Clear_CodeRange( TT_ExecContext exec,
FT_Int range );
/*************************************************************************/
/* */
/* <Function> */
/* TT_New_Context */
/* */
/* <Description> */
/* Queries the face context for a given font. Note that there is */
/* now a _single_ execution context in the TrueType driver which is */
/* shared among faces. */
/* */
/* <Input> */
/* face :: A handle to the source face object. */
/* */
/* <Return> */
/* A handle to the execution context. Initialized for `face'. */
/* */
/* <Note> */
/* Only the glyph loader and debugger should call this function. */
/* */
FT_EXPORT( TT_ExecContext )
TT_New_Context( TT_Face face );
FT_LOCAL( FT_Error )
TT_Done_Context( TT_ExecContext exec );
FT_LOCAL( FT_Error )
TT_Destroy_Context( TT_ExecContext exec,
FT_Memory memory );
FT_LOCAL( FT_Error )
TT_Load_Context( TT_ExecContext exec,
TT_Face face,
TT_Size size );
FT_LOCAL( FT_Error )
TT_Save_Context( TT_ExecContext exec,
TT_Size ins );
FT_LOCAL( FT_Error )
TT_Run_Context( TT_ExecContext exec,
FT_Bool debug );
/*************************************************************************/
/* */
/* <Function> */
/* TT_RunIns */
/* */
/* <Description> */
/* Executes one or more instruction in the execution context. This */
/* is the main function of the TrueType opcode interpreter. */
/* */
/* <Input> */
/* exec :: A handle to the target execution context. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
/* <Note> */
/* Only the object manager and debugger should call this function. */
/* */
/* This function is publicly exported because it is directly */
/* invoked by the TrueType debugger. */
/* */
FT_EXPORT( FT_Error )
TT_RunIns( TT_ExecContext exec );
FT_END_HEADER
#endif /* __TTINTERP_H__ */
/* END */

View File

@ -0,0 +1,844 @@
/***************************************************************************/
/* */
/* ttobjs.c */
/* */
/* Objects manager (body). */
/* */
/* Copyright 1996-2001, 2002 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 <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_CALC_H
#include FT_INTERNAL_STREAM_H
#include FT_TRUETYPE_IDS_H
#include FT_TRUETYPE_TAGS_H
#include FT_INTERNAL_SFNT_H
#include FT_INTERNAL_POSTSCRIPT_NAMES_H
#include "ttgload.h"
#include "ttpload.h"
#include "tterrors.h"
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
#include "ttinterp.h"
#endif
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_ttobjs
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
/*************************************************************************/
/* */
/* GLYPH ZONE FUNCTIONS */
/* */
/*************************************************************************/
/*************************************************************************/
/* */
/* <Function> */
/* TT_Done_GlyphZone */
/* */
/* <Description> */
/* Deallocates a glyph zone. */
/* */
/* <Input> */
/* zone :: A pointer to the target glyph zone. */
/* */
FT_LOCAL_DEF( void )
TT_Done_GlyphZone( TT_GlyphZone zone )
{
FT_Memory memory = zone->memory;
FT_FREE( zone->contours );
FT_FREE( zone->tags );
FT_FREE( zone->cur );
FT_FREE( zone->org );
zone->max_points = zone->n_points = 0;
zone->max_contours = zone->n_contours = 0;
}
/*************************************************************************/
/* */
/* <Function> */
/* TT_New_GlyphZone */
/* */
/* <Description> */
/* Allocates a new glyph zone. */
/* */
/* <Input> */
/* memory :: A handle to the current memory object. */
/* */
/* maxPoints :: The capacity of glyph zone in points. */
/* */
/* maxContours :: The capacity of glyph zone in contours. */
/* */
/* <Output> */
/* zone :: A pointer to the target glyph zone record. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
TT_New_GlyphZone( FT_Memory memory,
FT_UShort maxPoints,
FT_Short maxContours,
TT_GlyphZone zone )
{
FT_Error error;
if ( maxPoints > 0 )
maxPoints += 2;
FT_MEM_SET( zone, 0, sizeof ( *zone ) );
zone->memory = memory;
if ( FT_NEW_ARRAY( zone->org, maxPoints * 2 ) ||
FT_NEW_ARRAY( zone->cur, maxPoints * 2 ) ||
FT_NEW_ARRAY( zone->tags, maxPoints ) ||
FT_NEW_ARRAY( zone->contours, maxContours ) )
{
TT_Done_GlyphZone( zone );
}
return error;
}
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
/*************************************************************************/
/* */
/* <Function> */
/* TT_Face_Init */
/* */
/* <Description> */
/* Initializes a given TrueType face object. */
/* */
/* <Input> */
/* stream :: The source font stream. */
/* */
/* face_index :: The index of the font face in the resource. */
/* */
/* num_params :: Number of additional generic parameters. Ignored. */
/* */
/* params :: Additional generic parameters. Ignored. */
/* */
/* <InOut> */
/* face :: The newly built face object. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
TT_Face_Init( FT_Stream stream,
TT_Face face,
FT_Int face_index,
FT_Int num_params,
FT_Parameter* params )
{
FT_Error error;
FT_Library library;
SFNT_Service sfnt;
library = face->root.driver->root.library;
sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
if ( !sfnt )
goto Bad_Format;
/* create input stream from resource */
if ( FT_STREAM_SEEK( 0 ) )
goto Exit;
/* check that we have a valid TrueType file */
error = sfnt->init_face( stream, face, face_index, num_params, params );
if ( error )
goto Exit;
/* We must also be able to accept Mac/GX fonts, as well as OT ones */
if ( face->format_tag != 0x00010000L && /* MS fonts */
face->format_tag != TTAG_true ) /* Mac fonts */
{
FT_TRACE2(( "[not a valid TTF font]\n" ));
goto Bad_Format;
}
/* If we are performing a simple font format check, exit immediately */
if ( face_index < 0 )
return TT_Err_Ok;
/* Load font directory */
error = sfnt->load_face( stream, face, face_index, num_params, params );
if ( error )
goto Exit;
if ( face->root.face_flags & FT_FACE_FLAG_SCALABLE )
error = TT_Load_Locations( face, stream ) ||
TT_Load_CVT ( face, stream ) ||
TT_Load_Programs ( face, stream );
/* initialize standard glyph loading routines */
TT_Init_Glyph_Loading( face );
Exit:
return error;
Bad_Format:
error = TT_Err_Unknown_File_Format;
goto Exit;
}
/*************************************************************************/
/* */
/* <Function> */
/* TT_Face_Done */
/* */
/* <Description> */
/* Finalizes a given face object. */
/* */
/* <Input> */
/* face :: A pointer to the face object to destroy. */
/* */
FT_LOCAL_DEF( void )
TT_Face_Done( TT_Face face )
{
FT_Memory memory = face->root.memory;
FT_Stream stream = face->root.stream;
SFNT_Service sfnt = (SFNT_Service)face->sfnt;
/* for `extended TrueType formats' (i.e. compressed versions) */
if ( face->extra.finalizer )
face->extra.finalizer( face->extra.data );
if ( sfnt )
sfnt->done_face( face );
/* freeing the locations table */
FT_FREE( face->glyph_locations );
face->num_locations = 0;
/* freeing the CVT */
FT_FREE( face->cvt );
face->cvt_size = 0;
/* freeing the programs */
FT_FRAME_RELEASE( face->font_program );
FT_FRAME_RELEASE( face->cvt_program );
face->font_program_size = 0;
face->cvt_program_size = 0;
}
/*************************************************************************/
/* */
/* SIZE FUNCTIONS */
/* */
/*************************************************************************/
/*************************************************************************/
/* */
/* <Function> */
/* TT_Size_Init */
/* */
/* <Description> */
/* Initializes a new TrueType size object. */
/* */
/* <InOut> */
/* size :: A handle to the size object. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
TT_Size_Init( 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 ( 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 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:
TT_Size_Done( size );
return error;
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
}
/*************************************************************************/
/* */
/* <Function> */
/* TT_Size_Done */
/* */
/* <Description> */
/* The TrueType size object finalizer. */
/* */
/* <Input> */
/* size :: A handle to the target size object. */
/* */
FT_LOCAL_DEF( void )
TT_Size_Done( TT_Size size )
{
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
FT_Memory memory = size->root.face->memory;
if ( size->debug )
{
/* the debug context must be deleted by the debugger itself */
size->context = NULL;
size->debug = FALSE;
}
FT_FREE( size->cvt );
size->cvt_size = 0;
/* free storage area */
FT_FREE( size->storage );
size->storage_size = 0;
/* twilight zone */
TT_Done_GlyphZone( &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;
#endif
size->ttmetrics.valid = FALSE;
}
/*************************************************************************/
/* */
/* <Function> */
/* Reset_Outline_Size */
/* */
/* <Description> */
/* Resets a TrueType outline size when resolutions and character */
/* dimensions have been changed. */
/* */
/* <Input> */
/* size :: A handle to the target size object. */
/* */
static FT_Error
Reset_Outline_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_EMBEDDED_BITMAPS
/* set to `invalid' by default */
size->strike_index = 0xFFFFU;
#endif
#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 < (FT_UInt)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 < (FT_UInt)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;
}
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
/*************************************************************************/
/* */
/* <Function> */
/* Reset_SBit_Size */
/* */
/* <Description> */
/* Resets a TrueType sbit size when resolutions and character */
/* dimensions have been changed. */
/* */
/* <Input> */
/* size :: A handle to the target size object. */
/* */
static FT_Error
Reset_SBit_Size( TT_Size size )
{
TT_Face face;
FT_Error error = TT_Err_Ok;
FT_ULong strike_index;
FT_Size_Metrics* metrics;
FT_Size_Metrics* sbit_metrics;
SFNT_Service sfnt;
metrics = &size->root.metrics;
if ( size->strike_index != 0xFFFFU )
return TT_Err_Ok;
face = (TT_Face)size->root.face;
sfnt = (SFNT_Service)face->sfnt;
sbit_metrics = &size->strike_metrics;
error = sfnt->set_sbit_strike(face,
metrics->x_ppem, metrics->y_ppem,
&strike_index);
if ( !error )
{
TT_SBit_Strike strike = face->sbit_strikes + strike_index;
sbit_metrics->x_ppem = metrics->x_ppem;
sbit_metrics->y_ppem = metrics->y_ppem;
#if 0
/*
* sbit_metrics->?_scale
* are not used now.
*/
sbit_metrics->x_scale = 1 << 16;
sbit_metrics->y_scale = 1 << 16;
#endif
sbit_metrics->ascender = strike->hori.ascender << 6;
sbit_metrics->descender = strike->hori.descender << 6;
/* XXX: Is this correct? */
sbit_metrics->height = sbit_metrics->ascender -
sbit_metrics->descender;
/* XXX: Is this correct? */
sbit_metrics->max_advance = ( strike->hori.min_origin_SB +
strike->hori.max_width +
strike->hori.min_advance_SB ) << 6;
size->strike_index = strike_index;
}
else
{
size->strike_index = 0xFFFFU;
sbit_metrics->x_ppem = 0;
sbit_metrics->y_ppem = 0;
sbit_metrics->ascender = 0;
sbit_metrics->descender = 0;
sbit_metrics->height = 0;
sbit_metrics->max_advance = 0;
}
return error;
}
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
/*************************************************************************/
/* */
/* <Function> */
/* TT_Size_Reset */
/* */
/* <Description> */
/* Resets a TrueType size when resolutions and character dimensions */
/* have been changed. */
/* */
/* <Input> */
/* size :: A handle to the target size object. */
/* */
FT_LOCAL_DEF( FT_Error )
TT_Size_Reset( TT_Size size )
{
FT_Face face;
FT_Error error = TT_Err_Ok;
face = size->root.face;
if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
{
if ( !size->ttmetrics.valid )
error = Reset_Outline_Size( size );
if ( error )
return error;
}
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
if ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES )
{
if ( size->strike_index == 0xFFFFU )
error = Reset_SBit_Size( size );
if ( !error && !( face->face_flags & FT_FACE_FLAG_SCALABLE ) )
size->root.metrics = size->strike_metrics;
}
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
return TT_Err_Ok;
else
return error;
}
/*************************************************************************/
/* */
/* <Function> */
/* TT_Driver_Init */
/* */
/* <Description> */
/* Initializes a given TrueType driver object. */
/* */
/* <Input> */
/* driver :: A handle to the target driver object. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
TT_Driver_Init( TT_Driver driver )
{
FT_Error error;
/* set `extra' in glyph loader */
error = FT_GlyphLoader_CreateExtra( FT_DRIVER( driver )->glyph_loader );
return error;
}
/*************************************************************************/
/* */
/* <Function> */
/* TT_Driver_Done */
/* */
/* <Description> */
/* Finalizes a given TrueType driver. */
/* */
/* <Input> */
/* driver :: A handle to the target TrueType driver. */
/* */
FT_LOCAL_DEF( void )
TT_Driver_Done( TT_Driver driver )
{
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
/* destroy the execution context */
if ( driver->context )
{
TT_Destroy_Context( driver->context, driver->root.root.memory );
driver->context = NULL;
}
#else
FT_UNUSED( driver );
#endif
}
/* END */

View File

@ -0,0 +1,422 @@
/***************************************************************************/
/* */
/* ttobjs.h */
/* */
/* Objects manager (specification). */
/* */
/* Copyright 1996-2001, 2002 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. */
/* */
/***************************************************************************/
#ifndef __TTOBJS_H__
#define __TTOBJS_H__
#include <ft2build.h>
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_TRUETYPE_TYPES_H
FT_BEGIN_HEADER
/*************************************************************************/
/* */
/* <Type> */
/* TT_Driver */
/* */
/* <Description> */
/* A handle to a TrueType driver object. */
/* */
typedef struct TT_DriverRec_* TT_Driver;
/*************************************************************************/
/* */
/* <Type> */
/* TT_Instance */
/* */
/* <Description> */
/* A handle to a TrueType size object. */
/* */
typedef struct TT_SizeRec_* TT_Size;
/*************************************************************************/
/* */
/* <Type> */
/* TT_GlyphSlot */
/* */
/* <Description> */
/* A handle to a TrueType glyph slot object. */
/* */
/* <Note> */
/* This is a direct typedef of FT_GlyphSlot, as there is nothing */
/* specific about the TrueType glyph slot. */
/* */
typedef FT_GlyphSlot TT_GlyphSlot;
/*************************************************************************/
/* */
/* <Struct> */
/* TT_GraphicsState */
/* */
/* <Description> */
/* The TrueType graphics state used during bytecode interpretation. */
/* */
typedef struct TT_GraphicsState_
{
FT_UShort rp0;
FT_UShort rp1;
FT_UShort rp2;
FT_UnitVector dualVector;
FT_UnitVector projVector;
FT_UnitVector freeVector;
FT_Long loop;
FT_F26Dot6 minimum_distance;
FT_Int round_state;
FT_Bool auto_flip;
FT_F26Dot6 control_value_cutin;
FT_F26Dot6 single_width_cutin;
FT_F26Dot6 single_width_value;
FT_Short delta_base;
FT_Short delta_shift;
FT_Byte instruct_control;
FT_Bool scan_control;
FT_Int scan_type;
FT_UShort gep0;
FT_UShort gep1;
FT_UShort gep2;
} TT_GraphicsState;
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
FT_LOCAL( void )
TT_Done_GlyphZone( TT_GlyphZone zone );
FT_LOCAL( FT_Error )
TT_New_GlyphZone( FT_Memory memory,
FT_UShort maxPoints,
FT_Short maxContours,
TT_GlyphZone zone );
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
/*************************************************************************/
/* */
/* EXECUTION SUBTABLES */
/* */
/* These sub-tables relate to instruction execution. */
/* */
/*************************************************************************/
#define TT_MAX_CODE_RANGES 3
/*************************************************************************/
/* */
/* There can only be 3 active code ranges at once: */
/* - the Font Program */
/* - the CVT Program */
/* - a glyph's instructions set */
/* */
typedef enum TT_CodeRange_Tag_
{
tt_coderange_none = 0,
tt_coderange_font,
tt_coderange_cvt,
tt_coderange_glyph
} TT_CodeRange_Tag;
typedef struct TT_CodeRange_
{
FT_Byte* base;
FT_ULong size;
} TT_CodeRange;
typedef TT_CodeRange TT_CodeRangeTable[TT_MAX_CODE_RANGES];
/*************************************************************************/
/* */
/* Defines a function/instruction definition record. */
/* */
typedef struct TT_DefRecord_
{
FT_Int range; /* in which code range is it located? */
FT_Long start; /* where does it start? */
FT_UInt opc; /* function #, or instruction code */
FT_Bool active; /* is it active? */
} TT_DefRecord, *TT_DefArray;
/*************************************************************************/
/* */
/* Subglyph transformation record. */
/* */
typedef struct TT_Transform_
{
FT_Fixed xx, xy; /* transformation matrix coefficients */
FT_Fixed yx, yy;
FT_F26Dot6 ox, oy; /* offsets */
} TT_Transform;
/*************************************************************************/
/* */
/* Subglyph loading record. Used to load composite components. */
/* */
typedef struct TT_SubglyphRec_
{
FT_Long index; /* subglyph index; initialized with -1 */
FT_Bool is_scaled; /* is the subglyph scaled? */
FT_Bool is_hinted; /* should it be hinted? */
FT_Bool preserve_pps; /* preserve phantom points? */
FT_Long file_offset;
FT_BBox bbox;
FT_Pos left_bearing;
FT_Pos advance;
TT_GlyphZoneRec zone;
FT_Long arg1; /* first argument */
FT_Long arg2; /* second argument */
FT_UShort element_flag; /* current load element flag */
TT_Transform transform; /* transformation matrix */
FT_Vector pp1, pp2; /* phantom points */
} TT_SubGlyphRec, *TT_SubGlyph_Stack;
/*************************************************************************/
/* */
/* A note regarding non-squared pixels: */
/* */
/* (This text will probably go into some docs at some time; for now, it */
/* is kept here to explain some definitions in the TIns_Metrics */
/* record). */
/* */
/* The CVT is a one-dimensional array containing values that control */
/* certain important characteristics in a font, like the height of all */
/* capitals, all lowercase letter, default spacing or stem width/height. */
/* */
/* These values are found in FUnits in the font file, and must be scaled */
/* to pixel coordinates before being used by the CVT and glyph programs. */
/* Unfortunately, when using distinct x and y resolutions (or distinct x */
/* and y pointsizes), there are two possible scalings. */
/* */
/* A first try was to implement a `lazy' scheme where all values were */
/* scaled when first used. However, while some values are always used */
/* in the same direction, some others are used under many different */
/* circumstances and orientations. */
/* */
/* I have found a simpler way to do the same, and it even seems to work */
/* in most of the cases: */
/* */
/* - All CVT values are scaled to the maximum ppem size. */
/* */
/* - When performing a read or write in the CVT, a ratio factor is used */
/* to perform adequate scaling. Example: */
/* */
/* x_ppem = 14 */
/* y_ppem = 10 */
/* */
/* We choose ppem = x_ppem = 14 as the CVT scaling size. All cvt */
/* entries are scaled to it. */
/* */
/* x_ratio = 1.0 */
/* y_ratio = y_ppem/ppem (< 1.0) */
/* */
/* We compute the current ratio like: */
/* */
/* - If projVector is horizontal, */
/* ratio = x_ratio = 1.0 */
/* */
/* - if projVector is vertical, */
/* ratio = y_ratio */
/* */
/* - else, */
/* ratio = sqrt( (proj.x * x_ratio) ^ 2 + (proj.y * y_ratio) ^ 2 ) */
/* */
/* Reading a cvt value returns */
/* ratio * cvt[index] */
/* */
/* Writing a cvt value in pixels: */
/* cvt[index] / ratio */
/* */
/* The current ppem is simply */
/* ratio * ppem */
/* */
/*************************************************************************/
/*************************************************************************/
/* */
/* Metrics used by the TrueType size and context objects. */
/* */
typedef struct TT_Size_Metrics_
{
/* for non-square pixels */
FT_Long x_ratio;
FT_Long y_ratio;
FT_UShort ppem; /* maximum ppem size */
FT_Long ratio; /* current ratio */
FT_Fixed scale;
FT_F26Dot6 compensations[4]; /* device-specific compensations */
FT_Bool valid;
FT_Bool rotated; /* `is the glyph rotated?'-flag */
FT_Bool stretched; /* `is the glyph stretched?'-flag */
} TT_Size_Metrics;
/*************************************************************************/
/* */
/* TrueType size class. */
/* */
typedef struct TT_SizeRec_
{
FT_SizeRec root;
TT_Size_Metrics ttmetrics;
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
FT_UInt strike_index; /* 0xFFFF to indicate invalid */
FT_Size_Metrics strike_metrics; /* current strike's metrics */
#endif
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
FT_UInt num_function_defs; /* number of function definitions */
FT_UInt max_function_defs;
TT_DefArray function_defs; /* table of function definitions */
FT_UInt num_instruction_defs; /* number of ins. definitions */
FT_UInt max_instruction_defs;
TT_DefArray instruction_defs; /* table of ins. definitions */
FT_UInt max_func;
FT_UInt max_ins;
TT_CodeRangeTable codeRangeTable;
TT_GraphicsState GS;
FT_ULong cvt_size; /* the scaled control value table */
FT_Long* cvt;
FT_UShort storage_size; /* The storage area is now part of */
FT_Long* storage; /* the instance */
TT_GlyphZoneRec twilight; /* The instance's twilight zone */
/* debugging variables */
/* When using the debugger, we must keep the */
/* execution context tied to the instance */
/* object rather than asking it on demand. */
FT_Bool debug;
TT_ExecContext context;
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
} TT_SizeRec;
/*************************************************************************/
/* */
/* TrueType driver class. */
/* */
typedef struct TT_DriverRec_
{
FT_DriverRec root;
TT_ExecContext context; /* execution context */
TT_GlyphZoneRec zone; /* glyph loader points zone */
void* extension_component;
} TT_DriverRec;
/*************************************************************************/
/* */
/* Face functions */
/* */
FT_LOCAL( FT_Error )
TT_Face_Init( FT_Stream stream,
TT_Face face,
FT_Int face_index,
FT_Int num_params,
FT_Parameter* params );
FT_LOCAL( void )
TT_Face_Done( TT_Face face );
/*************************************************************************/
/* */
/* Size functions */
/* */
FT_LOCAL( FT_Error )
TT_Size_Init( TT_Size size );
FT_LOCAL( void )
TT_Size_Done( TT_Size size );
FT_LOCAL( FT_Error )
TT_Size_Reset( TT_Size size );
/*************************************************************************/
/* */
/* Driver functions */
/* */
FT_LOCAL( FT_Error )
TT_Driver_Init( TT_Driver driver );
FT_LOCAL( void )
TT_Driver_Done( TT_Driver driver );
FT_END_HEADER
#endif /* __TTOBJS_H__ */
/* END */

View File

@ -0,0 +1,264 @@
/***************************************************************************/
/* */
/* ttpload.c */
/* */
/* TrueType glyph data/program tables loader (body). */
/* */
/* Copyright 1996-2001, 2002 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 <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_STREAM_H
#include FT_TRUETYPE_TAGS_H
#include "ttpload.h"
#include "tterrors.h"
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_ttpload
/*************************************************************************/
/* */
/* <Function> */
/* TT_Load_Locations */
/* */
/* <Description> */
/* Loads the locations table. */
/* */
/* <InOut> */
/* face :: A handle to the target face object. */
/* */
/* <Input> */
/* stream :: The input stream. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
TT_Load_Locations( TT_Face face,
FT_Stream stream )
{
FT_Error error;
FT_Memory memory = stream->memory;
FT_Short LongOffsets;
FT_ULong table_len;
FT_TRACE2(( "Locations " ));
LongOffsets = face->header.Index_To_Loc_Format;
error = face->goto_table( face, TTAG_loca, stream, &table_len );
if ( error )
{
error = TT_Err_Locations_Missing;
goto Exit;
}
if ( LongOffsets != 0 )
{
face->num_locations = (FT_UShort)( table_len >> 2 );
FT_TRACE2(( "(32bit offsets): %12d ", face->num_locations ));
if ( FT_NEW_ARRAY( face->glyph_locations, face->num_locations ) )
goto Exit;
if ( FT_FRAME_ENTER( face->num_locations * 4L ) )
goto Exit;
{
FT_Long* loc = face->glyph_locations;
FT_Long* limit = loc + face->num_locations;
for ( ; loc < limit; loc++ )
*loc = FT_GET_LONG();
}
FT_FRAME_EXIT();
}
else
{
face->num_locations = (FT_UShort)( table_len >> 1 );
FT_TRACE2(( "(16bit offsets): %12d ", face->num_locations ));
if ( FT_NEW_ARRAY( face->glyph_locations, face->num_locations ) )
goto Exit;
if ( FT_FRAME_ENTER( face->num_locations * 2L ) )
goto Exit;
{
FT_Long* loc = face->glyph_locations;
FT_Long* limit = loc + face->num_locations;
for ( ; loc < limit; loc++ )
*loc = (FT_Long)( (FT_ULong)FT_GET_USHORT() * 2 );
}
FT_FRAME_EXIT();
}
FT_TRACE2(( "loaded\n" ));
Exit:
return error;
}
/*************************************************************************/
/* */
/* <Function> */
/* TT_Load_CVT */
/* */
/* <Description> */
/* Loads the control value table into a face object. */
/* */
/* <InOut> */
/* face :: A handle to the target face object. */
/* */
/* <Input> */
/* stream :: A handle to the input stream. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
TT_Load_CVT( TT_Face face,
FT_Stream stream )
{
FT_Error error;
FT_Memory memory = stream->memory;
FT_ULong table_len;
FT_TRACE2(( "CVT " ));
error = face->goto_table( face, TTAG_cvt, stream, &table_len );
if ( error )
{
FT_TRACE2(( "is missing!\n" ));
face->cvt_size = 0;
face->cvt = NULL;
error = TT_Err_Ok;
goto Exit;
}
face->cvt_size = table_len / 2;
if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) )
goto Exit;
if ( FT_FRAME_ENTER( face->cvt_size * 2L ) )
goto Exit;
{
FT_Short* cur = face->cvt;
FT_Short* limit = cur + face->cvt_size;
for ( ; cur < limit; cur++ )
*cur = FT_GET_SHORT();
}
FT_FRAME_EXIT();
FT_TRACE2(( "loaded\n" ));
Exit:
return error;
}
/*************************************************************************/
/* */
/* <Function> */
/* TT_Load_Progams */
/* */
/* <Description> */
/* Loads the font program and the cvt program. */
/* */
/* <InOut> */
/* face :: A handle to the target face object. */
/* */
/* <Input> */
/* stream :: A handle to the input stream. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
TT_Load_Programs( TT_Face face,
FT_Stream stream )
{
FT_Error error;
FT_ULong table_len;
FT_TRACE2(( "Font program " ));
/* The font program is optional */
error = face->goto_table( face, TTAG_fpgm, stream, &table_len );
if ( error )
{
face->font_program = NULL;
face->font_program_size = 0;
FT_TRACE2(( "is missing!\n" ));
}
else
{
face->font_program_size = table_len;
if ( FT_FRAME_EXTRACT( table_len, face->font_program ) )
goto Exit;
FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size ));
}
FT_TRACE2(( "Prep program " ));
error = face->goto_table( face, TTAG_prep, stream, &table_len );
if ( error )
{
face->cvt_program = NULL;
face->cvt_program_size = 0;
error = TT_Err_Ok;
FT_TRACE2(( "is missing!\n" ));
}
else
{
face->cvt_program_size = table_len;
if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) )
goto Exit;
FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size ));
}
Exit:
return error;
}
/* END */

View File

@ -0,0 +1,48 @@
/***************************************************************************/
/* */
/* ttpload.h */
/* */
/* TrueType glyph data/program tables loader (specification). */
/* */
/* Copyright 1996-2001, 2002 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. */
/* */
/***************************************************************************/
#ifndef __TTPLOAD_H__
#define __TTPLOAD_H__
#include <ft2build.h>
#include FT_INTERNAL_TRUETYPE_TYPES_H
FT_BEGIN_HEADER
FT_LOCAL( FT_Error )
TT_Load_Locations( TT_Face face,
FT_Stream stream );
FT_LOCAL( FT_Error )
TT_Load_CVT( TT_Face face,
FT_Stream stream );
FT_LOCAL( FT_Error )
TT_Load_Programs( TT_Face face,
FT_Stream stream );
FT_END_HEADER
#endif /* __TTPLOAD_H__ */
/* END */

View File

@ -0,0 +1,23 @@
# FreeType 2 src/type1 Jamfile (c) 2001 David Turner
#
SubDir FT2_TOP src type1 ;
SubDirHdrs [ FT2_SubDir src type1 ] ;
{
local _sources ;
if $(FT2_MULTI)
{
_sources = t1afm t1driver t1objs t1load t1gload t1parse ;
}
else
{
_sources = type1 ;
}
Library $(FT2_LIB) : $(_sources).c ;
}
# end of src/type1 Jamfile

View File

@ -0,0 +1,23 @@
#
# FreeType 2 Type1 driver compilation rules for VMS
#
# Copyright 1996-2000, 2002 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.
CFLAGS=$(COMP_FLAGS)$(DEBUG)/include=([--.include],[--.src.type1])
OBJS=type1.obj
all : $(OBJS)
library [--.lib]freetype.olb $(OBJS)
# EOF

View File

@ -0,0 +1,22 @@
#
# FreeType 2 Type1 module definition
#
# Copyright 1996-2000 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.
make_module_list: add_type1_driver
add_type1_driver:
$(OPEN_DRIVER)t1_driver_class$(CLOSE_DRIVER)
$(ECHO_DRIVER)type1 $(ECHO_DRIVER_DESC)Postscript font files with extension *.pfa or *.pfb$(ECHO_DRIVER_DONE)
# EOF

View File

@ -0,0 +1,73 @@
#
# FreeType 2 Type1 driver configuration rules
#
# Copyright 1996-2000, 2001 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.
# Type1 driver directory
#
T1_DIR := $(SRC_)type1
T1_DIR_ := $(T1_DIR)$(SEP)
# compilation flags for the driver
#
T1_COMPILE := $(FT_COMPILE) $I$(T1_DIR)
# Type1 driver sources (i.e., C files)
#
T1_DRV_SRC := $(T1_DIR_)t1parse.c \
$(T1_DIR_)t1load.c \
$(T1_DIR_)t1driver.c \
$(T1_DIR_)t1afm.c \
$(T1_DIR_)t1gload.c \
$(T1_DIR_)t1objs.c
# Type1 driver headers
#
T1_DRV_H := $(T1_DRV_SRC:%.c=%.h) \
$(T1_DIR_)t1tokens.h \
$(T1_DIR_)t1errors.h
# Type1 driver object(s)
#
# T1_DRV_OBJ_M is used during `multi' builds
# T1_DRV_OBJ_S is used during `single' builds
#
T1_DRV_OBJ_M := $(T1_DRV_SRC:$(T1_DIR_)%.c=$(OBJ_)%.$O)
T1_DRV_OBJ_S := $(OBJ_)type1.$O
# Type1 driver source file for single build
#
T1_DRV_SRC_S := $(T1_DIR_)type1.c
# Type1 driver - single object
#
$(T1_DRV_OBJ_S): $(T1_DRV_SRC_S) $(T1_DRV_SRC) $(FREETYPE_H) $(T1_DRV_H)
$(T1_COMPILE) $T$@ $(T1_DRV_SRC_S)
# Type1 driver - multiple objects
#
$(OBJ_)%.$O: $(T1_DIR_)%.c $(FREETYPE_H) $(T1_DRV_H)
$(T1_COMPILE) $T$@ $<
# update main driver object lists
#
DRV_OBJS_S += $(T1_DRV_OBJ_S)
DRV_OBJS_M += $(T1_DRV_OBJ_M)
# EOF

View File

@ -0,0 +1,282 @@
/***************************************************************************/
/* */
/* t1afm.c */
/* */
/* AFM support for Type 1 fonts (body). */
/* */
/* Copyright 1996-2001, 2002 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 <ft2build.h>
#include "t1afm.h"
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_TYPE1_TYPES_H
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_t1afm
FT_LOCAL_DEF( void )
T1_Done_AFM( FT_Memory memory,
T1_AFM* afm )
{
FT_FREE( afm->kern_pairs );
afm->num_pairs = 0;
FT_FREE( afm );
}
#undef IS_KERN_PAIR
#define IS_KERN_PAIR( p ) ( p[0] == 'K' && p[1] == 'P' )
#define IS_ALPHANUM( c ) ( ft_isalnum( c ) || \
c == '_' || \
c == '.' )
/* read a glyph name and return the equivalent glyph index */
static FT_UInt
afm_atoindex( FT_Byte** start,
FT_Byte* limit,
T1_Font type1 )
{
FT_Byte* p = *start;
FT_Int len;
FT_UInt result = 0;
char temp[64];
/* skip whitespace */
while ( ( *p == ' ' || *p == '\t' || *p == ':' || *p == ';' ) &&
p < limit )
p++;
*start = p;
/* now, read glyph name */
while ( IS_ALPHANUM( *p ) && p < limit )
p++;
len = (FT_Int)( p - *start );
if ( len > 0 && len < 64 )
{
FT_Int n;
/* copy glyph name to intermediate array */
FT_MEM_COPY( temp, *start, len );
temp[len] = 0;
/* lookup glyph name in face array */
for ( n = 0; n < type1->num_glyphs; n++ )
{
char* gname = (char*)type1->glyph_names[n];
if ( gname && gname[0] == temp[0] && ft_strcmp( gname, temp ) == 0 )
{
result = n;
break;
}
}
}
*start = p;
return result;
}
/* read an integer */
static int
afm_atoi( FT_Byte** start,
FT_Byte* limit )
{
FT_Byte* p = *start;
int sum = 0;
int sign = 1;
/* skip everything that is not a number */
while ( p < limit && !isdigit( *p ) )
{
sign = 1;
if ( *p == '-' )
sign = -1;
p++;
}
while ( p < limit && isdigit( *p ) )
{
sum = sum * 10 + ( *p - '0' );
p++;
}
*start = p;
return sum * sign;
}
#undef KERN_INDEX
#define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 )
/* compare two kerning pairs */
FT_CALLBACK_DEF( int )
compare_kern_pairs( const void* a,
const void* b )
{
T1_Kern_Pair* pair1 = (T1_Kern_Pair*)a;
T1_Kern_Pair* pair2 = (T1_Kern_Pair*)b;
FT_ULong index1 = KERN_INDEX( pair1->glyph1, pair1->glyph2 );
FT_ULong index2 = KERN_INDEX( pair2->glyph1, pair2->glyph2 );
return ( index1 - index2 );
}
/* parse an AFM file -- for now, only read the kerning pairs */
FT_LOCAL_DEF( FT_Error )
T1_Read_AFM( FT_Face t1_face,
FT_Stream stream )
{
FT_Error error;
FT_Memory memory = stream->memory;
FT_Byte* start;
FT_Byte* limit;
FT_Byte* p;
FT_Int count = 0;
T1_Kern_Pair* pair;
T1_Font type1 = &((T1_Face)t1_face)->type1;
T1_AFM* afm = 0;
if ( FT_FRAME_ENTER( stream->size ) )
return error;
start = (FT_Byte*)stream->cursor;
limit = (FT_Byte*)stream->limit;
p = start;
/* we are now going to count the occurences of `KP' or `KPX' in */
/* the AFM file */
count = 0;
for ( p = start; p < limit - 3; p++ )
{
if ( IS_KERN_PAIR( p ) )
count++;
}
/* Actually, kerning pairs are simply optional! */
if ( count == 0 )
goto Exit;
/* allocate the pairs */
if ( FT_NEW( afm ) || FT_NEW_ARRAY( afm->kern_pairs, count ) )
goto Exit;
/* now, read each kern pair */
pair = afm->kern_pairs;
afm->num_pairs = count;
/* save in face object */
((T1_Face)t1_face)->afm_data = afm;
t1_face->face_flags |= FT_FACE_FLAG_KERNING;
for ( p = start; p < limit - 3; p++ )
{
if ( IS_KERN_PAIR( p ) )
{
FT_Byte* q;
/* skip keyword (KP or KPX) */
q = p + 2;
if ( *q == 'X' )
q++;
pair->glyph1 = afm_atoindex( &q, limit, type1 );
pair->glyph2 = afm_atoindex( &q, limit, type1 );
pair->kerning.x = afm_atoi( &q, limit );
pair->kerning.y = 0;
if ( p[2] != 'X' )
pair->kerning.y = afm_atoi( &q, limit );
pair++;
}
}
/* now, sort the kern pairs according to their glyph indices */
ft_qsort( afm->kern_pairs, count, sizeof ( T1_Kern_Pair ),
compare_kern_pairs );
Exit:
if ( error )
FT_FREE( afm );
FT_FRAME_EXIT();
return error;
}
/* find the kerning for a given glyph pair */
FT_LOCAL_DEF( void )
T1_Get_Kerning( T1_AFM* afm,
FT_UInt glyph1,
FT_UInt glyph2,
FT_Vector* kerning )
{
T1_Kern_Pair *min, *mid, *max;
FT_ULong idx = KERN_INDEX( glyph1, glyph2 );
/* simple binary search */
min = afm->kern_pairs;
max = min + afm->num_pairs - 1;
while ( min <= max )
{
FT_ULong midi;
mid = min + ( max - min ) / 2;
midi = KERN_INDEX( mid->glyph1, mid->glyph2 );
if ( midi == idx )
{
*kerning = mid->kerning;
return;
}
if ( midi < idx )
min = mid + 1;
else
max = mid - 1;
}
kerning->x = 0;
kerning->y = 0;
}
/* END */

View File

@ -0,0 +1,66 @@
/***************************************************************************/
/* */
/* t1afm.h */
/* */
/* AFM support for Type 1 fonts (specification). */
/* */
/* Copyright 1996-2001, 2002 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. */
/* */
/***************************************************************************/
#ifndef __T1AFM_H__
#define __T1AFM_H__
#include <ft2build.h>
#include "t1objs.h"
FT_BEGIN_HEADER
typedef struct T1_Kern_Pair_
{
FT_UInt glyph1;
FT_UInt glyph2;
FT_Vector kerning;
} T1_Kern_Pair;
typedef struct T1_AFM_
{
FT_Int num_pairs;
T1_Kern_Pair* kern_pairs;
} T1_AFM;
FT_LOCAL( FT_Error )
T1_Read_AFM( FT_Face face,
FT_Stream stream );
FT_LOCAL( void )
T1_Done_AFM( FT_Memory memory,
T1_AFM* afm );
FT_LOCAL( void )
T1_Get_Kerning( T1_AFM* afm,
FT_UInt glyph1,
FT_UInt glyph2,
FT_Vector* kerning );
FT_END_HEADER
#endif /* __T1AFM_H__ */
/* END */

View File

@ -0,0 +1,509 @@
/***************************************************************************/
/* */
/* t1driver.c */
/* */
/* Type 1 driver interface (body). */
/* */
/* Copyright 1996-2001, 2002 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 <ft2build.h>
#include "t1driver.h"
#include "t1gload.h"
#include "t1load.h"
#include "t1errors.h"
#ifndef T1_CONFIG_OPTION_NO_AFM
#include "t1afm.h"
#endif
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_POSTSCRIPT_NAMES_H
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_t1driver
static FT_Error
t1_get_glyph_name( T1_Face face,
FT_UInt glyph_index,
FT_Pointer buffer,
FT_UInt buffer_max )
{
FT_String* gname;
gname = face->type1.glyph_names[glyph_index];
if ( buffer_max > 0 )
{
FT_UInt len = (FT_UInt)( ft_strlen( gname ) );
if (len >= buffer_max)
len = buffer_max - 1;
FT_MEM_COPY( buffer, gname, len );
((FT_Byte*)buffer)[len] = 0;
}
return T1_Err_Ok;
}
/*************************************************************************/
/* */
/* <Function> */
/* t1_get_name_index */
/* */
/* <Description> */
/* Uses the Type 1 font's `glyph_names' table to find a given glyph */
/* name's glyph index. */
/* */
/* <Input> */
/* face :: A handle to the source face object. */
/* */
/* glyph_name :: The glyph name. */
/* */
/* <Return> */
/* Glyph index. 0 means `undefined character code'. */
/* */
static FT_UInt
t1_get_name_index( T1_Face face,
FT_String* glyph_name )
{
FT_Int i;
FT_String* gname;
for ( i = 0; i < face->type1.num_glyphs; i++ )
{
gname = face->type1.glyph_names[i];
if ( !ft_strcmp( glyph_name, gname ) )
return (FT_UInt)i;
}
return 0;
}
static const char*
t1_get_ps_name( T1_Face face )
{
return (const char*) face->type1.font_name;
}
/*************************************************************************/
/* */
/* <Function> */
/* Get_Interface */
/* */
/* <Description> */
/* Each driver can provide one or more extensions to the base */
/* FreeType API. These can be used to access format specific */
/* features (e.g., all TrueType/OpenType resources share a common */
/* file structure and common tables which can be accessed through the */
/* `sfnt' interface), or more simply generic ones (e.g., the */
/* `postscript names' interface which can be used to retrieve the */
/* PostScript name of a given glyph index). */
/* */
/* <InOut> */
/* driver :: A handle to a driver object. */
/* */
/* <Input> */
/* t1_interface :: A string designing the interface. Examples are */
/* `sfnt', `post_names', `charmaps', etc. */
/* */
/* <Return> */
/* A typeless pointer to the extension's interface (normally a table */
/* of function pointers). Returns NULL if the requested extension */
/* isn't available (i.e., wasn't compiled in the driver at build */
/* time). */
/* */
static FT_Module_Interface
Get_Interface( FT_Driver driver,
const FT_String* t1_interface )
{
FT_UNUSED( driver );
FT_UNUSED( t1_interface );
if ( ft_strcmp( (const char*)t1_interface, "glyph_name" ) == 0 )
return (FT_Module_Interface)t1_get_glyph_name;
if ( ft_strcmp( (const char*)t1_interface, "name_index" ) == 0 )
return (FT_Module_Interface)t1_get_name_index;
if ( ft_strcmp( (const char*)t1_interface, "postscript_name" ) == 0 )
return (FT_Module_Interface)t1_get_ps_name;
#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
if ( ft_strcmp( (const char*)t1_interface, "get_mm" ) == 0 )
return (FT_Module_Interface)T1_Get_Multi_Master;
if ( ft_strcmp( (const char*)t1_interface, "set_mm_design") == 0 )
return (FT_Module_Interface)T1_Set_MM_Design;
if ( ft_strcmp( (const char*)t1_interface, "set_mm_blend") == 0 )
return (FT_Module_Interface)T1_Set_MM_Blend;
#endif
return 0;
}
#ifndef T1_CONFIG_OPTION_NO_AFM
/*************************************************************************/
/* */
/* <Function> */
/* Get_Kerning */
/* */
/* <Description> */
/* A driver method used to return the kerning vector between two */
/* glyphs of the same face. */
/* */
/* <Input> */
/* face :: A handle to the source face object. */
/* */
/* left_glyph :: The index of the left glyph in the kern pair. */
/* */
/* right_glyph :: The index of the right glyph in the kern pair. */
/* */
/* <Output> */
/* kerning :: The kerning vector. This is in font units for */
/* scalable formats, and in pixels for fixed-sizes */
/* formats. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
/* <Note> */
/* Only horizontal layouts (left-to-right & right-to-left) are */
/* supported by this function. Other layouts, or more sophisticated */
/* kernings are out of scope of this method (the basic driver */
/* interface is meant to be simple). */
/* */
/* They can be implemented by format-specific interfaces. */
/* */
static FT_Error
Get_Kerning( T1_Face face,
FT_UInt left_glyph,
FT_UInt right_glyph,
FT_Vector* kerning )
{
T1_AFM* afm;
kerning->x = 0;
kerning->y = 0;
afm = (T1_AFM*)face->afm_data;
if ( afm )
T1_Get_Kerning( afm, left_glyph, right_glyph, kerning );
return T1_Err_Ok;
}
#endif /* T1_CONFIG_OPTION_NO_AFM */
/*************************************************************************/
/* */
/* <Function> */
/* Get_Char_Index */
/* */
/* <Description> */
/* Uses a charmap to return a given character code's glyph index. */
/* */
/* <Input> */
/* charmap :: A handle to the source charmap object. */
/* */
/* charcode :: The character code. */
/* */
/* <Return> */
/* Glyph index. 0 means `undefined character code'. */
/* */
static FT_UInt
Get_Char_Index( FT_CharMap charmap,
FT_Long charcode )
{
T1_Face face;
FT_UInt result = 0;
PSNames_Service psnames;
face = (T1_Face)charmap->face;
psnames = (PSNames_Service)face->psnames;
if ( psnames )
switch ( charmap->encoding )
{
/*******************************************************************/
/* */
/* Unicode encoding support */
/* */
case ft_encoding_unicode:
/* use the `PSNames' module to synthetize the Unicode charmap */
result = psnames->lookup_unicode( &face->unicode_map,
(FT_ULong)charcode );
/* the function returns 0xFFFF if the Unicode charcode has */
/* no corresponding glyph */
if ( result == 0xFFFFU )
result = 0;
goto Exit;
/*******************************************************************/
/* */
/* ISOLatin1 encoding support */
/* */
case ft_encoding_latin_1:
/* ISOLatin1 is the first page of Unicode */
if ( charcode < 256 && psnames->unicode_value )
{
result = psnames->lookup_unicode( &face->unicode_map,
(FT_ULong)charcode );
/* the function returns 0xFFFF if the Unicode charcode has */
/* no corresponding glyph */
if ( result == 0xFFFFU )
result = 0;
}
goto Exit;
/*******************************************************************/
/* */
/* Custom Type 1 encoding */
/* */
case ft_encoding_adobe_custom:
{
T1_Encoding encoding = &face->type1.encoding;
if ( charcode >= encoding->code_first &&
charcode <= encoding->code_last )
result = encoding->char_index[charcode];
goto Exit;
}
/*******************************************************************/
/* */
/* Adobe Standard & Expert encoding support */
/* */
default:
if ( charcode < 256 )
{
FT_UInt code;
FT_Int n;
const char* glyph_name;
code = psnames->adobe_std_encoding[charcode];
if ( charmap->encoding == ft_encoding_adobe_expert )
code = psnames->adobe_expert_encoding[charcode];
glyph_name = psnames->adobe_std_strings( code );
if ( !glyph_name )
break;
for ( n = 0; n < face->type1.num_glyphs; n++ )
{
const char* gname = face->type1.glyph_names[n];
if ( gname && gname[0] == glyph_name[0] &&
ft_strcmp( gname, glyph_name ) == 0 )
{
result = n;
break;
}
}
}
}
Exit:
return result;
}
/*************************************************************************/
/* */
/* <Function> */
/* Get_Next_Char */
/* */
/* <Description> */
/* Uses a charmap to return the next encoded char. */
/* */
/* <Input> */
/* charmap :: A handle to the source charmap object. */
/* */
/* charcode :: The character code. */
/* */
/* <Return> */
/* Next char code. 0 means `no more char codes'. */
/* */
static FT_Long
Get_Next_Char( FT_CharMap charmap,
FT_Long charcode )
{
T1_Face face;
PSNames_Service psnames;
face = (T1_Face)charmap->face;
psnames = (PSNames_Service)face->psnames;
if ( psnames )
switch ( charmap->encoding )
{
/*******************************************************************/
/* */
/* Unicode encoding support */
/* */
case ft_encoding_unicode:
/* use the `PSNames' module to synthetize the Unicode charmap */
return psnames->next_unicode( &face->unicode_map,
(FT_ULong)charcode );
/*******************************************************************/
/* */
/* ISOLatin1 encoding support */
/* */
case ft_encoding_latin_1:
{
FT_Long code;
/* use the `PSNames' module to synthetize the Unicode charmap */
code = psnames->next_unicode( &face->unicode_map,
(FT_ULong)charcode );
if ( code < 256 )
return code;
break;
}
/*******************************************************************/
/* */
/* Custom Type 1 encoding */
/* */
case ft_encoding_adobe_custom:
{
T1_Encoding encoding = &face->type1.encoding;
charcode++;
if ( charcode < encoding->code_first )
charcode = encoding->code_first;
while ( charcode <= encoding->code_last )
{
if ( encoding->char_index[charcode] )
return charcode;
charcode++;
}
}
/*******************************************************************/
/* */
/* Adobe Standard & Expert encoding support */
/* */
default:
while ( ++charcode < 256 )
{
FT_UInt code;
FT_Int n;
const char* glyph_name;
code = psnames->adobe_std_encoding[charcode];
if ( charmap->encoding == ft_encoding_adobe_expert )
code = psnames->adobe_expert_encoding[charcode];
glyph_name = psnames->adobe_std_strings( code );
if ( !glyph_name )
continue;
for ( n = 0; n < face->type1.num_glyphs; n++ )
{
const char* gname = face->type1.glyph_names[n];
if ( gname && gname[0] == glyph_name[0] &&
ft_strcmp( gname, glyph_name ) == 0 )
return charcode;
}
}
}
return 0;
}
FT_CALLBACK_TABLE_DEF
const FT_Driver_ClassRec t1_driver_class =
{
{
ft_module_font_driver |
ft_module_driver_scalable |
ft_module_driver_has_hinter,
sizeof( FT_DriverRec ),
"type1",
0x10000L,
0x20000L,
0, /* format interface */
(FT_Module_Constructor)T1_Driver_Init,
(FT_Module_Destructor) T1_Driver_Done,
(FT_Module_Requester) Get_Interface,
},
sizeof( T1_FaceRec ),
sizeof( T1_SizeRec ),
sizeof( T1_GlyphSlotRec ),
(FT_Face_InitFunc) T1_Face_Init,
(FT_Face_DoneFunc) T1_Face_Done,
(FT_Size_InitFunc) T1_Size_Init,
(FT_Size_DoneFunc) T1_Size_Done,
(FT_Slot_InitFunc) T1_GlyphSlot_Init,
(FT_Slot_DoneFunc) T1_GlyphSlot_Done,
(FT_Size_ResetPointsFunc) T1_Size_Reset,
(FT_Size_ResetPixelsFunc) T1_Size_Reset,
(FT_Slot_LoadFunc) T1_Load_Glyph,
(FT_CharMap_CharIndexFunc)Get_Char_Index,
#ifdef T1_CONFIG_OPTION_NO_AFM
(FT_Face_GetKerningFunc) 0,
(FT_Face_AttachFunc) 0,
#else
(FT_Face_GetKerningFunc) Get_Kerning,
(FT_Face_AttachFunc) T1_Read_AFM,
#endif
(FT_Face_GetAdvancesFunc) 0,
(FT_CharMap_CharNextFunc) Get_Next_Char
};
/* END */

View File

@ -0,0 +1,38 @@
/***************************************************************************/
/* */
/* t1driver.h */
/* */
/* High-level Type 1 driver interface (specification). */
/* */
/* Copyright 1996-2001, 2002 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. */
/* */
/***************************************************************************/
#ifndef __T1DRIVER_H__
#define __T1DRIVER_H__
#include <ft2build.h>
#include FT_INTERNAL_DRIVER_H
FT_BEGIN_HEADER
FT_EXPORT_VAR( const FT_Driver_ClassRec ) t1_driver_class;
FT_END_HEADER
#endif /* __T1DRIVER_H__ */
/* END */

View File

@ -0,0 +1,40 @@
/***************************************************************************/
/* */
/* t1errors.h */
/* */
/* Type 1 error codes (specification only). */
/* */
/* Copyright 2001 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. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* This file is used to define the Type 1 error enumeration constants. */
/* */
/*************************************************************************/
#ifndef __T1ERRORS_H__
#define __T1ERRORS_H__
#include FT_MODULE_ERRORS_H
#undef __FTERRORS_H__
#define FT_ERR_PREFIX T1_Err_
#define FT_ERR_BASE FT_Mod_Err_Type1
#include FT_ERRORS_H
#endif /* __T1ERRORS_H__ */
/* END */

View File

@ -0,0 +1,323 @@
/***************************************************************************/
/* */
/* t1gload.c */
/* */
/* Type 1 Glyph Loader (body). */
/* */
/* Copyright 1996-2001, 2002 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 <ft2build.h>
#include "t1gload.h"
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_OUTLINE_H
#include FT_INTERNAL_POSTSCRIPT_AUX_H
#include "t1errors.h"
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_t1gload
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/********** *********/
/********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
/********** *********/
/********** The following code is in charge of computing *********/
/********** the maximum advance width of the font. It *********/
/********** quickly processes each glyph charstring to *********/
/********** extract the value from either a `sbw' or `seac' *********/
/********** operator. *********/
/********** *********/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
FT_CALLBACK_DEF( FT_Error )
T1_Parse_Glyph( T1_Decoder decoder,
FT_UInt glyph_index )
{
T1_Face face = (T1_Face)decoder->builder.face;
T1_Font type1 = &face->type1;
decoder->font_matrix = type1->font_matrix;
decoder->font_offset = type1->font_offset;
return decoder->funcs.parse_charstrings(
decoder,
type1->charstrings [glyph_index],
type1->charstrings_len[glyph_index] );
}
FT_LOCAL_DEF( FT_Error )
T1_Compute_Max_Advance( T1_Face face,
FT_Int* max_advance )
{
FT_Error error;
T1_DecoderRec decoder;
FT_Int glyph_index;
T1_Font type1 = &face->type1;
PSAux_Service psaux = (PSAux_Service)face->psaux;
*max_advance = 0;
/* initialize load decoder */
error = psaux->t1_decoder_funcs->init( &decoder,
(FT_Face)face,
0, /* size */
0, /* glyph slot */
(FT_Byte**)type1->glyph_names,
face->blend,
0,
T1_Parse_Glyph );
if ( error )
return error;
decoder.builder.metrics_only = 1;
decoder.builder.load_points = 0;
decoder.num_subrs = type1->num_subrs;
decoder.subrs = type1->subrs;
decoder.subrs_len = type1->subrs_len;
*max_advance = 0;
/* for each glyph, parse the glyph charstring and extract */
/* the advance width */
for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
{
/* now get load the unscaled outline */
error = T1_Parse_Glyph( &decoder, glyph_index );
if ( glyph_index == 0 || decoder.builder.advance.x > *max_advance )
*max_advance = decoder.builder.advance.x;
/* ignore the error if one occured - skip to next glyph */
}
return T1_Err_Ok;
}
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/********** *********/
/********** UNHINTED GLYPH LOADER *********/
/********** *********/
/********** The following code is in charge of loading a *********/
/********** single outline. It completely ignores hinting *********/
/********** and is used when FT_LOAD_NO_HINTING is set. *********/
/********** *********/
/********** The Type 1 hinter is located in `t1hint.c' *********/
/********** *********/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
FT_LOCAL_DEF( FT_Error )
T1_Load_Glyph( T1_GlyphSlot glyph,
T1_Size size,
FT_UInt glyph_index,
FT_Int load_flags )
{
FT_Error error;
T1_DecoderRec decoder;
T1_Face face = (T1_Face)glyph->root.face;
FT_Bool hinting;
T1_Font type1 = &face->type1;
PSAux_Service psaux = (PSAux_Service)face->psaux;
const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs;
FT_Matrix font_matrix;
FT_Vector font_offset;
if ( load_flags & FT_LOAD_NO_RECURSE )
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
glyph->x_scale = size->root.metrics.x_scale;
glyph->y_scale = size->root.metrics.y_scale;
glyph->root.outline.n_points = 0;
glyph->root.outline.n_contours = 0;
hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
( load_flags & FT_LOAD_NO_HINTING ) == 0 );
glyph->root.format = ft_glyph_format_outline;
error = decoder_funcs->init( &decoder,
(FT_Face)face,
(FT_Size)size,
(FT_GlyphSlot)glyph,
(FT_Byte**)type1->glyph_names,
face->blend,
FT_BOOL( hinting ),
T1_Parse_Glyph );
if ( error )
goto Exit;
decoder.builder.no_recurse = FT_BOOL(
( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
decoder.num_subrs = type1->num_subrs;
decoder.subrs = type1->subrs;
decoder.subrs_len = type1->subrs_len;
/* now load the unscaled outline */
error = T1_Parse_Glyph( &decoder, glyph_index );
if ( error )
goto Exit;
font_matrix = decoder.font_matrix;
font_offset = decoder.font_offset;
/* save new glyph tables */
decoder_funcs->done( &decoder );
/* now, set the metrics -- this is rather simple, as */
/* the left side bearing is the xMin, and the top side */
/* bearing the yMax */
if ( !error )
{
glyph->root.outline.flags &= ft_outline_owner;
glyph->root.outline.flags |= ft_outline_reverse_fill;
/* for composite glyphs, return only left side bearing and */
/* advance width */
if ( load_flags & FT_LOAD_NO_RECURSE )
{
FT_Slot_Internal internal = glyph->root.internal;
glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
glyph->root.metrics.horiAdvance = decoder.builder.advance.x;
internal->glyph_matrix = font_matrix;
internal->glyph_delta = font_offset;
internal->glyph_transformed = 1;
}
else
{
FT_BBox cbox;
FT_Glyph_Metrics* metrics = &glyph->root.metrics;
/* copy the _unscaled_ advance width */
metrics->horiAdvance = decoder.builder.advance.x;
glyph->root.linearHoriAdvance = decoder.builder.advance.x;
glyph->root.internal->glyph_transformed = 0;
/* make up vertical metrics */
metrics->vertBearingX = 0;
metrics->vertBearingY = 0;
metrics->vertAdvance = 0;
glyph->root.linearVertAdvance = 0;
glyph->root.format = ft_glyph_format_outline;
if ( size && size->root.metrics.y_ppem < 24 )
glyph->root.outline.flags |= ft_outline_high_precision;
#if 1
/* apply the font matrix, if any */
FT_Outline_Transform( &glyph->root.outline, &font_matrix );
FT_Outline_Translate( &glyph->root.outline,
font_offset.x,
font_offset.y );
#endif
if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
{
/* scale the outline and the metrics */
FT_Int n;
FT_Outline* cur = decoder.builder.base;
FT_Vector* vec = cur->points;
FT_Fixed x_scale = glyph->x_scale;
FT_Fixed y_scale = glyph->y_scale;
/* First of all, scale the points, if we are not hinting */
if ( !hinting )
for ( n = cur->n_points; n > 0; n--, vec++ )
{
vec->x = FT_MulFix( vec->x, x_scale );
vec->y = FT_MulFix( vec->y, y_scale );
}
FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
/* Then scale the metrics */
metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
if ( hinting )
{
metrics->horiAdvance = ( metrics->horiAdvance + 32 ) & -64;
metrics->vertAdvance = ( metrics->vertAdvance + 32 ) & -64;
metrics->vertBearingX = ( metrics->vertBearingX + 32 ) & -64;
metrics->vertBearingY = ( metrics->vertBearingY + 32 ) & -64;
}
}
/* compute the other metrics */
FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
/* grid fit the bounding box if necessary */
if ( hinting )
{
cbox.xMin &= -64;
cbox.yMin &= -64;
cbox.xMax = ( cbox.xMax+63 ) & -64;
cbox.yMax = ( cbox.yMax+63 ) & -64;
}
metrics->width = cbox.xMax - cbox.xMin;
metrics->height = cbox.yMax - cbox.yMin;
metrics->horiBearingX = cbox.xMin;
metrics->horiBearingY = cbox.yMax;
}
/* Set control data to the glyph charstrings. Note that this is */
/* _not_ zero-terminated. */
glyph->root.control_data = type1->charstrings [glyph_index];
glyph->root.control_len = type1->charstrings_len[glyph_index];
}
Exit:
return error;
}
/* END */

View File

@ -0,0 +1,46 @@
/***************************************************************************/
/* */
/* t1gload.h */
/* */
/* Type 1 Glyph Loader (specification). */
/* */
/* Copyright 1996-2001, 2002 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. */
/* */
/***************************************************************************/
#ifndef __T1GLOAD_H__
#define __T1GLOAD_H__
#include <ft2build.h>
#include "t1objs.h"
FT_BEGIN_HEADER
FT_LOCAL( FT_Error )
T1_Compute_Max_Advance( T1_Face face,
FT_Int* max_advance );
FT_LOCAL( FT_Error )
T1_Load_Glyph( T1_GlyphSlot glyph,
T1_Size size,
FT_UInt glyph_index,
FT_Int load_flags );
FT_END_HEADER
#endif /* __T1GLOAD_H__ */
/* END */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
/***************************************************************************/
/* */
/* t1load.h */
/* */
/* Type 1 font loader (specification). */
/* */
/* Copyright 1996-2001, 2002 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. */
/* */
/***************************************************************************/
#ifndef __T1LOAD_H__
#define __T1LOAD_H__
#include <ft2build.h>
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_POSTSCRIPT_AUX_H
#include FT_MULTIPLE_MASTERS_H
#include "t1parse.h"
FT_BEGIN_HEADER
typedef struct T1_Loader_
{
T1_ParserRec parser; /* parser used to read the stream */
FT_Int num_chars; /* number of characters in encoding */
PS_TableRec encoding_table; /* PS_Table used to store the */
/* encoding character names */
FT_Int num_glyphs;
PS_TableRec glyph_names;
PS_TableRec charstrings;
PS_TableRec swap_table; /* For moving .notdef glyph to index 0. */
FT_Int num_subrs;
PS_TableRec subrs;
FT_Bool fontdata;
} T1_LoaderRec, *T1_Loader;
FT_LOCAL( FT_Error )
T1_Open_Face( T1_Face face );
#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
FT_LOCAL( FT_Error )
T1_Get_Multi_Master( T1_Face face,
FT_Multi_Master* master );
FT_LOCAL( FT_Error )
T1_Set_MM_Blend( T1_Face face,
FT_UInt num_coords,
FT_Fixed* coords );
FT_LOCAL( FT_Error )
T1_Set_MM_Design( T1_Face face,
FT_UInt num_coords,
FT_Long* coords );
FT_LOCAL( void )
T1_Done_Blend( T1_Face face );
#endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */
FT_END_HEADER
#endif /* __T1LOAD_H__ */
/* END */

View File

@ -0,0 +1,616 @@
/***************************************************************************/
/* */
/* t1objs.c */
/* */
/* Type 1 objects manager (body). */
/* */
/* Copyright 1996-2001, 2002 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 <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include "t1gload.h"
#include "t1load.h"
#include "t1errors.h"
#ifndef T1_CONFIG_OPTION_NO_AFM
#include "t1afm.h"
#endif
#include FT_INTERNAL_POSTSCRIPT_NAMES_H
#include FT_INTERNAL_POSTSCRIPT_AUX_H
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_t1objs
/*************************************************************************/
/* */
/* SIZE FUNCTIONS */
/* */
/* note that we store the global hints in the size's "internal" root */
/* field */
/* */
/*************************************************************************/
static PSH_Globals_Funcs
T1_Size_Get_Globals_Funcs( T1_Size size )
{
T1_Face face = (T1_Face)size->root.face;
PSHinter_Service pshinter = (PSHinter_Service)face->pshinter;
FT_Module module;
module = FT_Get_Module( size->root.face->driver->root.library,
"pshinter" );
return ( module && pshinter && pshinter->get_globals_funcs )
? pshinter->get_globals_funcs( module )
: 0 ;
}
FT_LOCAL_DEF( void )
T1_Size_Done( T1_Size size )
{
if ( size->root.internal )
{
PSH_Globals_Funcs funcs;
funcs = T1_Size_Get_Globals_Funcs( size );
if ( funcs )
funcs->destroy( (PSH_Globals)size->root.internal );
size->root.internal = 0;
}
}
FT_LOCAL_DEF( FT_Error )
T1_Size_Init( T1_Size size )
{
FT_Error error = 0;
PSH_Globals_Funcs funcs = T1_Size_Get_Globals_Funcs( size );
if ( funcs )
{
PSH_Globals globals;
T1_Face face = (T1_Face)size->root.face;
error = funcs->create( size->root.face->memory,
&face->type1.private_dict, &globals );
if ( !error )
size->root.internal = (FT_Size_Internal)(void*)globals;
}
return error;
}
FT_LOCAL_DEF( FT_Error )
T1_Size_Reset( T1_Size size )
{
PSH_Globals_Funcs funcs = T1_Size_Get_Globals_Funcs( size );
FT_Error error = 0;
if ( funcs )
error = funcs->set_scale( (PSH_Globals)size->root.internal,
size->root.metrics.x_scale,
size->root.metrics.y_scale,
0, 0 );
return error;
}
/*************************************************************************/
/* */
/* SLOT FUNCTIONS */
/* */
/*************************************************************************/
FT_LOCAL_DEF( void )
T1_GlyphSlot_Done( T1_GlyphSlot slot )
{
slot->root.internal->glyph_hints = 0;
}
FT_LOCAL_DEF( FT_Error )
T1_GlyphSlot_Init( T1_GlyphSlot slot )
{
T1_Face face;
PSHinter_Service pshinter;
face = (T1_Face)slot->root.face;
pshinter = (PSHinter_Service)face->pshinter;
if ( pshinter )
{
FT_Module module;
module = FT_Get_Module( slot->root.face->driver->root.library, "pshinter" );
if (module)
{
T1_Hints_Funcs funcs;
funcs = pshinter->get_t1_funcs( module );
slot->root.internal->glyph_hints = (void*)funcs;
}
}
return 0;
}
/*************************************************************************/
/* */
/* FACE FUNCTIONS */
/* */
/*************************************************************************/
/*************************************************************************/
/* */
/* <Function> */
/* T1_Face_Done */
/* */
/* <Description> */
/* The face object destructor. */
/* */
/* <Input> */
/* face :: A typeless pointer to the face object to destroy. */
/* */
FT_LOCAL_DEF( void )
T1_Face_Done( T1_Face face )
{
FT_Memory memory;
T1_Font type1 = &face->type1;
if ( face )
{
memory = face->root.memory;
#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
/* release multiple masters information */
T1_Done_Blend( face );
face->blend = 0;
#endif
/* release font info strings */
{
PS_FontInfo info = &type1->font_info;
FT_FREE( info->version );
FT_FREE( info->notice );
FT_FREE( info->full_name );
FT_FREE( info->family_name );
FT_FREE( info->weight );
}
/* release top dictionary */
FT_FREE( type1->charstrings_len );
FT_FREE( type1->charstrings );
FT_FREE( type1->glyph_names );
FT_FREE( type1->subrs );
FT_FREE( type1->subrs_len );
FT_FREE( type1->subrs_block );
FT_FREE( type1->charstrings_block );
FT_FREE( type1->glyph_names_block );
FT_FREE( type1->encoding.char_index );
FT_FREE( type1->encoding.char_name );
FT_FREE( type1->font_name );
#ifndef T1_CONFIG_OPTION_NO_AFM
/* release afm data if present */
if ( face->afm_data )
T1_Done_AFM( memory, (T1_AFM*)face->afm_data );
#endif
/* release unicode map, if any */
FT_FREE( face->unicode_map.maps );
face->unicode_map.num_maps = 0;
face->root.family_name = 0;
face->root.style_name = 0;
}
}
/*************************************************************************/
/* */
/* <Function> */
/* T1_Face_Init */
/* */
/* <Description> */
/* The face object constructor. */
/* */
/* <Input> */
/* stream :: input stream where to load font data. */
/* */
/* face_index :: The index of the font face in the resource. */
/* */
/* num_params :: Number of additional generic parameters. Ignored. */
/* */
/* params :: Additional generic parameters. Ignored. */
/* */
/* <InOut> */
/* face :: The face record to build. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
T1_Face_Init( FT_Stream stream,
T1_Face face,
FT_Int face_index,
FT_Int num_params,
FT_Parameter* params )
{
FT_Error error;
PSNames_Service psnames;
PSAux_Service psaux;
PSHinter_Service pshinter;
FT_UNUSED( num_params );
FT_UNUSED( params );
FT_UNUSED( face_index );
FT_UNUSED( stream );
face->root.num_faces = 1;
face->psnames = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
"psnames" );
psnames = (PSNames_Service)face->psnames;
face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
"psaux" );
psaux = (PSAux_Service)face->psaux;
face->pshinter = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
"pshinter" );
pshinter = (PSHinter_Service)face->pshinter;
/* open the tokenizer, this will also check the font format */
error = T1_Open_Face( face );
if ( error )
goto Exit;
/* if we just wanted to check the format, leave successfully now */
if ( face_index < 0 )
goto Exit;
/* check the face index */
if ( face_index != 0 )
{
FT_ERROR(( "T1_Face_Init: invalid face index\n" ));
error = T1_Err_Invalid_Argument;
goto Exit;
}
/* Now, load the font program into the face object */
/* Init the face object fields */
/* Now set up root face fields */
{
FT_Face root = (FT_Face)&face->root;
root->num_glyphs = face->type1.num_glyphs;
root->face_index = face_index;
root->face_flags = FT_FACE_FLAG_SCALABLE;
root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
if ( face->type1.font_info.is_fixed_pitch )
root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
if ( face->blend )
root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
/* XXX: TODO -- add kerning with .afm support */
/* get style name -- be careful, some broken fonts only */
/* have a `/FontName' dictionary entry! */
root->family_name = face->type1.font_info.family_name;
if ( root->family_name )
{
char* full = face->type1.font_info.full_name;
char* family = root->family_name;
if ( full )
{
while ( *family && *full == *family )
{
family++;
full++;
}
root->style_name = ( *full == ' ' ? full + 1
: (char *)"Regular" );
}
else
root->style_name = (char *)"Regular";
}
else
{
/* do we have a `/FontName'? */
if ( face->type1.font_name )
{
root->family_name = face->type1.font_name;
root->style_name = (char *)"Regular";
}
}
/* compute style flags */
root->style_flags = 0;
if ( face->type1.font_info.italic_angle )
root->style_flags |= FT_STYLE_FLAG_ITALIC;
if ( face->type1.font_info.weight )
{
if ( !ft_strcmp( face->type1.font_info.weight, "Bold" ) ||
!ft_strcmp( face->type1.font_info.weight, "Black" ) )
root->style_flags |= FT_STYLE_FLAG_BOLD;
}
/* no embedded bitmap support */
root->num_fixed_sizes = 0;
root->available_sizes = 0;
root->bbox.xMin = face->type1.font_bbox.xMin >> 16;
root->bbox.yMin = face->type1.font_bbox.yMin >> 16;
root->bbox.xMax = ( face->type1.font_bbox.xMax + 0xFFFFU ) >> 16;
root->bbox.yMax = ( face->type1.font_bbox.yMax + 0xFFFFU ) >> 16;
/* Set units_per_EM if we didn't set it in parse_font_matrix. */
if ( !root->units_per_EM )
root->units_per_EM = 1000;
root->ascender = (FT_Short)( root->bbox.yMax );
root->descender = (FT_Short)( root->bbox.yMin );
root->height = (FT_Short)(
( ( root->ascender - root->descender ) * 12 ) / 10 );
/* now compute the maximum advance width */
root->max_advance_width =
(FT_Short)( root->bbox.xMax );
{
FT_Int max_advance;
error = T1_Compute_Max_Advance( face, &max_advance );
/* in case of error, keep the standard width */
if ( !error )
root->max_advance_width = (FT_Short)max_advance;
else
error = 0; /* clear error */
}
root->max_advance_height = root->height;
root->underline_position = face->type1.font_info.underline_position;
root->underline_thickness = face->type1.font_info.underline_thickness;
root->internal->max_points = 0;
root->internal->max_contours = 0;
}
#ifdef FT_CONFIG_OPTION_USE_CMAPS
{
FT_Face root = &face->root;
if ( psnames && psaux )
{
FT_CharMapRec charmap;
T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes;
FT_CMap_Class clazz;
charmap.face = root;
/* first of all, try to synthetize a Unicode charmap */
charmap.platform_id = 3;
charmap.encoding_id = 1;
charmap.encoding = ft_encoding_unicode;
FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );
/* now, generate an Adobe Standard encoding when appropriate */
charmap.platform_id = 7;
clazz = NULL;
switch ( face->type1.encoding_type )
{
case T1_ENCODING_TYPE_STANDARD:
charmap.encoding = ft_encoding_adobe_standard;
charmap.encoding_id = 0;
clazz = cmap_classes->standard;
break;
case T1_ENCODING_TYPE_EXPERT:
charmap.encoding = ft_encoding_adobe_expert;
charmap.encoding_id = 1;
clazz = cmap_classes->expert;
break;
case T1_ENCODING_TYPE_ARRAY:
charmap.encoding = ft_encoding_adobe_custom;
charmap.encoding_id = 2;
clazz = cmap_classes->custom;
break;
case T1_ENCODING_TYPE_ISOLATIN1:
charmap.encoding = ft_encoding_latin_1;
charmap.encoding_id = 3;
clazz = cmap_classes->unicode;
break;
default:
;
}
if ( clazz )
FT_CMap_New( clazz, NULL, &charmap, NULL );
/* Select default charmap */
if (root->num_charmaps)
root->charmap = root->charmaps[0];
}
}
#else /* !FT_CONFIG_OPTION_USE_CMAPS */
/* charmap support -- synthetize unicode charmap if possible */
{
FT_Face root = &face->root;
FT_CharMap charmap = face->charmaprecs;
/* synthesize a Unicode charmap if there is support in the `PSNames' */
/* module */
if ( psnames )
{
if ( psnames->unicode_value )
{
error = psnames->build_unicodes(
root->memory,
face->type1.num_glyphs,
(const char**)face->type1.glyph_names,
&face->unicode_map );
if ( !error )
{
root->charmap = charmap;
charmap->face = (FT_Face)face;
charmap->encoding = ft_encoding_unicode;
charmap->platform_id = 3;
charmap->encoding_id = 1;
charmap++;
}
/* simply clear the error in case of failure (which really) */
/* means that out of memory or no unicode glyph names */
error = T1_Err_Ok;
}
}
/* now, support either the standard, expert, or custom encoding */
charmap->face = (FT_Face)face;
charmap->platform_id = 7; /* a new platform id for Adobe fonts? */
switch ( face->type1.encoding_type )
{
case T1_ENCODING_TYPE_STANDARD:
charmap->encoding = ft_encoding_adobe_standard;
charmap->encoding_id = 0;
break;
case T1_ENCODING_TYPE_EXPERT:
charmap->encoding = ft_encoding_adobe_expert;
charmap->encoding_id = 1;
break;
case T1_ENCODING_TYPE_ARRAY:
charmap->encoding = ft_encoding_adobe_custom;
charmap->encoding_id = 2;
break;
case T1_ENCODING_TYPE_ISOLATIN1:
charmap->encoding = ft_encoding_latin_1;
charmap->encoding_id = 3;
break;
default:
FT_ERROR(( "T1_Face_Init: invalid encoding\n" ));
error = T1_Err_Invalid_File_Format;
goto Exit;
}
root->charmaps = face->charmaps;
root->num_charmaps = charmap - face->charmaprecs + 1;
face->charmaps[0] = &face->charmaprecs[0];
face->charmaps[1] = &face->charmaprecs[1];
}
#endif /* !FT_CONFIG_OPTION_USE_CMAPS */
Exit:
return error;
}
/*************************************************************************/
/* */
/* <Function> */
/* T1_Driver_Init */
/* */
/* <Description> */
/* Initializes a given Type 1 driver object. */
/* */
/* <Input> */
/* driver :: A handle to the target driver object. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
T1_Driver_Init( T1_Driver driver )
{
FT_UNUSED( driver );
return T1_Err_Ok;
}
/*************************************************************************/
/* */
/* <Function> */
/* T1_Driver_Done */
/* */
/* <Description> */
/* Finalizes a given Type 1 driver. */
/* */
/* <Input> */
/* driver :: A handle to the target Type 1 driver. */
/* */
FT_LOCAL_DEF( void )
T1_Driver_Done( T1_Driver driver )
{
FT_UNUSED( driver );
}
/* END */

View File

@ -0,0 +1,170 @@
/***************************************************************************/
/* */
/* t1objs.h */
/* */
/* Type 1 objects manager (specification). */
/* */
/* Copyright 1996-2001, 2002 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. */
/* */
/***************************************************************************/
#ifndef __T1OBJS_H__
#define __T1OBJS_H__
#include <ft2build.h>
#include FT_INTERNAL_OBJECTS_H
#include FT_CONFIG_CONFIG_H
#include FT_INTERNAL_TYPE1_TYPES_H
FT_BEGIN_HEADER
/* The following structures must be defined by the hinter */
typedef struct T1_Size_Hints_ T1_Size_Hints;
typedef struct T1_Glyph_Hints_ T1_Glyph_Hints;
/*************************************************************************/
/* */
/* <Type> */
/* T1_Driver */
/* */
/* <Description> */
/* A handle to a Type 1 driver object. */
/* */
typedef struct T1_DriverRec_ *T1_Driver;
/*************************************************************************/
/* */
/* <Type> */
/* T1_Size */
/* */
/* <Description> */
/* A handle to a Type 1 size object. */
/* */
typedef struct T1_SizeRec_* T1_Size;
/*************************************************************************/
/* */
/* <Type> */
/* T1_GlyphSlot */
/* */
/* <Description> */
/* A handle to a Type 1 glyph slot object. */
/* */
typedef struct T1_GlyphSlotRec_* T1_GlyphSlot;
/*************************************************************************/
/* */
/* <Type> */
/* T1_CharMap */
/* */
/* <Description> */
/* A handle to a Type 1 character mapping object. */
/* */
/* <Note> */
/* The Type 1 format doesn't use a charmap but an encoding table. */
/* The driver is responsible for making up charmap objects */
/* corresponding to these tables. */
/* */
typedef struct T1_CharMapRec_* T1_CharMap;
/*************************************************************************/
/* */
/* HERE BEGINS THE TYPE1 SPECIFIC STUFF */
/* */
/*************************************************************************/
/*************************************************************************/
/* */
/* <Type> */
/* T1_SizeRec */
/* */
/* <Description> */
/* Type 1 size record. */
/* */
typedef struct T1_SizeRec_
{
FT_SizeRec root;
} T1_SizeRec;
FT_LOCAL( void )
T1_Size_Done( T1_Size size );
FT_LOCAL( FT_Error )
T1_Size_Reset( T1_Size size );
FT_LOCAL( FT_Error )
T1_Size_Init( T1_Size size );
/*************************************************************************/
/* */
/* <Type> */
/* T1_GlyphSlotRec */
/* */
/* <Description> */
/* Type 1 glyph slot record. */
/* */
typedef struct T1_GlyphSlotRec_
{
FT_GlyphSlotRec root;
FT_Bool hint;
FT_Bool scaled;
FT_Int max_points;
FT_Int max_contours;
FT_Fixed x_scale;
FT_Fixed y_scale;
} T1_GlyphSlotRec;
FT_LOCAL( FT_Error )
T1_Face_Init( FT_Stream stream,
T1_Face face,
FT_Int face_index,
FT_Int num_params,
FT_Parameter* params );
FT_LOCAL( void )
T1_Face_Done( T1_Face face );
FT_LOCAL( FT_Error )
T1_GlyphSlot_Init( T1_GlyphSlot slot );
FT_LOCAL( void )
T1_GlyphSlot_Done( T1_GlyphSlot slot );
FT_LOCAL( FT_Error )
T1_Driver_Init( T1_Driver driver );
FT_LOCAL( void )
T1_Driver_Done( T1_Driver driver );
FT_END_HEADER
#endif /* __T1OBJS_H__ */
/* END */

View File

@ -0,0 +1,460 @@
/***************************************************************************/
/* */
/* t1parse.c */
/* */
/* Type 1 parser (body). */
/* */
/* Copyright 1996-2001, 2002 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. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* The Type 1 parser is in charge of the following: */
/* */
/* - provide an implementation of a growing sequence of objects called */
/* a `T1_Table' (used to build various tables needed by the loader). */
/* */
/* - opening .pfb and .pfa files to extract their top-level and private */
/* dictionaries. */
/* */
/* - read numbers, arrays & strings from any dictionary. */
/* */
/* See `t1load.c' to see how data is loaded from the font file. */
/* */
/*************************************************************************/
#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_CALC_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_POSTSCRIPT_AUX_H
#include "t1parse.h"
#include "t1errors.h"
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_t1parse
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** INPUT STREAM PARSER *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
#define IS_T1_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' )
#define IS_T1_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' )
#define IS_T1_SPACE( c ) ( IS_T1_WHITESPACE( c ) || IS_T1_LINESPACE( c ) )
typedef struct PFB_Tag_
{
FT_UShort tag;
FT_Long size;
} PFB_Tag;
#undef FT_STRUCTURE
#define FT_STRUCTURE PFB_Tag
static
const FT_Frame_Field pfb_tag_fields[] =
{
FT_FRAME_START( 6 ),
FT_FRAME_USHORT ( tag ),
FT_FRAME_LONG_LE( size ),
FT_FRAME_END
};
static FT_Error
read_pfb_tag( FT_Stream stream,
FT_UShort* tag,
FT_Long* size )
{
FT_Error error;
PFB_Tag head;
*tag = 0;
*size = 0;
if ( !FT_STREAM_READ_FIELDS( pfb_tag_fields, &head ) )
{
if ( head.tag == 0x8001U || head.tag == 0x8002U )
{
*tag = head.tag;
*size = head.size;
}
}
return error;
}
FT_LOCAL_DEF( FT_Error )
T1_New_Parser( T1_Parser parser,
FT_Stream stream,
FT_Memory memory,
PSAux_Service psaux )
{
FT_Error error;
FT_UShort tag;
FT_Long size;
psaux->ps_parser_funcs->init( &parser->root,0, 0, memory );
parser->stream = stream;
parser->base_len = 0;
parser->base_dict = 0;
parser->private_len = 0;
parser->private_dict = 0;
parser->in_pfb = 0;
parser->in_memory = 0;
parser->single_block = 0;
/******************************************************************/
/* */
/* Here a short summary of what is going on: */
/* */
/* When creating a new Type 1 parser, we try to locate and load */
/* the base dictionary if this is possible (i.e. for PFB */
/* files). Otherwise, we load the whole font into memory. */
/* */
/* When `loading' the base dictionary, we only setup pointers */
/* in the case of a memory-based stream. Otherwise, we */
/* allocate and load the base dictionary in it. */
/* */
/* parser->in_pfb is set if we are in a binary (".pfb") font. */
/* parser->in_memory is set if we have a memory stream. */
/* */
/* try to compute the size of the base dictionary; */
/* look for a Postscript binary file tag, i.e 0x8001 */
if ( FT_STREAM_SEEK( 0L ) )
goto Exit;
error = read_pfb_tag( stream, &tag, &size );
if ( error )
goto Exit;
if ( tag != 0x8001U )
{
/* assume that this is a PFA file for now; an error will */
/* be produced later when more things are checked */
if ( FT_STREAM_SEEK( 0L ) )
goto Exit;
size = stream->size;
}
else
parser->in_pfb = 1;
/* now, try to load `size' bytes of the `base' dictionary we */
/* found previously */
/* if it is a memory-based resource, set up pointers */
if ( !stream->read )
{
parser->base_dict = (FT_Byte*)stream->base + stream->pos;
parser->base_len = size;
parser->in_memory = 1;
/* check that the `size' field is valid */
if ( FT_STREAM_SKIP( size ) )
goto Exit;
}
else
{
/* read segment in memory */
if ( FT_ALLOC( parser->base_dict, size ) ||
FT_STREAM_READ( parser->base_dict, size ) )
goto Exit;
parser->base_len = size;
}
/* Now check font format; we must see `%!PS-AdobeFont-1' */
/* or `%!FontType' */
{
if ( size <= 16 ||
( ft_strncmp( (const char*)parser->base_dict,
"%!PS-AdobeFont-1", 16 ) &&
ft_strncmp( (const char*)parser->base_dict,
"%!FontType", 10 ) ) )
{
FT_TRACE2(( "[not a Type1 font]\n" ));
error = T1_Err_Unknown_File_Format;
}
else
{
parser->root.base = parser->base_dict;
parser->root.cursor = parser->base_dict;
parser->root.limit = parser->root.cursor + parser->base_len;
}
}
Exit:
if ( error && !parser->in_memory )
FT_FREE( parser->base_dict );
return error;
}
FT_LOCAL_DEF( void )
T1_Finalize_Parser( T1_Parser parser )
{
FT_Memory memory = parser->root.memory;
/* always free the private dictionary */
FT_FREE( parser->private_dict );
/* free the base dictionary only when we have a disk stream */
if ( !parser->in_memory )
FT_FREE( parser->base_dict );
parser->root.funcs.done( &parser->root );
}
/* return the value of an hexadecimal digit */
static int
hexa_value( char c )
{
unsigned int d;
d = (unsigned int)( c - '0' );
if ( d <= 9 )
return (int)d;
d = (unsigned int)( c - 'a' );
if ( d <= 5 )
return (int)( d + 10 );
d = (unsigned int)( c - 'A' );
if ( d <= 5 )
return (int)( d + 10 );
return -1;
}
FT_LOCAL_DEF( FT_Error )
T1_Get_Private_Dict( T1_Parser parser,
PSAux_Service psaux )
{
FT_Stream stream = parser->stream;
FT_Memory memory = parser->root.memory;
FT_Error error = 0;
FT_Long size;
if ( parser->in_pfb )
{
/* in the case of the PFB format, the private dictionary can be */
/* made of several segments. We thus first read the number of */
/* segments to compute the total size of the private dictionary */
/* then re-read them into memory. */
FT_Long start_pos = FT_STREAM_POS();
FT_UShort tag;
parser->private_len = 0;
for (;;)
{
error = read_pfb_tag( stream, &tag, &size );
if ( error )
goto Fail;
if ( tag != 0x8002U )
break;
parser->private_len += size;
if ( FT_STREAM_SKIP( size ) )
goto Fail;
}
/* Check that we have a private dictionary there */
/* and allocate private dictionary buffer */
if ( parser->private_len == 0 )
{
FT_ERROR(( "T1_Get_Private_Dict:" ));
FT_ERROR(( " invalid private dictionary section\n" ));
error = T1_Err_Invalid_File_Format;
goto Fail;
}
if ( FT_STREAM_SEEK( start_pos ) ||
FT_ALLOC( parser->private_dict, parser->private_len ) )
goto Fail;
parser->private_len = 0;
for (;;)
{
error = read_pfb_tag( stream, &tag, &size );
if ( error || tag != 0x8002U )
{
error = T1_Err_Ok;
break;
}
if ( FT_STREAM_READ( parser->private_dict + parser->private_len, size ) )
goto Fail;
parser->private_len += size;
}
}
else
{
/* we have already `loaded' the whole PFA font file into memory; */
/* if this is a memory resource, allocate a new block to hold */
/* the private dict. Otherwise, simply overwrite into the base */
/* dictionary block in the heap. */
/* first of all, look at the `eexec' keyword */
FT_Byte* cur = parser->base_dict;
FT_Byte* limit = cur + parser->base_len;
FT_Byte c;
for (;;)
{
c = cur[0];
if ( c == 'e' && cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */
/* newline + 4 chars */
{
if ( cur[1] == 'e' && cur[2] == 'x' &&
cur[3] == 'e' && cur[4] == 'c' )
{
cur += 6; /* we skip the newling after the `eexec' */
/* XXX: Some fonts use DOS-linefeeds, i.e. \r\n; we need to */
/* skip the extra \n if we find it */
if ( cur[0] == '\n' )
cur++;
break;
}
}
cur++;
if ( cur >= limit )
{
FT_ERROR(( "T1_Get_Private_Dict:" ));
FT_ERROR(( " could not find `eexec' keyword\n" ));
error = T1_Err_Invalid_File_Format;
goto Exit;
}
}
/* now determine where to write the _encrypted_ binary private */
/* dictionary. We overwrite the base dictionary for disk-based */
/* resources and allocate a new block otherwise */
size = (FT_Long)( parser->base_len - ( cur - parser->base_dict ) );
if ( parser->in_memory )
{
/* note that we allocate one more byte to put a terminating `0' */
if ( FT_ALLOC( parser->private_dict, size + 1 ) )
goto Fail;
parser->private_len = size;
}
else
{
parser->single_block = 1;
parser->private_dict = parser->base_dict;
parser->private_len = size;
parser->base_dict = 0;
parser->base_len = 0;
}
/* now determine whether the private dictionary is encoded in binary */
/* or hexadecimal ASCII format -- decode it accordingly */
/* we need to access the next 4 bytes (after the final \r following */
/* the `eexec' keyword); if they all are hexadecimal digits, then */
/* we have a case of ASCII storage */
if ( ( hexa_value( cur[0] ) | hexa_value( cur[1] ) |
hexa_value( cur[2] ) | hexa_value( cur[3] ) ) < 0 )
/* binary encoding -- `simply' copy the private dict */
FT_MEM_COPY( parser->private_dict, cur, size );
else
{
/* ASCII hexadecimal encoding */
FT_Byte* write;
FT_Int count;
write = parser->private_dict;
count = 0;
for ( ;cur < limit; cur++ )
{
int hex1;
/* check for newline */
if ( cur[0] == '\r' || cur[0] == '\n' )
continue;
/* exit if we have a non-hexadecimal digit that isn't a newline */
hex1 = hexa_value( cur[0] );
if ( hex1 < 0 || cur + 1 >= limit )
break;
/* otherwise, store byte */
*write++ = (FT_Byte)( ( hex1 << 4 ) | hexa_value( cur[1] ) );
count++;
cur++;
}
/* put a safeguard */
parser->private_len = (FT_Int)( write - parser->private_dict );
*write++ = 0;
}
}
/* we now decrypt the encoded binary private dictionary */
psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U );
parser->root.base = parser->private_dict;
parser->root.cursor = parser->private_dict;
parser->root.limit = parser->root.cursor + parser->private_len;
Fail:
Exit:
return error;
}
/* END */

View File

@ -0,0 +1,135 @@
/***************************************************************************/
/* */
/* t1parse.h */
/* */
/* Type 1 parser (specification). */
/* */
/* Copyright 1996-2001, 2002 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. */
/* */
/***************************************************************************/
#ifndef __T1PARSE_H__
#define __T1PARSE_H__
#include <ft2build.h>
#include FT_INTERNAL_TYPE1_TYPES_H
#include FT_INTERNAL_STREAM_H
FT_BEGIN_HEADER
/*************************************************************************/
/* */
/* <Struct> */
/* T1_ParserRec */
/* */
/* <Description> */
/* A PS_ParserRec is an object used to parse a Type 1 fonts very */
/* quickly. */
/* */
/* <Fields> */
/* root :: The root parser. */
/* */
/* stream :: The current input stream. */
/* */
/* base_dict :: A pointer to the top-level dictionary. */
/* */
/* base_len :: The length in bytes of the top dictionary. */
/* */
/* private_dict :: A pointer to the private dictionary. */
/* */
/* private_len :: The length in bytes of the private dictionary. */
/* */
/* in_pfb :: A boolean. Indicates that we are handling a PFB */
/* file. */
/* */
/* in_memory :: A boolean. Indicates a memory-based stream. */
/* */
/* single_block :: A boolean. Indicates that the private dictionary */
/* is stored in lieu of the base dictionary. */
/* */
typedef struct T1_ParserRec_
{
PS_ParserRec root;
FT_Stream stream;
FT_Byte* base_dict;
FT_Int base_len;
FT_Byte* private_dict;
FT_Int private_len;
FT_Byte in_pfb;
FT_Byte in_memory;
FT_Byte single_block;
} T1_ParserRec, *T1_Parser;
#define T1_Add_Table( p, i, o, l ) (p)->funcs.add( (p), i, o, l )
#define T1_Done_Table( p ) \
do \
{ \
if ( (p)->funcs.done ) \
(p)->funcs.done( p ); \
} while ( 0 )
#define T1_Release_Table( p ) \
do \
{ \
if ( (p)->funcs.release ) \
(p)->funcs.release( p ); \
} while ( 0 )
#define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root )
#define T1_Skip_Alpha( p ) (p)->root.funcs.skip_alpha ( &(p)->root )
#define T1_ToInt( p ) (p)->root.funcs.to_int( &(p)->root )
#define T1_ToFixed( p, t ) (p)->root.funcs.to_fixed( &(p)->root, t )
#define T1_ToCoordArray( p, m, c ) \
(p)->root.funcs.to_coord_array( &(p)->root, m, c )
#define T1_ToFixedArray( p, m, f, t ) \
(p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
#define T1_ToToken( p, t ) \
(p)->root.funcs.to_token( &(p)->root, t )
#define T1_ToTokenArray( p, t, m, c ) \
(p)->root.funcs.to_token_array( &(p)->root, t, m, c )
#define T1_Load_Field( p, f, o, m, pf ) \
(p)->root.funcs.load_field( &(p)->root, f, o, m, pf )
#define T1_Load_Field_Table( p, f, o, m, pf ) \
(p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )
FT_LOCAL( FT_Error )
T1_New_Parser( T1_Parser parser,
FT_Stream stream,
FT_Memory memory,
PSAux_Service psaux );
FT_LOCAL( FT_Error )
T1_Get_Private_Dict( T1_Parser parser,
PSAux_Service psaux );
FT_LOCAL( void )
T1_Finalize_Parser( T1_Parser parser );
FT_END_HEADER
#endif /* __T1PARSE_H__ */
/* END */

View File

@ -0,0 +1,73 @@
/***************************************************************************/
/* */
/* t1tokens.h */
/* */
/* Type 1 tokenizer (specification). */
/* */
/* Copyright 1996-2001, 2002 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. */
/* */
/***************************************************************************/
#undef FT_STRUCTURE
#define FT_STRUCTURE PS_FontInfoRec
#undef T1CODE
#define T1CODE T1_FIELD_LOCATION_FONT_INFO
T1_FIELD_STRING ( "version", version )
T1_FIELD_STRING ( "Notice", notice )
T1_FIELD_STRING ( "FullName", full_name )
T1_FIELD_STRING ( "FamilyName", family_name )
T1_FIELD_STRING ( "Weight", weight )
T1_FIELD_NUM ( "ItalicAngle", italic_angle )
T1_FIELD_TYPE_BOOL( "isFixedPitch", is_fixed_pitch )
T1_FIELD_NUM ( "UnderlinePosition", underline_position )
T1_FIELD_NUM ( "UnderlineThickness", underline_thickness )
#undef FT_STRUCTURE
#define FT_STRUCTURE PS_PrivateRec
#undef T1CODE
#define T1CODE T1_FIELD_LOCATION_PRIVATE
T1_FIELD_NUM ( "UniqueID", unique_id )
T1_FIELD_NUM ( "lenIV", lenIV )
T1_FIELD_NUM ( "LanguageGroup", language_group )
T1_FIELD_NUM ( "password", password )
T1_FIELD_FIXED ( "BlueScale", blue_scale )
T1_FIELD_NUM ( "BlueShift", blue_shift )
T1_FIELD_NUM ( "BlueFuzz", blue_fuzz )
T1_FIELD_NUM_TABLE ( "BlueValues", blue_values, 14 )
T1_FIELD_NUM_TABLE ( "OtherBlues", other_blues, 10 )
T1_FIELD_NUM_TABLE ( "FamilyBlues", family_blues, 14 )
T1_FIELD_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10 )
T1_FIELD_NUM_TABLE2( "StdHW", standard_width, 1 )
T1_FIELD_NUM_TABLE2( "StdVW", standard_height, 1 )
T1_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2 )
T1_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12 )
T1_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12 )
#undef FT_STRUCTURE
#define FT_STRUCTURE T1_FontRec
#undef T1CODE
#define T1CODE T1_FIELD_LOCATION_FONT_DICT
T1_FIELD_NUM( "PaintType", paint_type )
T1_FIELD_NUM( "FontType", font_type )
T1_FIELD_NUM( "StrokeWidth", stroke_width )
/* END */

View File

@ -0,0 +1,33 @@
/***************************************************************************/
/* */
/* type1.c */
/* */
/* FreeType Type 1 driver component (body only). */
/* */
/* Copyright 1996-2001 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. */
/* */
/***************************************************************************/
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include <ft2build.h>
#include "t1parse.c"
#include "t1load.c"
#include "t1objs.c"
#include "t1driver.c"
#include "t1gload.c"
#ifndef T1_CONFIG_OPTION_NO_AFM
#include "t1afm.c"
#endif
/* END */

View File

@ -0,0 +1,23 @@
# FreeType 2 src/type42 Jamfile (c) 2002 David Turner
#
SubDir FT2_TOP src type42 ;
SubDirHdrs [ FT2_SubDir src type42 ] ;
{
local _sources ;
if $(FT2_MULTI)
{
_sources = t42objs t42parse t42drivr ;
}
else
{
_sources = type42 ;
}
Library $(FT2_LIB) : $(_sources).c ;
}
# end of src/type42 Jamfile

View File

@ -0,0 +1,23 @@
#
# FreeType 2 Type 42 driver compilation rules for VMS
#
# Copyright 2002 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.
CFLAGS=$(COMP_FLAGS)$(DEBUG)/include=([--.include],[--.src.type42])
OBJS=type42.obj
all : $(OBJS)
library [--.lib]freetype.olb $(OBJS)
# EOF

View File

@ -0,0 +1,22 @@
#
# FreeType 2 Type42 module definition
#
# Copyright 2002 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.
make_module_list: add_type42_driver
add_type42_driver:
$(OPEN_DRIVER)t42_driver_class$(CLOSE_DRIVER)
$(ECHO_DRIVER)type42 $(ECHO_DRIVER_DESC)Type 42 font files with no known extension$(ECHO_DRIVER_DONE)
# EOF

View File

@ -0,0 +1,69 @@
#
# FreeType 2 Type42 driver configuration rules
#
# Copyright 2002 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.
# Type42 driver directory
#
T42_DIR := $(SRC_)type42
T42_DIR_ := $(T42_DIR)$(SEP)
# compilation flags for the driver
#
T42_COMPILE := $(FT_COMPILE) $I$(T42_DIR)
# Type42 driver source
#
T42_DRV_SRC := $(T42_DIR_)t42objs.c \
$(T42_DIR_)t42parse.c \
$(T42_DIR_)t42drivr.c
# Type42 driver headers
#
T42_DRV_H := $(T42_DRV_SRC:%.c=%.h) \
$(T42_DIR_)t42error.h
# Type42 driver object(s)
#
# T42_DRV_OBJ_M is used during `multi' builds
# T42_DRV_OBJ_S is used during `single' builds
#
T42_DRV_OBJ_M := $(T42_DRV_SRC:$(T42_DIR_)%.c=$(OBJ_)%.$O)
T42_DRV_OBJ_S := $(OBJ_)type42.$O
# Type42 driver source file for single build
#
T42_DRV_SRC_S := $(T42_DIR_)type42.c
# Type42 driver - single object
#
$(T42_DRV_OBJ_S): $(T42_DRV_SRC_S) $(T42_DRV_SRC) $(FREETYPE_H) $(T42_DRV_H)
$(T42_COMPILE) $T$@ $(T42_DRV_SRC_S)
# Type42 driver - multiple objects
#
$(OBJ_)%.$O: $(T42_DIR_)%.c $(FREETYPE_H) $(T42_DRV_H)
$(T42_COMPILE) $T$@ $<
# update main driver object lists
#
DRV_OBJS_S += $(T42_DRV_OBJ_S)
DRV_OBJS_M += $(T42_DRV_OBJ_M)
# EOF

View File

@ -0,0 +1,172 @@
/***************************************************************************/
/* */
/* t42drivr.c */
/* */
/* High-level Type 42 driver interface (body). */
/* */
/* Copyright 2002 by Roberto Alameda. */
/* */
/* 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. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* This driver implements Type42 fonts as described in the */
/* Technical Note #5012 from Adobe, with these limitations: */
/* */
/* 1) CID Fonts are not currently supported. */
/* 2) Incremental fonts making use of the GlyphDirectory keyword */
/* will be loaded, but the rendering will be using the TrueType */
/* tables. */
/* 3) The sfnts array is expected to be ASCII, not binary. */
/* 4) As for Type1 fonts, CDevProc is not supported. */
/* 5) The Metrics dictionary is not supported. */
/* 6) AFM metrics are not supported. */
/* */
/* In other words, this driver supports Type42 fonts derived from */
/* TrueType fonts in a non-CID manner, as done by usual conversion */
/* programs. */
/* */
/*************************************************************************/
#include "t42drivr.h"
#include "t42objs.h"
#include "t42error.h"
#include FT_INTERNAL_DEBUG_H
#undef FT_COMPONENT
#define FT_COMPONENT trace_t42
static FT_Error
t42_get_glyph_name( T42_Face face,
FT_UInt glyph_index,
FT_Pointer buffer,
FT_UInt buffer_max )
{
FT_String* gname;
gname = face->type1.glyph_names[glyph_index];
if ( buffer_max > 0 )
{
FT_UInt len = (FT_UInt)( ft_strlen( gname ) );
if ( len >= buffer_max )
len = buffer_max - 1;
FT_MEM_COPY( buffer, gname, len );
((FT_Byte*)buffer)[len] = 0;
}
return T42_Err_Ok;
}
static const char*
t42_get_ps_name( T42_Face face )
{
return (const char*)face->type1.font_name;
}
static FT_UInt
t42_get_name_index( T42_Face face,
FT_String* glyph_name )
{
FT_Int i;
FT_String* gname;
for ( i = 0; i < face->type1.num_glyphs; i++ )
{
gname = face->type1.glyph_names[i];
if ( !ft_strcmp( glyph_name, gname ) )
return ft_atoi( (const char *)face->type1.charstrings[i] );
}
return 0;
}
static FT_Module_Interface
T42_Get_Interface( FT_Driver driver,
const FT_String* t42_interface )
{
FT_UNUSED( driver );
/* Any additional interface are defined here */
if (ft_strcmp( (const char*)t42_interface, "glyph_name" ) == 0 )
return (FT_Module_Interface)t42_get_glyph_name;
if ( ft_strcmp( (const char*)t42_interface, "name_index" ) == 0 )
return (FT_Module_Interface)t42_get_name_index;
if ( ft_strcmp( (const char*)t42_interface, "postscript_name" ) == 0 )
return (FT_Module_Interface)t42_get_ps_name;
return 0;
}
const FT_Driver_ClassRec t42_driver_class =
{
{
ft_module_font_driver |
ft_module_driver_scalable |
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
ft_module_driver_has_hinter,
#else
0,
#endif
sizeof ( T42_DriverRec ),
"type42",
0x10000L,
0x20000L,
0, /* format interface */
(FT_Module_Constructor)T42_Driver_Init,
(FT_Module_Destructor) T42_Driver_Done,
(FT_Module_Requester) T42_Get_Interface,
},
sizeof ( T42_FaceRec ),
sizeof ( T42_SizeRec ),
sizeof ( T42_GlyphSlotRec ),
(FT_Face_InitFunc) T42_Face_Init,
(FT_Face_DoneFunc) T42_Face_Done,
(FT_Size_InitFunc) T42_Size_Init,
(FT_Size_DoneFunc) T42_Size_Done,
(FT_Slot_InitFunc) T42_GlyphSlot_Init,
(FT_Slot_DoneFunc) T42_GlyphSlot_Done,
(FT_Size_ResetPointsFunc) T42_Size_SetChars,
(FT_Size_ResetPixelsFunc) T42_Size_SetPixels,
(FT_Slot_LoadFunc) T42_GlyphSlot_Load,
(FT_CharMap_CharIndexFunc)T42_CMap_CharIndex,
(FT_Face_GetKerningFunc) 0,
(FT_Face_AttachFunc) 0,
(FT_Face_GetAdvancesFunc) 0,
(FT_CharMap_CharNextFunc) T42_CMap_CharNext,
};
/* END */

View File

@ -0,0 +1,38 @@
/***************************************************************************/
/* */
/* t42drivr.h */
/* */
/* High-level Type 42 driver interface (specification). */
/* */
/* Copyright 2002 by Roberto Alameda. */
/* */
/* 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. */
/* */
/***************************************************************************/
#ifndef __T42DRIVR_H__
#define __T42DRIVR_H__
#include <ft2build.h>
#include FT_INTERNAL_DRIVER_H
FT_BEGIN_HEADER
FT_EXPORT_VAR( const FT_Driver_ClassRec ) t42_driver_class;
FT_END_HEADER
#endif /* __T42DRIVR_H__ */
/* END */

View File

@ -0,0 +1,40 @@
/***************************************************************************/
/* */
/* t42error.h */
/* */
/* Type 42 error codes (specification only). */
/* */
/* Copyright 2002 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. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* This file is used to define the Type 42 error enumeration constants. */
/* */
/*************************************************************************/
#ifndef __T42ERROR_H__
#define __T42ERROR_H__
#include FT_MODULE_ERRORS_H
#undef __FTERRORS_H__
#define FT_ERR_PREFIX T42_Err_
#define FT_ERR_BASE FT_Mod_Err_T42
#include FT_ERRORS_H
#endif /* __T42ERROR_H__ */
/* END */

View File

@ -0,0 +1,919 @@
/***************************************************************************/
/* */
/* t42objs.c */
/* */
/* Type 42 objects manager (body). */
/* */
/* Copyright 2002 by Roberto Alameda. */
/* */
/* 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 "t42objs.h"
#include "t42parse.h"
#include "t42error.h"
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_LIST_H
#undef FT_COMPONENT
#define FT_COMPONENT trace_t42
static FT_Error
T42_Open_Face( T42_Face face )
{
T42_LoaderRec loader;
T42_Parser parser;
T1_Font type1 = &face->type1;
FT_Memory memory = face->root.memory;
FT_Error error;
PSAux_Service psaux = (PSAux_Service)face->psaux;
t42_loader_init( &loader, face );
parser = &loader.parser;
if ( FT_ALLOC( face->ttf_data, 12 ) )
goto Exit;
error = t42_parser_init( parser,
face->root.stream,
memory,
psaux);
if ( error )
goto Exit;
error = t42_parse_dict( face, &loader, parser->base_dict, parser->base_len );
if ( type1->font_type != 42 )
{
error = T42_Err_Unknown_File_Format;
goto Exit;
}
/* now, propagate the charstrings and glyphnames tables */
/* to the Type1 data */
type1->num_glyphs = loader.num_glyphs;
if ( !loader.charstrings.init ) {
FT_ERROR(( "T42_Open_Face: no charstrings array in face!\n" ));
error = T42_Err_Invalid_File_Format;
}
loader.charstrings.init = 0;
type1->charstrings_block = loader.charstrings.block;
type1->charstrings = loader.charstrings.elements;
type1->charstrings_len = loader.charstrings.lengths;
/* we copy the glyph names `block' and `elements' fields; */
/* the `lengths' field must be released later */
type1->glyph_names_block = loader.glyph_names.block;
type1->glyph_names = (FT_String**)loader.glyph_names.elements;
loader.glyph_names.block = 0;
loader.glyph_names.elements = 0;
/* we must now build type1.encoding when we have a custom array */
if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY )
{
FT_Int charcode, idx, min_char, max_char;
FT_Byte* char_name;
FT_Byte* glyph_name;
/* OK, we do the following: for each element in the encoding */
/* table, look up the index of the glyph having the same name */
/* as defined in the CharStrings array. */
/* The index is then stored in type1.encoding.char_index, and */
/* the name in type1.encoding.char_name */
min_char = +32000;
max_char = -32000;
charcode = 0;
for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
{
type1->encoding.char_index[charcode] = 0;
type1->encoding.char_name [charcode] = (char *)".notdef";
char_name = loader.encoding_table.elements[charcode];
if ( char_name )
for ( idx = 0; idx < type1->num_glyphs; idx++ )
{
glyph_name = (FT_Byte*)type1->glyph_names[idx];
if ( ft_strcmp( (const char*)char_name,
(const char*)glyph_name ) == 0 )
{
type1->encoding.char_index[charcode] = (FT_UShort)idx;
type1->encoding.char_name [charcode] = (char*)glyph_name;
/* Change min/max encoded char only if glyph name is */
/* not /.notdef */
if ( ft_strcmp( (const char*)".notdef",
(const char*)glyph_name ) != 0 )
{
if ( charcode < min_char ) min_char = charcode;
if ( charcode > max_char ) max_char = charcode;
}
break;
}
}
}
type1->encoding.code_first = min_char;
type1->encoding.code_last = max_char;
type1->encoding.num_chars = loader.num_chars;
}
Exit:
t42_loader_done( &loader );
return error;
}
/***************** Driver Functions *************/
FT_LOCAL_DEF( FT_Error )
T42_Face_Init( FT_Stream stream,
T42_Face face,
FT_Int face_index,
FT_Int num_params,
FT_Parameter* params)
{
FT_Error error;
PSNames_Service psnames;
PSAux_Service psaux;
FT_Face root = (FT_Face)&face->root;
FT_UNUSED( num_params );
FT_UNUSED( params );
FT_UNUSED( face_index );
FT_UNUSED( stream );
face->ttf_face = NULL;
face->root.num_faces = 1;
face->psnames = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
"psnames" );
psnames = (PSNames_Service)face->psnames;
face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
"psaux" );
psaux = (PSAux_Service)face->psaux;
/* open the tokenizer, this will also check the font format */
error = T42_Open_Face( face );
if ( error )
goto Exit;
/* if we just wanted to check the format, leave successfully now */
if ( face_index < 0 )
goto Exit;
/* check the face index */
if ( face_index != 0 )
{
FT_ERROR(( "T42_Face_Init: invalid face index\n" ));
error = T42_Err_Invalid_Argument;
goto Exit;
}
/* Now, load the font program into the face object */
/* Init the face object fields */
/* Now set up root face fields */
root->num_glyphs = face->type1.num_glyphs;
root->num_charmaps = 0;
root->face_index = face_index;
root->face_flags = FT_FACE_FLAG_SCALABLE;
root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
if ( face->type1.font_info.is_fixed_pitch )
root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
/* XXX: TODO -- add kerning with .afm support */
/* get style name -- be careful, some broken fonts only */
/* have a `/FontName' dictionary entry! */
root->family_name = face->type1.font_info.family_name;
if ( root->family_name )
{
char* full = face->type1.font_info.full_name;
char* family = root->family_name;
if ( full )
{
while ( *family && *full == *family )
{
family++;
full++;
}
root->style_name = ( *full == ' ' ? full + 1
: (char *)"Regular" );
}
else
root->style_name = (char *)"Regular";
}
else
{
/* do we have a `/FontName'? */
if ( face->type1.font_name )
{
root->family_name = face->type1.font_name;
root->style_name = (char *)"Regular";
}
}
/* no embedded bitmap support */
root->num_fixed_sizes = 0;
root->available_sizes = 0;
/* Load the TTF font embedded in the T42 font */
error = FT_New_Memory_Face( FT_FACE_LIBRARY( face ),
face->ttf_data,
face->ttf_size,
0,
&face->ttf_face );
if ( error )
goto Exit;
FT_Done_Size( face->ttf_face->size );
/* Ignore info in FontInfo dictionary and use the info from the */
/* loaded TTF font. The PostScript interpreter also ignores it. */
root->bbox = face->ttf_face->bbox;
root->units_per_EM = face->ttf_face->units_per_EM;
root->ascender = face->ttf_face->ascender;
root->descender = face->ttf_face->descender;
root->height = face->ttf_face->height;
root->max_advance_width = face->ttf_face->max_advance_width;
root->max_advance_height = face->ttf_face->max_advance_height;
root->underline_position = face->type1.font_info.underline_position;
root->underline_thickness = face->type1.font_info.underline_thickness;
root->internal->max_points = 0;
root->internal->max_contours = 0;
/* compute style flags */
root->style_flags = 0;
if ( face->type1.font_info.italic_angle )
root->style_flags |= FT_STYLE_FLAG_ITALIC;
if ( face->ttf_face->style_flags & FT_STYLE_FLAG_BOLD )
root->style_flags |= FT_STYLE_FLAG_BOLD;
if ( face->ttf_face->face_flags & FT_FACE_FLAG_VERTICAL )
root->face_flags |= FT_FACE_FLAG_VERTICAL;
#ifdef FT_CONFIG_OPTION_USE_CMAPS
{
if ( psnames && psaux )
{
FT_CharMapRec charmap;
T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes;
FT_CMap_Class clazz;
charmap.face = root;
/* first of all, try to synthetize a Unicode charmap */
charmap.platform_id = 3;
charmap.encoding_id = 1;
charmap.encoding = ft_encoding_unicode;
FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );
/* now, generate an Adobe Standard encoding when appropriate */
charmap.platform_id = 7;
clazz = NULL;
switch ( face->type1.encoding_type )
{
case T1_ENCODING_TYPE_STANDARD:
charmap.encoding = ft_encoding_adobe_standard;
charmap.encoding_id = 0;
clazz = cmap_classes->standard;
break;
case T1_ENCODING_TYPE_EXPERT:
charmap.encoding = ft_encoding_adobe_expert;
charmap.encoding_id = 1;
clazz = cmap_classes->expert;
break;
case T1_ENCODING_TYPE_ARRAY:
charmap.encoding = ft_encoding_adobe_custom;
charmap.encoding_id = 2;
clazz = cmap_classes->custom;
break;
case T1_ENCODING_TYPE_ISOLATIN1:
charmap.encoding = ft_encoding_latin_1;
charmap.encoding_id = 3;
clazz = cmap_classes->unicode;
break;
default:
;
}
if ( clazz )
FT_CMap_New( clazz, NULL, &charmap, NULL );
/* Select default charmap */
if (root->num_charmaps)
root->charmap = root->charmaps[0];
}
}
#else /* !FT_CONFIG_OPTION_USE_CMAPS */
/* charmap support -- synthetize unicode charmap if possible */
{
FT_CharMap charmap = face->charmaprecs;
/* synthesize a Unicode charmap if there is support in the `PSNames' */
/* module */
if ( psnames && psnames->unicode_value )
{
error = psnames->build_unicodes( root->memory,
face->type1.num_glyphs,
(const char**)face->type1.glyph_names,
&face->unicode_map );
if ( !error )
{
root->charmap = charmap;
charmap->face = (FT_Face)face;
charmap->encoding = ft_encoding_unicode;
charmap->platform_id = 3;
charmap->encoding_id = 1;
charmap++;
}
/* XXX: Is the following code correct? It is used in t1objs.c */
/* simply clear the error in case of failure (which really) */
/* means that out of memory or no unicode glyph names */
error = T42_Err_Ok;
}
/* now, support either the standard, expert, or custom encoding */
charmap->face = (FT_Face)face;
charmap->platform_id = 7; /* a new platform id for Adobe fonts? */
switch ( face->type1.encoding_type )
{
case T1_ENCODING_TYPE_STANDARD:
charmap->encoding = ft_encoding_adobe_standard;
charmap->encoding_id = 0;
break;
case T1_ENCODING_TYPE_EXPERT:
charmap->encoding = ft_encoding_adobe_expert;
charmap->encoding_id = 1;
break;
case T1_ENCODING_TYPE_ARRAY:
charmap->encoding = ft_encoding_adobe_custom;
charmap->encoding_id = 2;
break;
case T1_ENCODING_TYPE_ISOLATIN1:
charmap->encoding = ft_encoding_latin_1;
charmap->encoding_id = 3;
break;
default:
FT_ERROR(( "T42_Face_Init: invalid encoding\n" ));
error = T42_Err_Invalid_File_Format;
goto Exit;
}
root->charmaps = face->charmaps;
root->num_charmaps = charmap - face->charmaprecs + 1;
face->charmaps[0] = &face->charmaprecs[0];
face->charmaps[1] = &face->charmaprecs[1];
}
#endif /* !FT_CONFIG_OPTION_USE_CMAPS */
Exit:
return error;
}
FT_LOCAL_DEF( void )
T42_Face_Done( T42_Face face )
{
T1_Font type1;
PS_FontInfo info;
FT_Memory memory;
if ( face )
{
type1 = &face->type1;
info = &type1->font_info;
memory = face->root.memory;
/* delete internal ttf face prior to freeing face->ttf_data */
if ( face->ttf_face )
FT_Done_Face( face->ttf_face );
/* release font info strings */
FT_FREE( info->version );
FT_FREE( info->notice );
FT_FREE( info->full_name );
FT_FREE( info->family_name );
FT_FREE( info->weight );
/* release top dictionary */
FT_FREE( type1->charstrings_len );
FT_FREE( type1->charstrings );
FT_FREE( type1->glyph_names );
FT_FREE( type1->charstrings_block );
FT_FREE( type1->glyph_names_block );
FT_FREE( type1->encoding.char_index );
FT_FREE( type1->encoding.char_name );
FT_FREE( type1->font_name );
FT_FREE( face->ttf_data );
#if 0
/* release afm data if present */
if ( face->afm_data )
T1_Done_AFM( memory, (T1_AFM*)face->afm_data );
#endif
/* release unicode map, if any */
FT_FREE( face->unicode_map.maps );
face->unicode_map.num_maps = 0;
face->root.family_name = 0;
face->root.style_name = 0;
}
}
/*************************************************************************/
/* */
/* <Function> */
/* T42_Driver_Init */
/* */
/* <Description> */
/* Initializes a given Type 42 driver object. */
/* */
/* <Input> */
/* driver :: A handle to the target driver object. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
T42_Driver_Init( T42_Driver driver )
{
FT_Module ttmodule;
ttmodule = FT_Get_Module( FT_MODULE(driver)->library, "truetype" );
driver->ttclazz = (FT_Driver_Class)ttmodule->clazz;
return T42_Err_Ok;
}
FT_LOCAL_DEF( void )
T42_Driver_Done( T42_Driver driver )
{
FT_UNUSED( driver );
}
FT_LOCAL_DEF( FT_UInt )
T42_CMap_CharIndex( FT_CharMap charmap,
FT_Long charcode )
{
T42_Face face;
FT_UInt result = 0;
PSNames_Service psnames;
face = (T42_Face)charmap->face;
psnames = (PSNames_Service)face->psnames;
if (!psnames )
goto Exit;
switch ( charmap->encoding )
{
/*******************************************************************/
/* */
/* Unicode encoding support */
/* */
case ft_encoding_unicode:
/* if this charmap is used, we ignore the encoding of the font and */
/* use the `PSNames' module to synthetize the Unicode charmap */
result = psnames->lookup_unicode( &face->unicode_map,
(FT_ULong)charcode );
/* the function returns 0xFFFF if the Unicode charcode has */
/* no corresponding glyph */
if ( result == 0xFFFFU )
result = 0;
/* The result returned is the index (position)in the CharStrings */
/* array. This must be used now to get the value associated to */
/* that glyph_name, which is the real index within the truetype */
/* structure. */
result = ft_atoi( (const char*)face->type1.charstrings[result] );
goto Exit;
/*******************************************************************/
/* */
/* ISOLatin1 encoding support */
/* */
case ft_encoding_latin_1:
/* ISOLatin1 is the first page of Unicode */
if ( charcode < 256 && psnames->unicode_value )
{
result = psnames->lookup_unicode( &face->unicode_map,
(FT_ULong)charcode );
/* the function returns 0xFFFF if the Unicode charcode has */
/* no corresponding glyph */
if ( result == 0xFFFFU )
result = 0;
}
goto Exit;
/*******************************************************************/
/* */
/* Custom Type 1 encoding */
/* */
case ft_encoding_adobe_custom:
{
T1_Encoding encoding = &face->type1.encoding;
if ( charcode >= encoding->code_first &&
charcode <= encoding->code_last )
{
FT_UInt idx = encoding->char_index[charcode];
result = ft_atoi( (const char *)face->type1.charstrings[idx] );
}
goto Exit;
}
/*******************************************************************/
/* */
/* Adobe Standard & Expert encoding support */
/* */
default:
if ( charcode < 256 )
{
FT_UInt code;
FT_Int n;
const char* glyph_name;
code = psnames->adobe_std_encoding[charcode];
if ( charmap->encoding == ft_encoding_adobe_expert )
code = psnames->adobe_expert_encoding[charcode];
glyph_name = psnames->adobe_std_strings( code );
if ( !glyph_name )
break;
for ( n = 0; n < face->type1.num_glyphs; n++ )
{
const char* gname = face->type1.glyph_names[n];
if ( gname && ( ft_strcmp( gname, glyph_name ) == 0 ) )
{
result = ft_atoi( (const char *)face->type1.charstrings[n] );
break;
}
}
}
}
Exit:
return result;
}
FT_LOCAL_DEF( FT_Error )
T42_Size_Init( T42_Size size )
{
FT_Face face = size->root.face;
T42_Face t42face = (T42_Face)face;
FT_Size ttsize;
FT_Error error = T42_Err_Ok;
error = FT_New_Size( t42face->ttf_face, &ttsize );
size->ttsize = ttsize;
FT_Activate_Size( ttsize );
return error;
}
FT_LOCAL_DEF( void )
T42_Size_Done( T42_Size size )
{
FT_Face face = size->root.face;
T42_Face t42face = (T42_Face)face;
FT_ListNode node;
node = FT_List_Find( &t42face->ttf_face->sizes_list, size->ttsize );
if ( node )
{
FT_Done_Size( size->ttsize );
size->ttsize = NULL;
}
}
FT_LOCAL_DEF( FT_Error )
T42_GlyphSlot_Init( T42_GlyphSlot slot )
{
FT_Face face = slot->root.face;
T42_Face t42face = (T42_Face)face;
FT_GlyphSlot ttslot;
FT_Error error = T42_Err_Ok;
if ( face->glyph == NULL )
{
/* First glyph slot for this face */
slot->ttslot = t42face->ttf_face->glyph;
}
else
{
error = FT_New_GlyphSlot( t42face->ttf_face, &ttslot );
slot->ttslot = ttslot;
}
return error;
}
FT_LOCAL_DEF( void )
T42_GlyphSlot_Done( T42_GlyphSlot slot )
{
FT_Face face = slot->root.face;
T42_Face t42face = (T42_Face)face;
FT_GlyphSlot cur = t42face->ttf_face->glyph;
while ( cur )
{
if ( cur == slot->ttslot )
{
FT_Done_GlyphSlot( slot->ttslot );
break;
}
cur = cur->next;
}
}
FT_LOCAL_DEF( FT_Error )
T42_Size_SetChars( T42_Size size,
FT_F26Dot6 char_width,
FT_F26Dot6 char_height,
FT_UInt horz_resolution,
FT_UInt vert_resolution )
{
FT_Face face = size->root.face;
T42_Face t42face = (T42_Face)face;
FT_Activate_Size(size->ttsize);
return FT_Set_Char_Size( t42face->ttf_face,
char_width,
char_height,
horz_resolution,
vert_resolution );
}
FT_LOCAL_DEF( FT_Error )
T42_Size_SetPixels( T42_Size size,
FT_UInt pixel_width,
FT_UInt pixel_height )
{
FT_Face face = size->root.face;
T42_Face t42face = (T42_Face)face;
FT_Activate_Size(size->ttsize);
return FT_Set_Pixel_Sizes( t42face->ttf_face,
pixel_width,
pixel_height );
}
static void
ft_glyphslot_clear( FT_GlyphSlot slot )
{
/* free bitmap if needed */
if ( slot->flags & FT_GLYPH_OWN_BITMAP )
{
FT_Memory memory = FT_FACE_MEMORY( slot->face );
FT_FREE( slot->bitmap.buffer );
slot->flags &= ~FT_GLYPH_OWN_BITMAP;
}
/* clear all public fields in the glyph slot */
FT_ZERO( &slot->metrics );
FT_ZERO( &slot->outline );
FT_ZERO( &slot->bitmap );
slot->bitmap_left = 0;
slot->bitmap_top = 0;
slot->num_subglyphs = 0;
slot->subglyphs = 0;
slot->control_data = 0;
slot->control_len = 0;
slot->other = 0;
slot->format = ft_glyph_format_none;
slot->linearHoriAdvance = 0;
slot->linearVertAdvance = 0;
}
FT_LOCAL_DEF( FT_Error )
T42_GlyphSlot_Load( FT_GlyphSlot glyph,
FT_Size size,
FT_Int glyph_index,
FT_Int load_flags )
{
FT_Error error;
T42_GlyphSlot t42slot = (T42_GlyphSlot)glyph;
T42_Size t42size = (T42_Size)size;
FT_Driver_Class ttclazz = ((T42_Driver)glyph->face->driver)->ttclazz;
ft_glyphslot_clear( t42slot->ttslot );
error = ttclazz->load_glyph( t42slot->ttslot,
t42size->ttsize,
glyph_index,
load_flags | FT_LOAD_NO_BITMAP );
if ( !error )
{
glyph->metrics = t42slot->ttslot->metrics;
glyph->linearHoriAdvance = t42slot->ttslot->linearHoriAdvance;
glyph->linearVertAdvance = t42slot->ttslot->linearVertAdvance;
glyph->format = t42slot->ttslot->format;
glyph->outline = t42slot->ttslot->outline;
glyph->bitmap = t42slot->ttslot->bitmap;
glyph->bitmap_left = t42slot->ttslot->bitmap_left;
glyph->bitmap_top = t42slot->ttslot->bitmap_top;
glyph->num_subglyphs = t42slot->ttslot->num_subglyphs;
glyph->subglyphs = t42slot->ttslot->subglyphs;
glyph->control_data = t42slot->ttslot->control_data;
glyph->control_len = t42slot->ttslot->control_len;
}
return error;
}
FT_LOCAL_DEF( FT_Long )
T42_CMap_CharNext( FT_CharMap charmap,
FT_Long charcode )
{
T42_Face face;
PSNames_Service psnames;
face = (T42_Face)charmap->face;
psnames = (PSNames_Service)face->psnames;
if ( psnames )
switch ( charmap->encoding )
{
/*******************************************************************/
/* */
/* Unicode encoding support */
/* */
case ft_encoding_unicode:
/* use the `PSNames' module to synthetize the Unicode charmap */
return psnames->next_unicode( &face->unicode_map,
(FT_ULong)charcode );
/*******************************************************************/
/* */
/* ISOLatin1 encoding support */
/* */
case ft_encoding_latin_1:
{
FT_ULong code;
/* use the `PSNames' module to synthetize the Unicode charmap */
code = psnames->next_unicode( &face->unicode_map,
(FT_ULong)charcode );
if ( code < 256 )
return code;
break;
}
/*******************************************************************/
/* */
/* Custom Type 1 encoding */
/* */
case ft_encoding_adobe_custom:
{
T1_Encoding encoding = &face->type1.encoding;
charcode++;
if ( charcode < encoding->code_first )
charcode = encoding->code_first;
while ( charcode <= encoding->code_last ) {
if ( encoding->char_index[charcode] )
return charcode;
charcode++;
}
}
/*******************************************************************/
/* */
/* Adobe Standard & Expert encoding support */
/* */
default:
while ( ++charcode < 256 )
{
FT_UInt code;
FT_Int n;
const char* glyph_name;
code = psnames->adobe_std_encoding[charcode];
if ( charmap->encoding == ft_encoding_adobe_expert )
code = psnames->adobe_expert_encoding[charcode];
glyph_name = psnames->adobe_std_strings( code );
if ( !glyph_name )
continue;
for ( n = 0; n < face->type1.num_glyphs; n++ )
{
const char* gname = face->type1.glyph_names[n];
if ( gname && gname[0] == glyph_name[0] &&
ft_strcmp( gname, glyph_name ) == 0 )
return charcode;
}
}
}
return 0;
}
/* END */

View File

@ -0,0 +1,135 @@
/***************************************************************************/
/* */
/* t42objs.h */
/* */
/* Type 42 objects manager (specification). */
/* */
/* Copyright 2002 by Roberto Alameda. */
/* */
/* 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. */
/* */
/***************************************************************************/
#ifndef __T42OBJS_H__
#define __T42OBJS_H__
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_TYPE1_TABLES_H
#include FT_INTERNAL_TYPE1_TYPES_H
#include FT_INTERNAL_TYPE42_TYPES_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DRIVER_H
#include FT_INTERNAL_POSTSCRIPT_NAMES_H
#include FT_INTERNAL_POSTSCRIPT_HINTS_H
FT_BEGIN_HEADER
/* Type42 size */
typedef struct T42_SizeRec_
{
FT_SizeRec root;
FT_Size ttsize;
} T42_SizeRec, *T42_Size;
/* Type42 slot */
typedef struct T42_GlyphSlotRec_
{
FT_GlyphSlotRec root;
FT_GlyphSlot ttslot;
} T42_GlyphSlotRec, *T42_GlyphSlot;
/* Type 42 driver */
typedef struct T42_DriverRec_
{
FT_DriverRec root;
FT_Driver_Class ttclazz;
void* extension_component;
} T42_DriverRec, *T42_Driver;
/* */
FT_LOCAL( FT_Error )
T42_Face_Init( FT_Stream stream,
T42_Face face,
FT_Int face_index,
FT_Int num_params,
FT_Parameter* params );
FT_LOCAL( void )
T42_Face_Done( T42_Face face );
FT_LOCAL( FT_Error )
T42_Size_Init( T42_Size size );
FT_LOCAL( FT_Error )
T42_Size_SetChars( T42_Size size,
FT_F26Dot6 char_width,
FT_F26Dot6 char_height,
FT_UInt horz_resolution,
FT_UInt vert_resolution );
FT_LOCAL( FT_Error )
T42_Size_SetPixels( T42_Size size,
FT_UInt pixel_width,
FT_UInt pixel_height );
FT_LOCAL( void )
T42_Size_Done( T42_Size size );
FT_LOCAL( FT_Error )
T42_GlyphSlot_Init( T42_GlyphSlot slot );
FT_LOCAL( FT_Error )
T42_GlyphSlot_Load( FT_GlyphSlot glyph,
FT_Size size,
FT_Int glyph_index,
FT_Int load_flags );
FT_LOCAL( void )
T42_GlyphSlot_Done( T42_GlyphSlot slot );
FT_LOCAL( FT_UInt )
T42_CMap_CharIndex( FT_CharMap charmap,
FT_Long charcode );
FT_LOCAL( FT_Long )
T42_CMap_CharNext( FT_CharMap charmap,
FT_Long charcode );
FT_LOCAL( FT_Error )
T42_Driver_Init( T42_Driver driver );
FT_LOCAL( void )
T42_Driver_Done( T42_Driver driver );
/* */
FT_END_HEADER
#endif /* __T42OBJS_H__ */
/* END */

View File

@ -0,0 +1,994 @@
/***************************************************************************/
/* */
/* t42parse.c */
/* */
/* Type 42 font parser (body). */
/* */
/* Copyright 2002 by Roberto Alameda. */
/* */
/* 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 "t42parse.h"
#include "t42error.h"
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_LIST_H
#include FT_INTERNAL_POSTSCRIPT_AUX_H
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_t42
static void
t42_parse_font_name( T42_Face face,
T42_Loader loader );
static void
t42_parse_font_bbox( T42_Face face,
T42_Loader loader );
static void
t42_parse_font_matrix( T42_Face face,
T42_Loader loader );
static void
t42_parse_encoding( T42_Face face,
T42_Loader loader );
static void
t42_parse_charstrings( T42_Face face,
T42_Loader loader );
static void
t42_parse_sfnts( T42_Face face,
T42_Loader loader );
static const
T1_FieldRec t42_keywords[] = {
#undef FT_STRUCTURE
#define FT_STRUCTURE T1_FontInfo
#undef T1CODE
#define T1CODE T1_FIELD_LOCATION_FONT_INFO
T1_FIELD_STRING ( "version", version )
T1_FIELD_STRING ( "Notice", notice )
T1_FIELD_STRING ( "FullName", full_name )
T1_FIELD_STRING ( "FamilyName", family_name )
T1_FIELD_STRING ( "Weight", weight )
T1_FIELD_NUM ( "ItalicAngle", italic_angle )
T1_FIELD_TYPE_BOOL( "isFixedPitch", is_fixed_pitch )
T1_FIELD_NUM ( "UnderlinePosition", underline_position )
T1_FIELD_NUM ( "UnderlineThickness", underline_thickness )
#undef FT_STRUCTURE
#define FT_STRUCTURE T1_FontRec
#undef T1CODE
#define T1CODE T1_FIELD_LOCATION_FONT_DICT
T1_FIELD_NUM( "PaintType", paint_type )
T1_FIELD_NUM( "FontType", font_type )
T1_FIELD_NUM( "StrokeWidth", stroke_width )
T1_FIELD_CALLBACK( "FontName", t42_parse_font_name )
T1_FIELD_CALLBACK( "FontBBox", t42_parse_font_bbox )
T1_FIELD_CALLBACK( "FontMatrix", t42_parse_font_matrix )
T1_FIELD_CALLBACK( "Encoding", t42_parse_encoding )
T1_FIELD_CALLBACK( "CharStrings", t42_parse_charstrings )
T1_FIELD_CALLBACK( "sfnts", t42_parse_sfnts )
{ 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 }
};
#define T1_Add_Table( p, i, o, l ) (p)->funcs.add( (p), i, o, l )
#define T1_Done_Table( p ) \
do \
{ \
if ( (p)->funcs.done ) \
(p)->funcs.done( p ); \
} while ( 0 )
#define T1_Release_Table( p ) \
do \
{ \
if ( (p)->funcs.release ) \
(p)->funcs.release( p ); \
} while ( 0 )
#define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root )
#define T1_Skip_Alpha( p ) (p)->root.funcs.skip_alpha ( &(p)->root )
#define T1_ToInt( p ) (p)->root.funcs.to_int( &(p)->root )
#define T1_ToFixed( p, t ) (p)->root.funcs.to_fixed( &(p)->root, t )
#define T1_ToCoordArray( p, m, c ) \
(p)->root.funcs.to_coord_array( &(p)->root, m, c )
#define T1_ToFixedArray( p, m, f, t ) \
(p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
#define T1_ToToken( p, t ) \
(p)->root.funcs.to_token( &(p)->root, t )
#define T1_ToTokenArray( p, t, m, c ) \
(p)->root.funcs.to_token_array( &(p)->root, t, m, c )
#define T1_Load_Field( p, f, o, m, pf ) \
(p)->root.funcs.load_field( &(p)->root, f, o, m, pf )
#define T1_Load_Field_Table( p, f, o, m, pf ) \
(p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )
/********************* Parsing Functions ******************/
FT_LOCAL_DEF( FT_Error )
t42_parser_init( T42_Parser parser,
FT_Stream stream,
FT_Memory memory,
PSAux_Service psaux )
{
FT_Error error = T42_Err_Ok;
FT_Long size;
psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
parser->stream = stream;
parser->base_len = 0;
parser->base_dict = 0;
parser->in_memory = 0;
/*******************************************************************/
/* */
/* Here a short summary of what is going on: */
/* */
/* When creating a new Type 42 parser, we try to locate and load */
/* the base dictionary, loading the whole font into memory. */
/* */
/* When `loading' the base dictionary, we only setup pointers in */
/* the case of a memory-based stream. Otherwise, we allocate */
/* and load the base dictionary in it. */
/* */
/* parser->in_memory is set if we have a memory stream. */
/* */
if ( FT_STREAM_SEEK( 0L ) )
goto Exit;
size = stream->size;
/* now, try to load `size' bytes of the `base' dictionary we */
/* found previously */
/* if it is a memory-based resource, set up pointers */
if ( !stream->read )
{
parser->base_dict = (FT_Byte*)stream->base + stream->pos;
parser->base_len = size;
parser->in_memory = 1;
/* check that the `size' field is valid */
if ( FT_STREAM_SKIP( size ) )
goto Exit;
}
else
{
/* read segment in memory */
if ( FT_ALLOC( parser->base_dict, size ) ||
FT_STREAM_READ( parser->base_dict, size ) )
goto Exit;
parser->base_len = size;
}
/* Now check font format; we must see `%!PS-TrueTypeFont' */
if (size <= 17 ||
( ft_strncmp( (const char*)parser->base_dict,
"%!PS-TrueTypeFont", 17) ) )
error = T42_Err_Unknown_File_Format;
else
{
parser->root.base = parser->base_dict;
parser->root.cursor = parser->base_dict;
parser->root.limit = parser->root.cursor + parser->base_len;
}
Exit:
if ( error && !parser->in_memory )
FT_FREE( parser->base_dict );
return error;
}
FT_LOCAL_DEF( void )
t42_parser_done( T42_Parser parser )
{
FT_Memory memory = parser->root.memory;
/* free the base dictionary only when we have a disk stream */
if ( !parser->in_memory )
FT_FREE( parser->base_dict );
parser->root.funcs.done( &parser->root );
}
static int
t42_is_alpha( FT_Byte c )
{
/* Note: we must accept "+" as a valid character, as it is used in */
/* embedded type1 fonts in PDF documents. */
/* */
return ( ft_isalnum( c ) ||
c == '.' ||
c == '_' ||
c == '-' ||
c == '+' );
}
static int
t42_is_space( FT_Byte c )
{
return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
}
static void
t42_parse_font_name( T42_Face face,
T42_Loader loader )
{
T42_Parser parser = &loader->parser;
FT_Error error;
FT_Memory memory = parser->root.memory;
FT_Int len;
FT_Byte* cur;
FT_Byte* cur2;
FT_Byte* limit;
T1_Skip_Spaces( parser );
cur = parser->root.cursor;
limit = parser->root.limit;
if ( cur >= limit - 1 ||
( *cur != '/' && *cur != '(') )
return;
cur++;
cur2 = cur;
while ( cur2 < limit && t42_is_alpha( *cur2 ) )
cur2++;
len = (FT_Int)( cur2 - cur );
if ( len > 0 )
{
if ( FT_ALLOC( face->type1.font_name, len + 1 ) )
{
parser->root.error = error;
return;
}
FT_MEM_COPY( face->type1.font_name, cur, len );
face->type1.font_name[len] = '\0';
}
parser->root.cursor = cur2;
}
static void
t42_parse_font_bbox( T42_Face face,
T42_Loader loader )
{
T42_Parser parser = &loader->parser;
FT_BBox* bbox = &face->type1.font_bbox;
bbox->xMin = T1_ToInt( parser );
bbox->yMin = T1_ToInt( parser );
bbox->xMax = T1_ToInt( parser );
bbox->yMax = T1_ToInt( parser );
}
static void
t42_parse_font_matrix( T42_Face face,
T42_Loader loader )
{
T42_Parser parser = &loader->parser;
FT_Matrix* matrix = &face->type1.font_matrix;
FT_Vector* offset = &face->type1.font_offset;
FT_Face root = (FT_Face)&face->root;
FT_Fixed temp[6];
FT_Fixed temp_scale;
(void)T1_ToFixedArray( parser, 6, temp, 3 );
temp_scale = ABS( temp[3] );
/* Set Units per EM based on FontMatrix values. We set the value to */
/* 1000 / temp_scale, because temp_scale was already multiplied by */
/* 1000 (in t1_tofixed, from psobjs.c). */
root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L,
temp_scale ) >> 16 );
/* we need to scale the values by 1.0/temp_scale */
if ( temp_scale != 0x10000L ) {
temp[0] = FT_DivFix( temp[0], temp_scale );
temp[1] = FT_DivFix( temp[1], temp_scale );
temp[2] = FT_DivFix( temp[2], temp_scale );
temp[4] = FT_DivFix( temp[4], temp_scale );
temp[5] = FT_DivFix( temp[5], temp_scale );
temp[3] = 0x10000L;
}
matrix->xx = temp[0];
matrix->yx = temp[1];
matrix->xy = temp[2];
matrix->yy = temp[3];
/* note that the offsets must be expressed in integer font units */
offset->x = temp[4] >> 16;
offset->y = temp[5] >> 16;
}
static void
t42_parse_encoding( T42_Face face,
T42_Loader loader )
{
T42_Parser parser = &loader->parser;
FT_Byte* cur = parser->root.cursor;
FT_Byte* limit = parser->root.limit;
PSAux_Service psaux = (PSAux_Service)face->psaux;
/* skip whitespace */
while ( t42_is_space( *cur ) )
{
cur++;
if ( cur >= limit )
{
FT_ERROR(( "t42_parse_encoding: out of bounds!\n" ));
parser->root.error = T42_Err_Invalid_File_Format;
return;
}
}
/* if we have a number, then the encoding is an array, */
/* and we must load it now */
if ( (FT_Byte)( *cur - '0' ) < 10 )
{
T1_Encoding encode = &face->type1.encoding;
FT_Int count, n;
PS_Table char_table = &loader->encoding_table;
FT_Memory memory = parser->root.memory;
FT_Error error;
/* read the number of entries in the encoding, should be 256 */
count = T1_ToInt( parser );
if ( parser->root.error )
return;
/* we use a T1_Table to store our charnames */
loader->num_chars = encode->num_chars = count;
if ( FT_NEW_ARRAY( encode->char_index, count ) ||
FT_NEW_ARRAY( encode->char_name, count ) ||
FT_SET_ERROR( psaux->ps_table_funcs->init(
char_table, count, memory ) ) )
{
parser->root.error = error;
return;
}
/* We need to `zero' out encoding_table.elements */
for ( n = 0; n < count; n++ )
{
char* notdef = (char *)".notdef";
T1_Add_Table( char_table, n, notdef, 8 );
}
/* Now, we will need to read a record of the form */
/* ... charcode /charname ... for each entry in our table */
/* */
/* We simply look for a number followed by an immediate */
/* name. Note that this ignores correctly the sequence */
/* that is often seen in type1 fonts: */
/* */
/* 0 1 255 { 1 index exch /.notdef put } for dup */
/* */
/* used to clean the encoding array before anything else. */
/* */
/* We stop when we encounter a `def'. */
cur = parser->root.cursor;
limit = parser->root.limit;
n = 0;
for ( ; cur < limit; )
{
FT_Byte c;
c = *cur;
/* we stop when we encounter a `def' */
if ( c == 'd' && cur + 3 < limit )
{
if ( cur[1] == 'e' &&
cur[2] == 'f' &&
t42_is_space( cur[-1] ) &&
t42_is_space( cur[3] ) )
{
FT_TRACE6(( "encoding end\n" ));
break;
}
}
/* otherwise, we must find a number before anything else */
if ( (FT_Byte)( c - '0' ) < 10 )
{
FT_Int charcode;
parser->root.cursor = cur;
charcode = T1_ToInt( parser );
cur = parser->root.cursor;
/* skip whitespace */
while ( cur < limit && t42_is_space( *cur ) )
cur++;
if ( cur < limit && *cur == '/' )
{
/* bingo, we have an immediate name -- it must be a */
/* character name */
FT_Byte* cur2 = cur + 1;
FT_Int len;
while ( cur2 < limit && t42_is_alpha( *cur2 ) )
cur2++;
len = (FT_Int)( cur2 - cur - 1 );
parser->root.error = T1_Add_Table( char_table, charcode,
cur + 1, len + 1 );
char_table->elements[charcode][len] = '\0';
if ( parser->root.error )
return;
cur = cur2;
}
}
else
cur++;
}
face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY;
parser->root.cursor = cur;
}
/* Otherwise, we should have either `StandardEncoding', */
/* `ExpertEncoding', or `ISOLatin1Encoding' */
else
{
if ( cur + 17 < limit &&
ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;
else if ( cur + 15 < limit &&
ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;
else if ( cur + 18 < limit &&
ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;
else {
FT_ERROR(( "t42_parse_encoding: invalid token!\n" ));
parser->root.error = T42_Err_Invalid_File_Format;
}
}
}
static FT_UInt
t42_hexval( FT_Byte v )
{
FT_UInt d;
d = (FT_UInt)( v - 'A' );
if ( d < 6 )
{
d += 10;
goto Exit;
}
d = (FT_UInt)( v - 'a' );
if ( d < 6 )
{
d += 10;
goto Exit;
}
d = (FT_UInt)( v - '0' );
if ( d < 10 )
goto Exit;
d = 0;
Exit:
return d;
}
static void
t42_parse_sfnts( T42_Face face,
T42_Loader loader )
{
T42_Parser parser = &loader->parser;
FT_Memory memory = parser->root.memory;
FT_Byte* cur = parser->root.cursor;
FT_Byte* limit = parser->root.limit;
FT_Error error;
FT_Int num_tables = 0, status;
FT_ULong count, ttf_size = 0, string_size = 0;
FT_Bool in_string = 0;
FT_Byte v = 0;
/* The format is `/sfnts [ <...> <...> ... ] def' */
while ( t42_is_space( *cur ) )
cur++;
if (*cur++ == '[')
{
status = 0;
count = 0;
}
else
{
FT_ERROR(( "t42_parse_sfnts: can't find begin of sfnts vector!\n" ));
error = T42_Err_Invalid_File_Format;
goto Fail;
}
while ( cur < limit - 2 )
{
while ( t42_is_space( *cur ) )
cur++;
switch ( *cur )
{
case ']':
parser->root.cursor = cur++;
return;
case '<':
in_string = 1;
string_size = 0;
cur++;
continue;
case '>':
if ( !in_string )
{
FT_ERROR(( "t42_parse_sfnts: found unpaired `>'!\n" ));
error = T42_Err_Invalid_File_Format;
goto Fail;
}
/* A string can have, as a last byte, */
/* a zero byte for padding. If so, ignore it */
if ( ( v == 0 ) && ( string_size % 2 == 1 ) )
count--;
in_string = 0;
cur++;
continue;
case '%':
if ( !in_string )
{
/* Comment found; skip till end of line */
while ( *cur != '\n' )
cur++;
continue;
}
else
{
FT_ERROR(( "t42_parse_sfnts: found `%' in string!\n" ));
error = T42_Err_Invalid_File_Format;
goto Fail;
}
default:
if ( !ft_xdigit( *cur ) || !ft_xdigit( *(cur + 1) ) )
{
FT_ERROR(( "t42_parse_sfnts: found non-hex characters in string" ));
error = T42_Err_Invalid_File_Format;
goto Fail;
}
v = (FT_Byte)( 16 * t42_hexval( cur[0] ) + t42_hexval( cur[1] ) );
cur += 2;
string_size++;
}
switch ( status )
{
case 0: /* The '[' was read, so load offset table, 12 bytes */
if ( count < 12 )
{
face->ttf_data[count++] = v;
continue;
}
else
{
num_tables = 16 * face->ttf_data[4] + face->ttf_data[5];
status = 1;
ttf_size = 12 + 16 * num_tables;
if ( FT_REALLOC( face->ttf_data, 12, ttf_size ) )
goto Fail;
}
/* No break, fall-through */
case 1: /* The offset table is read; read now the table directory */
if ( count < ttf_size )
{
face->ttf_data[count++] = v;
continue;
}
else
{
int i;
FT_ULong len;
for ( i = 0; i < num_tables; i++ )
{
FT_Byte* p = face->ttf_data + 12 + 16*i + 12;
len = FT_PEEK_ULONG( p );
/* Pad to a 4-byte boundary length */
ttf_size += ( len + 3 ) & ~3;
}
status = 2;
face->ttf_size = ttf_size;
if ( FT_REALLOC( face->ttf_data, 12 + 16 * num_tables,
ttf_size + 1 ) )
goto Fail;
}
/* No break, fall-through */
case 2: /* We are reading normal tables; just swallow them */
face->ttf_data[count++] = v;
}
}
/* If control reaches this point, the format was not valid */
error = T42_Err_Invalid_File_Format;
Fail:
parser->root.error = error;
}
static void
t42_parse_charstrings( T42_Face face,
T42_Loader loader )
{
T42_Parser parser = &loader->parser;
PS_Table code_table = &loader->charstrings;
PS_Table name_table = &loader->glyph_names;
FT_Memory memory = parser->root.memory;
FT_Error error;
PSAux_Service psaux = (PSAux_Service)face->psaux;
FT_Byte* cur;
FT_Byte* limit = parser->root.limit;
FT_Int n;
loader->num_glyphs = T1_ToInt( parser );
if ( parser->root.error )
return;
/* initialize tables */
error = psaux->ps_table_funcs->init( code_table,
loader->num_glyphs,
memory );
if ( error )
goto Fail;
error = psaux->ps_table_funcs->init( name_table,
loader->num_glyphs,
memory );
if ( error )
goto Fail;
n = 0;
for (;;)
{
/* the format is simple: */
/* `/glyphname' + index + def */
/* */
/* note that we stop when we find an `end' */
/* */
T1_Skip_Spaces( parser );
cur = parser->root.cursor;
if ( cur >= limit )
break;
/* we stop when we find an `end' keyword */
if ( *cur == 'e' &&
cur + 3 < limit &&
cur[1] == 'n' &&
cur[2] == 'd' )
break;
if ( *cur != '/' )
T1_Skip_Alpha( parser );
else
{
FT_Byte* cur2 = cur + 1;
FT_Int len;
while ( cur2 < limit && t42_is_alpha( *cur2 ) )
cur2++;
len = (FT_Int)( cur2 - cur - 1 );
error = T1_Add_Table( name_table, n, cur + 1, len + 1 );
if ( error )
goto Fail;
/* add a trailing zero to the name table */
name_table->elements[n][len] = '\0';
parser->root.cursor = cur2;
T1_Skip_Spaces( parser );
cur2 = cur = parser->root.cursor;
if ( cur >= limit )
break;
while ( cur2 < limit && t42_is_alpha( *cur2 ) )
cur2++;
len = (FT_Int)( cur2 - cur );
error = T1_Add_Table( code_table, n, cur, len + 1 );
if ( error )
goto Fail;
code_table->elements[n][len] = '\0';
n++;
if ( n >= loader->num_glyphs )
break;
}
}
/* Index 0 must be a .notdef element */
if ( ft_strcmp( (char *)name_table->elements[0], ".notdef" ) )
{
FT_ERROR(( "t42_parse_charstrings: Index 0 is not `.notdef'!\n" ));
error = T42_Err_Invalid_File_Format;
goto Fail;
}
loader->num_glyphs = n;
return;
Fail:
parser->root.error = error;
}
static FT_Error
t42_load_keyword( T42_Face face,
T42_Loader loader,
T1_Field field )
{
FT_Error error;
void* dummy_object;
void** objects;
FT_UInt max_objects = 0;
/* if the keyword has a dedicated callback, call it */
if ( field->type == T1_FIELD_TYPE_CALLBACK ) {
field->reader( (FT_Face)face, loader );
error = loader->parser.root.error;
goto Exit;
}
/* now, the keyword is either a simple field, or a table of fields; */
/* we are now going to take care of it */
switch ( field->location )
{
case T1_FIELD_LOCATION_FONT_INFO:
dummy_object = &face->type1.font_info;
objects = &dummy_object;
break;
default:
dummy_object = &face->type1;
objects = &dummy_object;
}
if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
field->type == T1_FIELD_TYPE_FIXED_ARRAY )
error = T1_Load_Field_Table( &loader->parser, field,
objects, max_objects, 0 );
else
error = T1_Load_Field( &loader->parser, field,
objects, max_objects, 0 );
Exit:
return error;
}
FT_LOCAL_DEF( FT_Error )
t42_parse_dict( T42_Face face,
T42_Loader loader,
FT_Byte* base,
FT_Long size )
{
T42_Parser parser = &loader->parser;
FT_Byte* cur = base;
FT_Byte* limit = cur + size;
FT_UInt n_keywords = sizeof ( t42_keywords ) /
sizeof ( t42_keywords[0] );
parser->root.cursor = base;
parser->root.limit = base + size;
parser->root.error = 0;
for ( ; cur < limit; cur++ )
{
/* look for `FontDirectory', which causes problems on some fonts */
if ( *cur == 'F' && cur + 25 < limit &&
ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
{
FT_Byte* cur2;
/* skip the `FontDirectory' keyword */
cur += 13;
cur2 = cur;
/* lookup the `known' keyword */
while ( cur < limit && *cur != 'k' &&
ft_strncmp( (char*)cur, "known", 5 ) )
cur++;
if ( cur < limit )
{
T1_TokenRec token;
/* skip the `known' keyword and the token following it */
cur += 5;
loader->parser.root.cursor = cur;
T1_ToToken( &loader->parser, &token );
/* if the last token was an array, skip it! */
if ( token.type == T1_TOKEN_TYPE_ARRAY )
cur2 = parser->root.cursor;
}
cur = cur2;
}
/* look for immediates */
else if ( *cur == '/' && cur + 2 < limit )
{
FT_Byte* cur2;
FT_UInt i, len;
cur++;
cur2 = cur;
while ( cur2 < limit && t42_is_alpha( *cur2 ) )
cur2++;
len = (FT_UInt)( cur2 - cur );
if ( len > 0 && len < 22 ) /* XXX What shall it this 22? */
{
/* now, compare the immediate name to the keyword table */
/* Loop through all known keywords */
for ( i = 0; i < n_keywords; i++ )
{
T1_Field keyword = (T1_Field)&t42_keywords[i];
FT_Byte *name = (FT_Byte*)keyword->ident;
if ( !name )
continue;
if ( ( len == ft_strlen( (const char *)name ) ) &&
( ft_memcmp( cur, name, len ) == 0 ) )
{
/* we found it -- run the parsing callback! */
parser->root.cursor = cur2;
T1_Skip_Spaces( parser );
parser->root.error = t42_load_keyword(face,
loader,
keyword );
if ( parser->root.error )
return parser->root.error;
cur = parser->root.cursor;
break;
}
}
}
}
}
return parser->root.error;
}
FT_LOCAL_DEF( void )
t42_loader_init( T42_Loader loader,
T42_Face face )
{
FT_UNUSED( face );
FT_MEM_SET( loader, 0, sizeof ( *loader ) );
loader->num_glyphs = 0;
loader->num_chars = 0;
/* initialize the tables -- simply set their `init' field to 0 */
loader->encoding_table.init = 0;
loader->charstrings.init = 0;
loader->glyph_names.init = 0;
}
FT_LOCAL_DEF( void )
t42_loader_done( T42_Loader loader )
{
T42_Parser parser = &loader->parser;
/* finalize tables */
T1_Release_Table( &loader->encoding_table );
T1_Release_Table( &loader->charstrings );
T1_Release_Table( &loader->glyph_names );
/* finalize parser */
t42_parser_done( parser );
}
/* END */

View File

@ -0,0 +1,89 @@
/***************************************************************************/
/* */
/* t42parse.h */
/* */
/* Type 42 font parser (specification). */
/* */
/* Copyright 2002 by Roberto Alameda. */
/* */
/* 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. */
/* */
/***************************************************************************/
#ifndef __T42PARSE_H__
#define __T42PARSE_H__
#include "t42objs.h"
#include FT_INTERNAL_POSTSCRIPT_AUX_H
FT_BEGIN_HEADER
typedef struct T42_ParserRec_
{
PS_ParserRec root;
FT_Stream stream;
FT_Byte* base_dict;
FT_Int base_len;
FT_Byte in_memory;
} T42_ParserRec, *T42_Parser;
typedef struct T42_Loader_
{
T42_ParserRec parser; /* parser used to read the stream */
FT_Int num_chars; /* number of characters in encoding */
PS_TableRec encoding_table; /* PS_Table used to store the */
/* encoding character names */
FT_Int num_glyphs;
PS_TableRec glyph_names;
PS_TableRec charstrings;
} T42_LoaderRec, *T42_Loader;
FT_LOCAL( FT_Error )
t42_parser_init( T42_Parser parser,
FT_Stream stream,
FT_Memory memory,
PSAux_Service psaux );
FT_LOCAL( void )
t42_parser_done( T42_Parser parser );
FT_LOCAL( FT_Error )
t42_parse_dict( T42_Face face,
T42_Loader loader,
FT_Byte* base,
FT_Long size );
FT_LOCAL( void )
t42_loader_init( T42_Loader loader,
T42_Face face );
FT_LOCAL( void )
t42_loader_done( T42_Loader loader );
/* */
FT_END_HEADER
#endif /* __T42PARSE_H__ */
/* END */

View File

@ -0,0 +1,25 @@
/***************************************************************************/
/* */
/* type42.c */
/* */
/* FreeType Type 42 driver component. */
/* */
/* Copyright 2002 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. */
/* */
/***************************************************************************/
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include <ft2build.h>
#include "t42objs.c"
#include "t42parse.c"
#include "t42drivr.c"
/* END */

View File

@ -0,0 +1,10 @@
# FreeType 2 src/winfonts Jamfile (c) 2001 David Turner
#
SubDir FT2_TOP src winfonts ;
SubDirHdrs [ FT2_SubDir src winfonts ] ;
Library $(FT2_LIB) : winfnt.c ;
# end of src/winfonts Jamfile

View File

@ -0,0 +1,23 @@
#
# FreeType 2 Windows FNT/FON driver compilation rules for VMS
#
# Copyright 2001, 2002 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.
CFLAGS=$(COMP_FLAGS)$(DEBUG)/include=([--.include],[--.src.winfonts])
OBJS=winfnt.obj
all : $(OBJS)
library [--.lib]freetype.olb $(OBJS)
# EOF

View File

@ -0,0 +1,41 @@
/***************************************************************************/
/* */
/* fnterrs.h */
/* */
/* Win FNT/FON error codes (specification only). */
/* */
/* Copyright 2001 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. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* This file is used to define the Windows FNT/FON error enumeration */
/* constants. */
/* */
/*************************************************************************/
#ifndef __FNTERRS_H__
#define __FNTERRS_H__
#include FT_MODULE_ERRORS_H
#undef __FTERRORS_H__
#define FT_ERR_PREFIX FNT_Err_
#define FT_ERR_BASE FT_Mod_Err_Winfonts
#include FT_ERRORS_H
#endif /* __FNTERRS_H__ */
/* END */

View File

@ -0,0 +1,21 @@
#
# FreeType 2 Windows FNT/FON module definition
#
# Copyright 1996-2000 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.
make_module_list: add_windows_driver
add_windows_driver:
$(OPEN_DRIVER)winfnt_driver_class$(CLOSE_DRIVER)
$(ECHO_DRIVER)winfnt $(ECHO_DRIVER_DESC)Windows bitmap fonts with extension *.fnt or *.fon$(ECHO_DRIVER_DONE)

View File

@ -0,0 +1,65 @@
#
# FreeType 2 Windows FNT/FON driver configuration rules
#
# Copyright 1996-2000, 2001 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.
# Windows driver directory
#
FNT_DIR := $(SRC_)winfonts
FNT_DIR_ := $(FNT_DIR)$(SEP)
FNT_COMPILE := $(FT_COMPILE) $I$(FNT_DIR)
# Windows driver sources (i.e., C files)
#
FNT_DRV_SRC := $(FNT_DIR_)winfnt.c
# Windows driver headers
#
FNT_DRV_H := $(FNT_DRV_SRC:%.c=%.h) \
$(FNT_DIR_)fnterrs.h
# Windows driver object(s)
#
# FNT_DRV_OBJ_M is used during `multi' builds
# FNT_DRV_OBJ_S is used during `single' builds
#
FNT_DRV_OBJ_M := $(FNT_DRV_SRC:$(FNT_DIR_)%.c=$(OBJ_)%.$O)
FNT_DRV_OBJ_S := $(OBJ_)winfnt.$O
# Windows driver source file for single build
#
FNT_DRV_SRC_S := $(FNT_DIR_)winfnt.c
# Windows driver - single object
#
$(FNT_DRV_OBJ_S): $(FNT_DRV_SRC_S) $(FNT_DRV_SRC) $(FREETYPE_H) $(FNT_DRV_H)
$(FNT_COMPILE) $T$@ $(FNT_DRV_SRC_S)
# Windows driver - multiple objects
#
$(OBJ_)%.$O: $(FNT_DIR_)%.c $(FREETYPE_H) $(FNT_DRV_H)
$(FNT_COMPILE) $T$@ $<
# update main driver object lists
#
DRV_OBJS_S += $(FNT_DRV_OBJ_S)
DRV_OBJS_M += $(FNT_DRV_OBJ_M)
# EOF

View File

@ -0,0 +1,776 @@
/***************************************************************************/
/* */
/* winfnt.c */
/* */
/* FreeType font driver for Windows FNT/FON files */
/* */
/* Copyright 1996-2001, 2002 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 <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_FNT_TYPES_H
#include "winfnt.h"
#include "fnterrs.h"
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_winfnt
static
const FT_Frame_Field winmz_header_fields[] =
{
#undef FT_STRUCTURE
#define FT_STRUCTURE WinMZ_HeaderRec
FT_FRAME_START( 64 ),
FT_FRAME_USHORT_LE ( magic ),
FT_FRAME_SKIP_BYTES( 29 * 2 ),
FT_FRAME_ULONG_LE ( lfanew ),
FT_FRAME_END
};
static
const FT_Frame_Field winne_header_fields[] =
{
#undef FT_STRUCTURE
#define FT_STRUCTURE WinNE_HeaderRec
FT_FRAME_START( 40 ),
FT_FRAME_USHORT_LE ( magic ),
FT_FRAME_SKIP_BYTES( 34 ),
FT_FRAME_USHORT_LE ( resource_tab_offset ),
FT_FRAME_USHORT_LE ( rname_tab_offset ),
FT_FRAME_END
};
static
const FT_Frame_Field winfnt_header_fields[] =
{
#undef FT_STRUCTURE
#define FT_STRUCTURE WinFNT_HeaderRec
FT_FRAME_START( 134 ),
FT_FRAME_USHORT_LE( version ),
FT_FRAME_ULONG_LE ( file_size ),
FT_FRAME_BYTES ( copyright, 60 ),
FT_FRAME_USHORT_LE( file_type ),
FT_FRAME_USHORT_LE( nominal_point_size ),
FT_FRAME_USHORT_LE( vertical_resolution ),
FT_FRAME_USHORT_LE( horizontal_resolution ),
FT_FRAME_USHORT_LE( ascent ),
FT_FRAME_USHORT_LE( internal_leading ),
FT_FRAME_USHORT_LE( external_leading ),
FT_FRAME_BYTE ( italic ),
FT_FRAME_BYTE ( underline ),
FT_FRAME_BYTE ( strike_out ),
FT_FRAME_USHORT_LE( weight ),
FT_FRAME_BYTE ( charset ),
FT_FRAME_USHORT_LE( pixel_width ),
FT_FRAME_USHORT_LE( pixel_height ),
FT_FRAME_BYTE ( pitch_and_family ),
FT_FRAME_USHORT_LE( avg_width ),
FT_FRAME_USHORT_LE( max_width ),
FT_FRAME_BYTE ( first_char ),
FT_FRAME_BYTE ( last_char ),
FT_FRAME_BYTE ( default_char ),
FT_FRAME_BYTE ( break_char ),
FT_FRAME_USHORT_LE( bytes_per_row ),
FT_FRAME_ULONG_LE ( device_offset ),
FT_FRAME_ULONG_LE ( face_name_offset ),
FT_FRAME_ULONG_LE ( bits_pointer ),
FT_FRAME_ULONG_LE ( bits_offset ),
FT_FRAME_BYTE ( reserved ),
FT_FRAME_ULONG_LE ( flags ),
FT_FRAME_USHORT_LE( A_space ),
FT_FRAME_USHORT_LE( B_space ),
FT_FRAME_USHORT_LE( C_space ),
FT_FRAME_USHORT_LE( color_table_offset ),
FT_FRAME_BYTES ( reserved, 4 ),
FT_FRAME_END
};
static void
fnt_font_done( FNT_Font font,
FT_Stream stream )
{
if ( font->fnt_frame )
FT_FRAME_RELEASE( font->fnt_frame );
font->fnt_size = 0;
font->fnt_frame = 0;
}
static FT_Error
fnt_font_load( FNT_Font font,
FT_Stream stream )
{
FT_Error error;
WinFNT_Header header = &font->header;
/* first of all, read the FNT header */
if ( FT_STREAM_SEEK( font->offset ) ||
FT_STREAM_READ_FIELDS( winfnt_header_fields, header ) )
goto Exit;
/* check header */
if ( header->version != 0x200 &&
header->version != 0x300 )
{
FT_TRACE2(( "[not a valid FNT file]\n" ));
error = FNT_Err_Unknown_File_Format;
goto Exit;
}
if ( header->file_type & 1 )
{
FT_TRACE2(( "[can't handle vector FNT fonts]\n" ));
error = FNT_Err_Unknown_File_Format;
goto Exit;
}
/* small fixup -- some fonts have the `pixel_width' field set to 0 */
if ( header->pixel_width == 0 )
header->pixel_width = header->pixel_height;
/* this is a FNT file/table, we now extract its frame */
if ( FT_STREAM_SEEK( font->offset ) ||
FT_FRAME_EXTRACT( header->file_size, font->fnt_frame ) )
goto Exit;
Exit:
return error;
}
static void
fnt_face_done_fonts( FNT_Face face )
{
FT_Memory memory = FT_FACE( face )->memory;
FT_Stream stream = FT_FACE( face )->stream;
FNT_Font cur = face->fonts;
FNT_Font limit = cur + face->num_fonts;
for ( ; cur < limit; cur++ )
fnt_font_done( cur, stream );
FT_FREE( face->fonts );
face->num_fonts = 0;
}
static FT_Error
fnt_face_get_dll_fonts( FNT_Face face )
{
FT_Error error;
FT_Stream stream = FT_FACE( face )->stream;
FT_Memory memory = FT_FACE( face )->memory;
WinMZ_HeaderRec mz_header;
face->fonts = 0;
face->num_fonts = 0;
/* does it begin with a MZ header? */
if ( FT_STREAM_SEEK( 0 ) ||
FT_STREAM_READ_FIELDS( winmz_header_fields, &mz_header ) )
goto Exit;
error = FNT_Err_Unknown_File_Format;
if ( mz_header.magic == WINFNT_MZ_MAGIC )
{
/* yes, now look for a NE header in the file */
WinNE_HeaderRec ne_header;
if ( FT_STREAM_SEEK( mz_header.lfanew ) ||
FT_STREAM_READ_FIELDS( winne_header_fields, &ne_header ) )
goto Exit;
error = FNT_Err_Unknown_File_Format;
if ( ne_header.magic == WINFNT_NE_MAGIC )
{
/* good, now look in the resource table for each FNT resource */
FT_ULong res_offset = mz_header.lfanew +
ne_header.resource_tab_offset;
FT_UShort size_shift;
FT_UShort font_count = 0;
FT_ULong font_offset = 0;
if ( FT_STREAM_SEEK( res_offset ) ||
FT_FRAME_ENTER( ne_header.rname_tab_offset -
ne_header.resource_tab_offset ) )
goto Exit;
size_shift = FT_GET_USHORT_LE();
for (;;)
{
FT_UShort type_id, count;
type_id = FT_GET_USHORT_LE();
if ( !type_id )
break;
count = FT_GET_USHORT_LE();
if ( type_id == 0x8008 )
{
font_count = count;
font_offset = (FT_ULong)( FT_STREAM_POS() + 4 +
( stream->cursor - stream->limit ) );
break;
}
stream->cursor += 4 + count * 12;
}
FT_FRAME_EXIT();
if ( !font_count || !font_offset )
{
FT_TRACE2(( "this file doesn't contain any FNT resources!\n" ));
error = FNT_Err_Unknown_File_Format;
goto Exit;
}
if ( FT_STREAM_SEEK( font_offset ) ||
FT_NEW_ARRAY( face->fonts, font_count ) )
goto Exit;
face->num_fonts = font_count;
if ( FT_FRAME_ENTER( (FT_Long)font_count * 12 ) )
goto Exit;
/* now read the offset and position of each FNT font */
{
FNT_Font cur = face->fonts;
FNT_Font limit = cur + font_count;
for ( ; cur < limit; cur++ )
{
cur->offset = (FT_ULong)FT_GET_USHORT_LE() << size_shift;
cur->fnt_size = (FT_ULong)FT_GET_USHORT_LE() << size_shift;
cur->size_shift = size_shift;
stream->cursor += 8;
}
}
FT_FRAME_EXIT();
/* finally, try to load each font there */
{
FNT_Font cur = face->fonts;
FNT_Font limit = cur + font_count;
for ( ; cur < limit; cur++ )
{
error = fnt_font_load( cur, stream );
if ( error )
goto Fail;
}
}
}
}
Fail:
if ( error )
fnt_face_done_fonts( face );
Exit:
return error;
}
#ifdef FT_CONFIG_OPTION_USE_CMAPS
typedef struct FNT_CMapRec_
{
FT_CMapRec cmap;
FT_UInt32 first;
FT_UInt32 count;
} FNT_CMapRec, *FNT_CMap;
static FT_Error
fnt_cmap_init( FNT_CMap cmap )
{
FNT_Face face = (FNT_Face)FT_CMAP_FACE( cmap );
FNT_Font font = face->fonts;
cmap->first = (FT_UInt32) font->header.first_char;
cmap->count = (FT_UInt32)( font->header.last_char - cmap->first + 1 );
return 0;
}
static FT_UInt
fnt_cmap_char_index( FNT_CMap cmap,
FT_UInt32 char_code )
{
FT_UInt gindex = 0;
char_code -= cmap->first;
if ( char_code < cmap->count )
gindex = char_code + 1;
return gindex;
}
static FT_UInt
fnt_cmap_char_next( FNT_CMap cmap,
FT_UInt32 *pchar_code )
{
FT_UInt gindex = 0;
FT_UInt32 result = 0;
FT_UInt32 char_code = *pchar_code + 1;
if ( char_code <= cmap->first )
{
result = cmap->first;
gindex = 1;
}
else
{
char_code -= cmap->first;
if ( char_code < cmap->count )
{
result = cmap->first + char_code;
gindex = char_code + 1;
}
}
*pchar_code = result;
return gindex;
}
static FT_CMap_ClassRec fnt_cmap_class_rec =
{
sizeof ( FNT_CMapRec ),
(FT_CMap_InitFunc) fnt_cmap_init,
(FT_CMap_DoneFunc) NULL,
(FT_CMap_CharIndexFunc)fnt_cmap_char_index,
(FT_CMap_CharNextFunc) fnt_cmap_char_next
};
static FT_CMap_Class fnt_cmap_class = &fnt_cmap_class_rec;
#else /* !FT_CONFIG_OPTION_USE_CMAPS */
static FT_UInt
FNT_Get_Char_Index( FT_CharMap charmap,
FT_Long char_code )
{
FT_Long result = char_code;
if ( charmap )
{
FNT_Font font = ((FNT_Face)charmap->face)->fonts;
FT_Long first = font->header.first_char;
FT_Long count = font->header.last_char - first + 1;
char_code -= first;
if ( char_code < count )
result = char_code + 1;
else
result = 0;
}
return result;
}
static FT_Long
FNT_Get_Next_Char( FT_CharMap charmap,
FT_Long char_code )
{
char_code++;
if ( charmap )
{
FNT_Font font = ((FNT_Face)charmap->face)->fonts;
FT_Long first = font->header.first_char;
if ( char_code < first )
char_code = first;
if ( char_code <= font->header.last_char )
return char_code;
}
else
return char_code;
return 0;
}
#endif /* !FT_CONFIG_OPTION_USE_CMAPS */
static void
FNT_Face_Done( FNT_Face face )
{
FT_Memory memory = FT_FACE_MEMORY( face );
fnt_face_done_fonts( face );
FT_FREE( face->root.available_sizes );
face->root.num_fixed_sizes = 0;
}
static FT_Error
FNT_Face_Init( FT_Stream stream,
FNT_Face face,
FT_Int face_index,
FT_Int num_params,
FT_Parameter* params )
{
FT_Error error;
FT_Memory memory = FT_FACE_MEMORY( face );
FT_UNUSED( num_params );
FT_UNUSED( params );
FT_UNUSED( face_index );
/* try to load several fonts from a DLL */
error = fnt_face_get_dll_fonts( face );
if ( error )
{
/* this didn't work, now try to load a single FNT font */
FNT_Font font;
if ( FT_NEW( face->fonts ) )
goto Exit;
face->num_fonts = 1;
font = face->fonts;
font->offset = 0;
font->fnt_size = stream->size;
error = fnt_font_load( font, stream );
if ( error )
goto Fail;
}
/* all right, one or more fonts were loaded; we now need to */
/* fill the root FT_Face fields with relevant information */
{
FT_Face root = FT_FACE( face );
FNT_Font fonts = face->fonts;
FNT_Font limit = fonts + face->num_fonts;
FNT_Font cur;
root->num_faces = 1;
root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
FT_FACE_FLAG_HORIZONTAL;
if ( fonts->header.avg_width == fonts->header.max_width )
root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
if ( fonts->header.italic )
root->style_flags |= FT_STYLE_FLAG_ITALIC;
if ( fonts->header.weight >= 800 )
root->style_flags |= FT_STYLE_FLAG_BOLD;
/* Setup the `fixed_sizes' array */
if ( FT_NEW_ARRAY( root->available_sizes, face->num_fonts ) )
goto Fail;
root->num_fixed_sizes = face->num_fonts;
{
FT_Bitmap_Size* size = root->available_sizes;
for ( cur = fonts; cur < limit; cur++, size++ )
{
size->width = cur->header.pixel_width;
size->height = cur->header.pixel_height;
}
}
#ifdef FT_CONFIG_OPTION_USE_CMAPS
{
FT_CharMapRec charmap;
charmap.encoding = ft_encoding_unicode;
charmap.platform_id = 3;
charmap.encoding_id = 1;
charmap.face = root;
error = FT_CMap_New( fnt_cmap_class,
NULL,
&charmap,
NULL );
if ( error )
goto Fail;
/* Select default charmap */
if ( root->num_charmaps )
root->charmap = root->charmaps[0];
}
#else /* !FT_CONFIG_OPTION_USE_CMAPS */
/* Setup the `charmaps' array */
root->charmaps = &face->charmap_handle;
root->num_charmaps = 1;
face->charmap.encoding = ft_encoding_unicode;
face->charmap.platform_id = 3;
face->charmap.encoding_id = 1;
face->charmap.face = root;
face->charmap_handle = &face->charmap;
root->charmap = face->charmap_handle;
#endif /* !FT_CONFIG_OPTION_USE_CMAPS */
/* setup remaining flags */
root->num_glyphs = fonts->header.last_char -
fonts->header.first_char + 1;
root->family_name = (FT_String*)fonts->fnt_frame +
fonts->header.face_name_offset;
root->style_name = (char *)"Regular";
if ( root->style_flags & FT_STYLE_FLAG_BOLD )
{
if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
root->style_name = (char *)"Bold Italic";
else
root->style_name = (char *)"Bold";
}
else if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
root->style_name = (char *)"Italic";
}
Fail:
if ( error )
FNT_Face_Done( face );
Exit:
return error;
}
static FT_Error
FNT_Size_Set_Pixels( FNT_Size size )
{
/* look up a font corresponding to the current pixel size */
FNT_Face face = (FNT_Face)FT_SIZE_FACE( size );
FNT_Font cur = face->fonts;
FNT_Font limit = cur + face->num_fonts;
size->font = 0;
for ( ; cur < limit; cur++ )
{
/* we only compare the character height, as fonts used some strange */
/* values */
if ( cur->header.pixel_height == size->root.metrics.y_ppem )
{
size->font = cur;
size->root.metrics.ascender = cur->header.ascent * 64;
size->root.metrics.descender = ( cur->header.pixel_height -
cur->header.ascent ) * 64;
size->root.metrics.height = cur->header.pixel_height * 64;
break;
}
}
return ( size->font ? FNT_Err_Ok : FNT_Err_Invalid_Pixel_Size );
}
static FT_Error
FNT_Load_Glyph( FT_GlyphSlot slot,
FNT_Size size,
FT_UInt glyph_index,
FT_Int load_flags )
{
FNT_Font font = size->font;
FT_Error error = 0;
FT_Byte* p;
FT_Int len;
FT_Bitmap* bitmap = &slot->bitmap;
FT_ULong offset;
FT_Bool new_format;
FT_UNUSED( slot );
FT_UNUSED( load_flags );
if ( !font )
{
error = FNT_Err_Invalid_Argument;
goto Exit;
}
if ( glyph_index > 0 )
glyph_index--;
else
glyph_index = font->header.default_char - font->header.first_char;
new_format = FT_BOOL( font->header.version == 0x300 );
len = new_format ? 6 : 4;
/* jump to glyph entry */
p = font->fnt_frame + 118 + len * glyph_index;
bitmap->width = FT_NEXT_SHORT_LE( p );
if ( new_format )
offset = FT_NEXT_ULONG_LE( p );
else
offset = FT_NEXT_USHORT_LE( p );
/* jump to glyph data */
p = font->fnt_frame + /* font->header.bits_offset */ + offset;
/* allocate and build bitmap */
{
FT_Memory memory = FT_FACE_MEMORY( slot->face );
FT_Int pitch = ( bitmap->width + 7 ) >> 3;
FT_Byte* column;
FT_Byte* write;
bitmap->pitch = pitch;
bitmap->rows = font->header.pixel_height;
bitmap->pixel_mode = ft_pixel_mode_mono;
if ( FT_ALLOC( bitmap->buffer, pitch * bitmap->rows ) )
goto Exit;
column = (FT_Byte*)bitmap->buffer;
for ( ; pitch > 0; pitch--, column++ )
{
FT_Byte* limit = p + bitmap->rows;
for ( write = column; p < limit; p++, write += bitmap->pitch )
write[0] = p[0];
}
}
slot->flags = FT_GLYPH_OWN_BITMAP;
slot->bitmap_left = 0;
slot->bitmap_top = font->header.ascent;
slot->format = ft_glyph_format_bitmap;
/* now set up metrics */
slot->metrics.horiAdvance = bitmap->width << 6;
slot->metrics.horiBearingX = 0;
slot->metrics.horiBearingY = slot->bitmap_top << 6;
slot->linearHoriAdvance = (FT_Fixed)bitmap->width << 16;
slot->format = ft_glyph_format_bitmap;
Exit:
return error;
}
FT_CALLBACK_TABLE_DEF
const FT_Driver_ClassRec winfnt_driver_class =
{
{
ft_module_font_driver,
sizeof ( FT_DriverRec ),
"winfonts",
0x10000L,
0x20000L,
0,
(FT_Module_Constructor)0,
(FT_Module_Destructor) 0,
(FT_Module_Requester) 0
},
sizeof( FNT_FaceRec ),
sizeof( FNT_SizeRec ),
sizeof( FT_GlyphSlotRec ),
(FT_Face_InitFunc) FNT_Face_Init,
(FT_Face_DoneFunc) FNT_Face_Done,
(FT_Size_InitFunc) 0,
(FT_Size_DoneFunc) 0,
(FT_Slot_InitFunc) 0,
(FT_Slot_DoneFunc) 0,
(FT_Size_ResetPointsFunc) FNT_Size_Set_Pixels,
(FT_Size_ResetPixelsFunc) FNT_Size_Set_Pixels,
(FT_Slot_LoadFunc) FNT_Load_Glyph,
#ifdef FT_CONFIG_OPTION_USE_CMAPS
(FT_CharMap_CharIndexFunc)0,
#else
(FT_CharMap_CharIndexFunc)FNT_Get_Char_Index,
#endif
(FT_Face_GetKerningFunc) 0,
(FT_Face_AttachFunc) 0,
(FT_Face_GetAdvancesFunc) 0,
#ifdef FT_CONFIG_OPTION_USE_CMAPS
(FT_CharMap_CharNextFunc) 0
#else
(FT_CharMap_CharNextFunc) FNT_Get_Next_Char
#endif
};
/* END */

View File

@ -0,0 +1,39 @@
/***************************************************************************/
/* */
/* winfnt.h */
/* */
/* FreeType font driver for Windows FNT/FON files */
/* */
/* Copyright 1996-2001, 2002 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. */
/* */
/***************************************************************************/
#ifndef __WINFNT_H__
#define __WINFNT_H__
#include <ft2build.h>
#include FT_INTERNAL_DRIVER_H
FT_BEGIN_HEADER
FT_EXPORT_VAR( const FT_Driver_ClassRec ) winfnt_driver_class;
FT_END_HEADER
#endif /* __WINFNT_H__ */
/* END */