#ifndef GLOBAL_H
#define GLOBAL_H

/**
 * AMISH NOTE:
 * double is used everywhere instead of float
 * so the following is not necessary:
 * #define float double
 **/

#ifdef _IEEE
 #include <mieeedoub.h>
#else
 #ifdef _FFP
  #include <mffp.h>
 #else
  #define _MATHCXFERR
  #ifdef _M68881
   #include <m68881.h>
  #else
   #define _MATHEXCEPT
  #endif
 #endif
#endif

#include <math.h>

#ifdef DEBUG
// TetiSoft: Must be declared with __stdargs
//#include <clib/debug_protos.h>
__stdargs void kprintf(const char *formatString, ...);
__stdargs void kputs(const char *string);
#endif

#include "afm.h"		// TetiSoft
#include <string.h>
#include <diskfont/diskfont.h>
#include <diskfont/glyph.h>

// TetiSoft: OT_SymbolSet values
#define UNICODE			0x00005543	// "UC" - Unicode
#define STANDARDENCODING	0x00005053	// "PS" - PostScript Standard
#define CEENCODING		0x00004345	// "CE" - CodePage 1250 WinLatin2 = PostScript CE
#define WINCYRILLICENCODING	0x00005743	// "WC" - CodePage 1251 WinCyrillic
#define WINLATIN1ENCODING	0x00005731	// "W1" - CodePage 1252 WinLatin1
#define PSISOLATIN1ENCODING	0x0000504C	// "PL" - PostScript ISOLatin1
#define ISOLATIN1ENCODING	0x00004c31	// "L1" - ISO 8859-1  Latin 1
#define ISOLATIN2ENCODING	0x00004c32	// "L2" - ISO 8859-2  Latin 2
#define ISOLATIN3ENCODING	0x00004c33	// "L3" - ISO 8859-3  Latin 3
#define ISOLATIN4ENCODING	0x00004c34	// "L4" - ISO 8859-4  Latin 4
#define ISOCYRILLICENCODING	0x00004359	// "CY" - ISO 8859-5  Cyrillic
#define ISOARABICENCODING	0x00004152	// "AR" - ISO 8859-6  Arabic
#define ISOGREEKENCODING	0x00004752	// "GR" - ISO 8859-7  Greek
#define ISOHEBREWENCODING	0x00004845	// "HE" - ISO 8859-8  Hebrew
#define ISOLATIN5ENCODING	0x00004c35	// "L5" - ISO 8859-9  Latin 5
#define ISOLATIN6ENCODING	0x00004c36	// "L6" - ISO 8859-10 Latin 6
#define ISOTHAIENCODING		0x00005448	// "TH" - ISO 8859-11 Thai
#define ISOLATIN7ENCODING	0x00004c37	// "L7" - ISO 8859-13 Latin 7
#define ISOLATIN8ENCODING	0x00004c38	// "L8" - ISO 8859-14 Latin 8
#define ISOLATIN9ENCODING	0x00004c39	// "L9" - ISO 8859-15 Latin 9
#define KOI8RENCODING		0x00004b38	// "K8" - koi8r
#define E2ENCODING		0x00004532	// "E2" - E2
#define BUILTINENCODING		0x00005049	// "PI" - PostScript Internal

/**
 * amishmalloc.c
 **/

#ifdef MEMTRACE
#define xalloc(e, n) (Xalloc(e, (int)n, __FILE__, __FUNC__, __LINE__))
#define xfree(e, p) (Xfree(e, (char *)p, __FILE__, __FUNC__, __LINE__))
#else
#define xalloc(e, n) Xalloc (e, (int) n)
#define xfree(e, p) Xfree (e, (char *) p)
#endif

/*********
 * myfontstruct.h
 *********/

//typedef unsigned char *pointer;
typedef void *pointer;
typedef int Bool;

struct Type1Glyph {
	struct GlyphMap *glyphmap;
	unsigned long bitmapsize;
	int rendered_ok;
};


/*********
 * scanfont.c
 *********/

typedef struct
{
//	int index;
	unsigned short index;
	char *name;
}
EncodingTable;

extern const EncodingTable AGL[];

#define ENCSIZE   256


/*********
 * T1INTF.H
 *********/

// TetiSoft: There really exist PostScript fonts
// with encodings that define characters below 32...
// I hope nobody will use the zero!
// #define FIRSTCOL  32
#define FIRSTCOL  1
#define LASTCOL   255
#define NUMCOLS   (LASTCOL - FIRSTCOL + 1)

struct type1font
{
	struct Type1Glyph glyphs[NUMCOLS];
};

/*********
 * amishfontrequest.h
 *********/

struct FontRequest
{
	ULONG GlyphCode;
	ULONG GlyphCode2;	// TetiSoft

	ULONG DeviceXDPI;
	ULONG DeviceYDPI;
	ULONG PointHeight;
#ifdef SETFACTOR		// TetiSoft: Not implemented
	ULONG SetFactor;
	ULONG PointSet;
#endif
	ULONG IsFixed;		// TetiSoft
	LONG  FixedWidth;	// TetiSoft
	LONG  FixedWidthPixels;	// TetiSoft
	LONG  SpaceWidth;	// TetiSoft
	LONG  GlyphWidth;	// TetiSoft
	LONG  GlyphWidthPixels;	// TetiSoft
	ULONG SymbolSet;	// TetiSoft
	T1_AFM *AFM;		// TetiSoft
	double RotateSin;
	double RotateCos;
	double ShearSin;
	double ShearCos;

	ULONG FontDone;
	BOOL transformchanged;

	char FontFileName[MAXFONTPATH];
//	char OTagFileName[MAXFONTPATH];	// TetiSoft: Unused
	char AFMFileName[MAXFONTPATH];
};

/*********
 * fontxlfd.h
 *********/

typedef struct _FontScalable
{
	int pixel, point, x, y;
	double pixel_matrix[4];
	double ShearSin, ShearCos, RotateSin, RotateCos;
	int IsFixed, FixedWidth, FixedWidthPixels;		// TetiSoft
	int GlyphWidth, GlyphWidthPixels;			// TetiSoft
	ULONG SymbolSet;					// TetiSoft
//	int width;						// TetiSoft: Unused
//	double point_matrix[4];					// TetiSoft: Unused
#ifdef SETFACTOR						// TetiSoft: Not implemented
	int pixel_set;
#endif
//	int point_set;						// TetiSoft: Unused
//	int horiz_weight, vert_weight;				// TetiSoft: Unused
//	Bool horiz_mirror, vert_mirror;				// TetiSoft: Unused
}
FontScalableRec, *FontScalablePtr;

/*********
 * t1stdio.H
 *********/

typedef struct F_FILE
{
	unsigned char *fbuf;
	int fbuflen;
	int curpos;
} F_FILE;

#ifndef EOF
#define EOF (-1)		/* end of file */
#endif

/*********
 * UTIL.H
 *********/

#ifndef boolean
typedef int boolean;
#endif

#ifndef TRUE
#define TRUE (1)
#endif

#ifndef FALSE
#define FALSE (0)
#endif

/***================================================================***/
/* Portable definitions for 2's complement machines.
 * NOTE: These really should be based on PostScript types,
 * for example, sizeof(ps_integer), or sizeof(ps_unsigned)
 */
#define MAX_ULONG             (~(unsigned long)(0))
/* This code is portable, assuming K&R C and 2's complement arithmetic */
#define MAX_INTEGER      \
     ((long)((((unsigned long) 1)<<(sizeof(unsigned long)*8-1))-1))
#define MIN_INTEGER           ((-MAX_INTEGER)-1)

#define MAX_ARRAY_CNT         (65535)
#define MAX_DICT_CNT          (65535)
#define MAX_STRING_LEN        (65535)
#define MAX_NAME_LEN          (128)

/* this is the size of memory allocated for reading fonts */

#define VM_SIZE               (50*1024)
/***================================================================***/

#ifndef MIN
#define   MIN(a,b)   (((a)<(b)) ? a : b )
#endif

/***================================================================***/
/*  Macros for managing virtual memory                                */
/***================================================================***/
#define vm_next_byte(e)  (e->vm_next)
#define vm_free_bytes(e) (e->vm_free)
#define vm_avail(e,B)    (B <= e->vm_free)



/***================================================================***/
/* Types of PostScript objects */
/***================================================================***/
#define OBJ_INTEGER    (0)
#define OBJ_REAL       (1)
#define OBJ_BOOLEAN    (2)
#define OBJ_ARRAY      (3)
#define OBJ_STRING     (4)
#define OBJ_NAME       (5)
#define OBJ_FILE       (6)
#define OBJ_ENCODING   (7)

/***================================================================***/
/* Value of PostScript objects */
/***================================================================***/
typedef union ps_value
{
	char *valueP;		/* value pointer for unspecified type */
	int value;		/* value for unspecified type         */
	int integer;		/* when type is OBJ_INTEGER           */
	double real;		/* when type is OBJ_REAL              */
	int boolean;		/* when type is OBJ_BOOLEAN           */
	struct ps_obj *arrayP;	/* when type is OBJ_ARRAY             */
	unsigned char *stringP;	/* when type is OBJ_STRING            */
	const char *nameP;	/* when type is OBJ_NAME              */
	F_FILE *fileP;		/* when type is OBJ_FILE              */
}
psvalue;

/***================================================================***/
/* Definition of a PostScript object */
/***================================================================***/
typedef struct ps_obj
{
	char type;
	char unused;
	unsigned short len;
	union ps_value data;
} psobj;

/***================================================================***/
/*     Definition of a PostScript Dictionary Entry */
/***================================================================***/
typedef struct ps_dict
{
	psobj key;
	psobj value;
} psdict;

/***================================================================***/
/* Macros for testing type of PostScript objects */
/***================================================================***/
#define objIsInteger(o)          ((o).type == OBJ_INTEGER)
#define objIsReal(o)             ((o).type == OBJ_REAL)
#define objIsBoolean(o)          ((o).type == OBJ_BOOLEAN)
#define objIsArray(o)            ((o).type == OBJ_ARRAY)
#define objIsString(o)           ((o).type == OBJ_STRING)
#define objIsName(o)             ((o).type == OBJ_NAME)
#define objIsFile(o)             ((o).type == OBJ_FILE)

/***================================================================***/
/* Macros for setting type of PostScript objects */
/***================================================================***/
#define objSetInteger(o)         ((o).type = OBJ_INTEGER)
#define objSetReal(o)            ((o).type = OBJ_REAL)
#define objSetBoolean(o)         ((o).type = OBJ_BOOLEAN)
#define objSetArray(o)           ((o).type = OBJ_ARRAY)
#define objSetString(o)          ((o).type = OBJ_STRING)
#define objSetName(o)            ((o).type = OBJ_NAME)
#define objSetFile(o)            ((o).type = OBJ_FILE)

/***================================================================***/
/* Macros for testing type of PostScript objects (pointer access) */
/***================================================================***/
#define objPIsInteger(o)         ((o)->type == OBJ_INTEGER)
#define objPIsReal(o)            ((o)->type == OBJ_REAL)
#define objPIsBoolean(o)         ((o)->type == OBJ_BOOLEAN)
#define objPIsArray(o)           ((o)->type == OBJ_ARRAY)
#define objPIsString(o)          ((o)->type == OBJ_STRING)
#define objPIsName(o)            ((o)->type == OBJ_NAME)
#define objPIsFile(o)            ((o)->type == OBJ_FILE)

/***================================================================***/
/* Macros for setting type of PostScript objects (pointer access) */
/***================================================================***/
#define objPSetInteger(o)        ((o)->type = OBJ_INTEGER)
#define objPSetReal(o)           ((o)->type = OBJ_REAL)
#define objPSetBoolean(o)        ((o)->type = OBJ_BOOLEAN)
#define objPSetArray(o)          ((o)->type = OBJ_ARRAY)
#define objPSetString(o)         ((o)->type = OBJ_STRING)
#define objPSetName(o)           ((o)->type = OBJ_NAME)
#define objPSetFile(o)           ((o)->type = OBJ_FILE)

/*********
 * BLUES.H
 *********/

#define TOPLEFT 1
#define BOTTOMRIGHT 2

#define NUMBLUEVALUES 14
#define NUMOTHERBLUES 10
#define NUMFAMILYBLUES 14
#define NUMFAMILYOTHERBLUES 10
#define NUMSTEMSNAPH 12
#define NUMSTEMSNAPV 12
#define NUMSTDHW 1
#define NUMSTDVW 1

#define DEFAULTBOLDSTEMWIDTH 2.0

#define MAXALIGNMENTZONES ((NUMBLUEVALUES+NUMOTHERBLUES)/2)
#define DEFAULTBLUESCALE 0.039625
#define DEFAULTBLUESHIFT 7
#define DEFAULTBLUEFUZZ 1
#define DEFAULTSTDHW 0
#define DEFAULTSTDVW 0
#define DEFAULTFORCEBOLD FALSE
#define DEFAULTLANGUAGEGROUP 0
#define DEFAULTRNDSTEMUP FALSE
#define DEFAULTLENIV 4
#define DEFAULTEXPANSIONFACTOR 0.06

/* see Type 1 Font Format book for explanations of these values */
/* Note that we're currently doing nothing for minfeature and password. */
struct blues_struct
{
	struct blues_struct *next;	/* ptr to next Blues structure in list */
	int numBlueValues;	/* # of BlueValues in following array */
	int BlueValues[NUMBLUEVALUES];
	int numOtherBlues;	/* # of OtherBlues values in following array */
	int OtherBlues[NUMOTHERBLUES];
	int numFamilyBlues;	/* # of FamilyBlues values in following array */
	int FamilyBlues[NUMFAMILYBLUES];
	int numFamilyOtherBlues;/* # of FamilyOtherBlues values in  */
	int FamilyOtherBlues[NUMFAMILYOTHERBLUES];	/* this array */
	double BlueScale;
	int BlueShift;
	int BlueFuzz;
	double StdHW;
	double StdVW;
	int numStemSnapH;	/* # of StemSnapH values in following array */
	double StemSnapH[NUMSTEMSNAPH];
	int numStemSnapV;	/* # of StemSnapV values in following array */
	double StemSnapV[NUMSTEMSNAPV];
	int ForceBold;
	int LanguageGroup;
	int RndStemUp;
	int lenIV;
	double ExpansionFactor;
};

/* the alignment zone structure -- somewhat similar to the stem structure */
/* see Adobe Type1 Font Format book about the terms used in this structure */
struct alignmentzone
{
	int topzone;		/* TRUE if a topzone, FALSE if a bottom zone */
	double bottomy, topy;	/* interval of this alignment zone */
};

/*********
 * CURVES.H
 *********/

#define   FlattenConic(xM,yM,xC,yC,r)        t1_StepConic(NULL,(fractpel)0,(fractpel)0,xM,yM,xC,yC,r)
#define   FlattenBezier(xB,yB,xC,yC,xD,yD)   t1_StepBezier(NULL,(fractpel)0,(fractpel)0,xB,yB,xC,yC,xD,yD)

/*********
 * FONTFCN.H
 *********/

/*     Definition of a PostScript FONT             */
typedef struct ps_font
{
	char *vm_start;
	psobj FontFileName;
	psobj Subrs;
	psdict *CharStringsP;
	psdict *Private;
	psdict *fontInfoP;
	struct blues_struct *BluesP;
} psfont;

/***================================================================***/
/*  Return codes from scan_font                                       */
/***================================================================***/
#define SCAN_OK               0
#define SCAN_FILE_EOF        -1
#define SCAN_ERROR           -2
#define SCAN_OUT_OF_MEMORY   -3
#define SCAN_FILE_OPEN_ERROR -4
#define SCAN_TRUE            -5
#define SCAN_FALSE           -6
#define SCAN_END             -7

/***================================================================***/
/*  Name of FontInfo fields                                           */
/***================================================================***/

#define FONTNAME 1
#define PAINTTYPE 2
#define FONTTYPENUM 3
#define FONTMATRIX 4
#define FONTBBOX   5
#define UNIQUEID  6
#define STROKEWIDTH  7
#define VERSION     8
#define NOTICE     9
#define FULLNAME 10
#define FAMILYNAME 11
#define WEIGHT 12
#define ITALICANGLE 13
#define ISFIXEDPITCH  14
#define UNDERLINEPOSITION 15
#define UNDERLINETHICKNESS 16
#define ENCODING 17
/***================================================================***/
/*  Name of Private values                                            */
/***================================================================***/
#define BLUEVALUES 1
#define OTHERBLUES 2
#define FAMILYBLUES 3
#define FAMILYOTHERBLUES 4
#define BLUESCALE 5
#define BLUESHIFT 6
#define BLUEFUZZ  7
#define STDHW     8
#define STDVW     9
#define STEMSNAPH 10
#define STEMSNAPV 11
#define FORCEBOLD 12
#define LANGUAGEGROUP 13
#define LENIV     14
#define RNDSTEMUP 15
#define EXPANSIONFACTOR 16

/*********
 * OBJECTS.H
 *********/

#define   ON          (~0)	/* all bits on                                  */
#ifndef MAX
#define   MAX(a,b)    (((a)>(b)) ? a : b)
#endif
#ifndef ABS
#define   ABS(a)      (((a)>=0)?(a):-(a))
#endif
#ifndef NULL
#define NULL 0L
#endif


/*
 * Basic TYPE1IMAGER Object Structure
 *
 * All TYPE1IMAGER objects which are available to the user have a common
 * header.  This header is defined below:
 */
struct xobject
{
	char type;		/* encoded type of object                         */
	unsigned char flag;	/* flag byte for temporary object characteristics */
	short references;	/* count of pointers to this object (plus 1 for permanent) PNM */
};


/*
 * The following define is an attempt to centralize the definition of the
 * common xobject data shared by structures that are derived from the
 * generic xobject structure. For example, the structure font, defined in
 * fonts.shr :
 *     struct font {
 *            char type;
 *            char flag;
 *            int references;
 *            ... other data types & structs ...
 *            }
 *
 * would now be defined as:
 *     struct font {
 *            XOBJ_COMMON
 *            ... other data types & structs ...
 *            }
 *
 * Thus we have a better-structured inheritance mechanism. 3-26-91 PNM
 */
#define XOBJ_COMMON      char type; unsigned char flag; short references;


/*
 * Object Type Definitions
 *
 * These constants define the values which go in the 'type' field of
 * an TYPE1IMAGER object structure:
 */
#define   INVALIDTYPE    0
//#define   FONTTYPE       1	// TetiSoft: Unused
#define   REGIONTYPE     3
//#define   PICTURETYPE    4	// TetiSoft: Unused
#define   SPACETYPE      5
//#define   LINESTYLETYPE  6	// TetiSoft: Unused
#define   EDGETYPE       7
//#define   STROKEPATHTYPE 8	// TetiSoft: Unused
//#define   CLUTTYPE       9	// TetiSoft: Unused


/*
 * Flag Byte Definitions
 *
 * Many programmers define flag bits as a mask (for example, 0x04), and
 * test, set, and reset them as follows:
 *         if ((flag & PERMANENT) != 0)
 *         flag |= PERMANENT;
 *         flag &= &inv.PERMANENT;
 *
 * I favor a style where the 'if' statement can ask a question:
 *         if (ISPERMANENT(flag))
 *         flag |= ISPERMANENT(ON);
 *         flag &= &inv.ISPERMANENT(ON);
 *
 * This said, we now define two bit settings of the flag byte of the
 * object.  "ISPERMANENT" will be set by the user, when he calls
 * Permanent().  "ISIMMORTAL" will be used for compiled-in objects
 * that we don't want the user to ever destroy.
 */
/*
 * Flag bit definitions that apply to all objects are assigned
 * starting with the least significant (0x01) bit.  Flag bit definitions
 * specific to a certain object type are assigned starting with the
 * most significant (0x80) bit.  We hope they never meet.
 */
#define   ISPATHTYPE(type)    ((type)&0x10)	/* all path segments have this bit on */
#define   LINETYPE    (0+ISPATHTYPE(ON))
#define   CONICTYPE   (1+ISPATHTYPE(ON))
#define   BEZIERTYPE  (2+ISPATHTYPE(ON))
#define   HINTTYPE    (3+ISPATHTYPE(ON))

#define   MOVETYPE    (5+ISPATHTYPE(ON))
//#define   TEXTTYPE    (6+ISPATHTYPE(ON))	// TetiSoft: Unused


#define   ISPERMANENT(flag)   ((flag)&0x01)
#define   ISIMMORTAL(flag)    ((flag)&0x02)


/*
 * PRESERVE() Macro
 *
 * Occasionally an TYPE1IMAGER operator is implemented by calling other
 * TYPE1IMAGER operators.  For example, Arc2() calls Conic().  When we
 * call more than one operator as a subroutine, we have to be careful
 * of temporary objects.  A temporary object will be consumed by the
 * subroutine operator and then is no longer available for the caller.
 * This can be prevented simply by bumping a temporary object's reference
 * count.
 */
#define   PRESERVE(obj)   if (!ISPERMANENT((obj)->flag)) \
   (obj)->references++;


/*
 * TYPE1IMAGER Object Functions
 *
 * LONGCOPY() - Macro to Copy "long" Aligned Data
 *
 * Copying arbitrary bytes in C is a bit of a problem.  "strcpy" can't be
 * used, because 0 bytes are special-cased.  Most environments have a
 * routine "memcopy" or "bcopy" or "bytecopy" that copies memory containing
 * zero bytes.  Sadly, there is no standard on the name of such a routine,
 * which makes it impossible to write truely portable code to use it.
 *
 * It turns out that TYPE1IMAGER, when it wants to copy data, frequently
 * knows that both the source and destination are aligned on "long"
 * boundaries.  This allows us to copy by using "long *" pointers.  This
 * is usually very efficient on almost all processors.  Frequently, it
 * is more efficient than using general-purpose assembly language routines.
 * So, we define a macro to do this in a portable way.  "dest" and "source"
 * must be long-aligned, and "bytes" must be a multiple of "sizeof(long)":
 */
#define  LONGCOPY(dest,source,bytes) { \
    register long *p1 = (long *)dest;  register long *p2 = (long *)source; \
    register int count = (bytes) / sizeof(long); \
    while (--count >= 0) *p1++ = *p2++; }


/*
 * FOLLOWING() - Macro to Point to the Data Following a Structure
 *
 * There are several places in TYPE1IMAGER where we will allocate variable
 * data that belongs to a structure immediately after that structure.
 * This is a performance technique, because it reduces the number of
 * trips we have to take through xiMalloc() and xiFree().  It turns out C has
 * a very convenient way to point past a structure--if 'p' is a pointer
 * to a structure, 'p+1' is a pointer to the data after it.  This
 * behavior of C is somewhat startling and somewhat hard to follow, if
 * you are not used to it, so we define a macro to point to the data
 * following a structure:
 */
#define   FOLLOWING(p)  ((p)+1)


/*
 * TYPECHECK() - Verify the Type of an Argument
 *
 * This macro tests the type of an argument.  If the test fails, it consumes
 * any other arguments as necessary and causes the imbedding routine to
 * return the value 'whenBAD'.
 *
 * Note that the consumeables list should be an argument list itself, for
 * example (0) or (2,A,B).  See :hdref refid=consume. below.
 */
#define  TYPECHECK(e, name, obj, expect, whenBAD, consumables, rettype) { \
    if (obj->type != expect) { \
         (Consume)consumables; \
         return((rettype)t1_TypeErr(e, name, (struct xobject *)obj, expect, (struct xobject *)whenBAD)); \
    } \
}


/*
 * ARGCHECK() - Perform an Arbitrary Check on an Argument
 *
 * This macro is a generalization of TYPECHECK to take an arbitrary
 * predicate.  If the error occurs (i.e., the predicate is true), the
 * arbitrary message 'msg' is returned.
 */
#define  ARGCHECK(test,msg,obj,whenBAD,consumables,rettype) { \
    if (test) { \
        (Consume)consumables; \
        return((rettype)t1_ArgErr(msg, (struct xobject *)obj, (struct xobject *)whenBAD)); \
    } \
}


/*
 * TYPENULLCHECK() - Extension of TYPECHECK() for NULL arguments
 *
 * Many routines allow NULLs to be passed as arguments.  'whenBAD' will
 * be returned in this case, too.
 */
/* Changed use of Dup() below to Temporary(Copy()) because Dup() does not
   necessarily return a Unique Copy anymore! 3-26-91 */
#define  TYPENULLCHECK(name, obj, expect, whenBAD, consumables,rettype) \
    if (obj == NULL) { \
        (Consume)consumables; \
        if (whenBAD != NULL && ISPERMANENT(whenBAD->flag)) \
              return((rettype)Temporary(Copy(whenBAD))); \
        else  return((rettype)whenBAD); \
    } else { \
        if (obj->type != expect) { \
             (Consume)consumables; \
             return((rettype)t1_TypeErr(name, (struct xobject *)obj, expect, (struct xobject *)whenBAD)); \
        } \
    }


/*
 * MAKECONSUME() - Create a "Consume"-type Macro
 *
 * Consuming an object means destroying it if it is not permanent.  This
 * logic is so common to all the routines, that it is immortalized in this
 * macro.  For example, ConsumePath(p) can be simply defined as
 * MAKECONSUME(p,KillPath(p)).  In effect, this macro operates on a
 * meta-level.
 */
#define  MAKECONSUME(obj,stmt)  { if (!ISPERMANENT(obj->flag)) stmt; }


/*
 * MAKEUNIQUE() - Create a "Unique"-type Macro
 *
 * Many routines are written to modify their arguments in place.  Thus,
 * they want to insure that they duplicate an object if it is permanent.
 * This is called making an object "unique".  For example, UniquePath(p)
 * can be simply defined as MAKEUNIQUE(p,DupPath(p)).
 */
#define MAKEUNIQUE(obj,stmt) ( ( (obj)->references > 1 ) ? stmt : obj )

#ifndef DEBUG	// TetiSoft
#define IfTrace0(condition,model)
#define IfTrace1(condition,model,arg0)
#define IfTrace2(condition,model,arg0,arg1)
#define IfTrace3(condition,model,arg0,arg1,arg2)
#define IfTrace4(condition,model,arg0,arg1,arg2,arg3)
#define IfTrace5(condition,model,arg0,arg1,arg2,arg3,arg4)
#define IfTrace6(condition,model,arg0,arg1,arg2,arg3,arg4,arg5)
#else
#define IfTrace0(condition,model)				{if(condition) kputs(model);}
#define IfTrace1(condition,model,arg0)				{if(condition) kprintf(model,arg0);}
#define IfTrace2(condition,model,arg0,arg1)			{if(condition) kprintf(model,arg0,arg1);}
#define IfTrace3(condition,model,arg0,arg1,arg2)		{if(condition) kprintf(model,arg0,arg1,arg2);}
#define IfTrace4(condition,model,arg0,arg1,arg2,arg3)		{if(condition) kprintf(model,arg0,arg1,arg2,arg3);}
#define IfTrace5(condition,model,arg0,arg1,arg2,arg3,arg4)	{if(condition) kprintf(model,arg0,arg1,arg2,arg3,arg4);}
#define IfTrace6(condition,model,arg0,arg1,arg2,arg3,arg4,arg5)	{if(condition) kprintf(model,arg0,arg1,arg2,arg3,arg4,arg5);}
#endif	// TetiSoft


/*********
 * SPACES.H
 *********/

/*
 * Macros and Typedefs Provided to Other Modules
 *
 * Duplicating and Killing Spaces
 *
 * Destroying XYspaces is so simple we can do it with a
 * macro:
 */
/*
 * #define    KillSpace(s)     Free(s)
 * Note - redefined KillSpace() to check references !
 * 3-26-91 PNM
 */
#define KillSpace(e, s)  if ( (--(s->references) == 0) ||\
                      ( (s->references == 1) && ISPERMANENT(s->flag) ) )\
                        t1_Free(e, (struct xobject *)s)

#define    ConsumeSpace(e, s)  MAKECONSUME(s,KillSpace(e, s))
#define    UniqueSpace(s)   MAKEUNIQUE(s,CopySpace(s))

/*
 * On the other hand, duplicating XYspaces is slightly more difficult
 * because of the need to keep a unique ID in the space.
 *
 * Fixed Point Pel Representation
 *
 * We represent pel positions with fixed point numbers.  This does NOT
 * mean integer, but truly means fixed point, with a certain number
 * of binary digits (FRACTBITS) representing the fractional part of the
 * pel.
 */
typedef short pel;			/* integer pel locations                        */
typedef long fractpel;		/* fractional pel locations                     */

#define   FRACTBITS     16	/* number of fractional bits in 'fractpel'      */


/*
 * We define the following macros to convert from 'fractpel' to 'pel' and
 * vice versa:
 */
#define   TOFRACTPEL(p)   (((fractpel)p)<<FRACTBITS)
#define   FPHALF          (1<<(FRACTBITS-1))
#define   NEARESTPEL(fp)  (((fp)+FPHALF)>>FRACTBITS)
#define   FRACTFLOAT   (double)(1L<<FRACTBITS)


/*
 * Data Structures for Coordinate Spaces and Points
 */

/*
 * Matrices
 *
 * TYPE1IMAGER uses 2x2 transformation matrices.  We'll use C notation for
 * such a matrix (M[2][2]), the first index being rows, the second columns.
 */

/*
 * The "doublematrix" Structure
 *
 * We frequently find it desirable to store both a matrix and its
 * inverse.  We store these in a "doublematrix" structure.
 */
struct doublematrix
{
	double normal[2][2];
	double inverse[2][2];
};

/*
 * The "XYspace" Structure
 *
 * The XYspace structure represents the XYspace object.
 */
struct XYspace
{
	XOBJ_COMMON				/* xobject common data define 3-26-91 PNM */
						/* type = SPACETYPE */

	void (*convert) (struct fractpoint *pt, struct XYspace *S, double x, double y);
						/* calculate "fractpoint" X,Y from double X,Y */

	void (*iconvert) (struct fractpoint *pt, struct XYspace *S, long x, long y);
						/* calculate "fractpoint" X,Y from int X,Y */

	fractpel (*xconvert) (double cx, double cy, double x, double y);
						/* subroutine of convert */

	fractpel (*yconvert) (double cx, double cy, double x, double y);
						/* subroutine of convert */

	fractpel (*ixconvert) (fractpel cx, fractpel cy, long x, long y);
						/* subroutine of iconvert */

	fractpel (*iyconvert) (fractpel cx, fractpel cy, long x, long y);
						/* subroutine of iconvert */

	int ID;					/* unique identifier (used in font caching) */
	unsigned char context;			/* device context of coordinate space */
	struct doublematrix tofract;		/* xform to get to fractional pels */
	fractpel itofract[2][2];		/* integer version of "tofract.normal" */
};

#define    INVALIDID  0		/* no valid space will have this ID             */

/*
 * The "fractpoint" Structure
 *
 * A fractional point is just a "fractpel" x and y:
 */
struct fractpoint
{
	fractpel x, y;
};

#define  NULLCONTEXT   0

/*********
 * HINTS.C
 * moved here from hints.c to deal with oldHint global variable
 * declaration in HINTS.c (by moving into globals.c)
 *********/

#define MAXLABEL 20
struct oldhintstruct
{
	int inuse;
	int computed;
	struct fractpoint hint;
};

/*********
 * PATHS.H
 *********/

#define    ConsumePath(e,p)    MAKECONSUME(p,t1_KillPath(e,p))
#define    UniquePath(e,p)     MAKEUNIQUE(p,t1_CopyPath(e,p))

struct segment
{
	XOBJ_COMMON		/* xobject common data define 3-26-91 PNM             */
	unsigned char size;	/* size of the structure                        */
	unsigned char context;	/* index to device context                    */
	struct segment *link;	/* pointer to next structure in linked list     */
	struct segment *last;	/* pointer to last structure in list            */
	struct fractpoint dest;	/* relative ending location of path segment   */
};

#define   ISCLOSED(flag)   ((flag)&0x80)	/* subpath is closed               */
#define   LASTCLOSED(flag) ((flag)&0x40)	/* last segment in closed subpath  */

/*
NOTE: The ISCLOSED flag is set on the MOVETYPE segment before the
subpath proper; the LASTCLOSED flag is set on the last segment (LINETYPE)
in the subpath

We define the ISPATHANCHOR predicate to test that a path handle
passed by the user is valid:
*/

#define   ISPATHANCHOR(p)  (ISPATHTYPE(p->type)&&p->last!=NULL)

/*
For performance reasons, a user's "location" object is identical to
a path whose only segment is a move segment.  We define a predicate
to test for this case.  See also :hdref refid=location..
*/

#define   ISLOCATION(p)    ((p)->type == MOVETYPE && (p)->link == NULL)

struct conicsegment
{
	XOBJ_COMMON		/* xobject common data define 3-26-91 PNM        */
	/* type = CONICTYPE			             */
	unsigned char size;	/* as with any 'segment' type                   */
	unsigned char context;	/* as with any 'segment' type                 */
	struct segment *link;	/* as with any 'segment' type                   */
	struct segment *last;	/* as with any 'segment' type                   */
	struct fractpoint dest;	/* Ending point (C point)                    */
	struct fractpoint M;	/* "midpoint" of conic explained above          */
	double roundness;	/* explained above                              */
};

struct beziersegment
{
	XOBJ_COMMON		/* xobject common data define 3-26-91 PNM       */
	/* type = BEZIERTYPE		             */
	unsigned char size;	/* as with any 'segment' type                   */
	unsigned char context;	/* as with any 'segment' type                 */
	struct segment *link;	/* as with any 'segment' type                   */
	struct segment *last;	/* as with any 'segment' type                   */
	struct fractpoint dest;	/* ending point (D)                          */
	struct fractpoint B;	/* control point B                              */
	struct fractpoint C;	/* control point C                              */
};

struct hintsegment
{
	XOBJ_COMMON		/* xobject common data define 3-26-91 PNM      */
	/* type = HINTTYPE			     */
	unsigned char size;	/* size of the structure                        */
	unsigned char context;	/* device context                             */
	struct segment *link;	/* pointer to next structure in linked list     */
	struct segment *last;	/* pointer to last structure in list            */
	struct fractpoint dest;	/* ALWAYS 0,0                                 */
	struct fractpoint ref;
	struct fractpoint width;
	char orientation;
	char hinttype;
	char adjusttype;
	char direction;
	int label;
};

/*
CONCAT links the 'p2' path chain on the end of the 'p1' chain.  (This macro
is also used by the STROKES module.)
*/
#define  CONCAT(p1, p2)  { \
       p1->last->link = p2;     /* link p2 on end of p1                      */ \
       p1->last = p2->last;    /* last of new is last of p2                  */ \
       p2->last = NULL; }	/* only first segment has non-NULL "last"       */

/*********
 * PICTURES.H
 *********/

#define      BegHandle(o,m)         o
#define	     EndHandle(o,m)         o

/*********
 * REGIONS.H
 *********/

/*
 * GOING_TO() - Macro Predicate Needed for Changing Direction, Etc.
 *
 * The actual generation of run end lists (edge boundaries) is left
 * to the low level rasterizing modules, LINES and CURVES.  There
 * are some global region-type
 * questions that occur when doing a low-level
 * rasterization:
 *
 * Did we just change direction in Y and therefore need to start
 * a new edge?
 * Did we run out of allocated edge space?
 * Do the minimum or maximum X values for the current edge need
 * updating?
 *
 * In general the REGIONS is not smart enough to answer those questions
 * itself.  (For example, determining if and when a curve changes direction
 * may need detailed curve knowledge.)  Yet, this must be done efficiently.
 * We provide a macro "GOING_TO" where the invoker tells us where it is
 * heading for (x2,y2), plus where it is now (x1,y1), plus the current
 * region under construction, and the macro answers the questions above.
 */
#define GOING_TO(e, R, x1, y1, x2, y2, dy) { \
   if (dy < 0) { \
      if (R->lastdy >= 0) \
          ChangeDirection(e, CD_CONTINUE, R, x1, y1, dy); \
      if (y2 < R->edgeYstop) \
          MoreWorkArea(e, R, x1, y1, x2, y2); \
   } \
   else if (dy > 0) { \
      if (R->lastdy <= 0) \
          ChangeDirection(e, CD_CONTINUE, R, x1, y1, dy); \
      if (y2 > R->edgeYstop) \
          MoreWorkArea(e, R, x1, y1, x2, y2); \
   } \
   else /* dy == 0 */ ChangeDirection(e, CD_CONTINUE, R, x1, y1, dy); \
   if (x2 < R->edgexmin) R->edgexmin = x2; \
   else if (x2 > R->edgexmax) R->edgexmax = x2; \
}

#include <limits.h>
#ifdef SHRT_MIN
#define MINPEL SHRT_MIN
#else
#define MINPEL ((pel)(-1<<(8*sizeof(pel)-1)))  /* smallest value fitting in a pel */
#endif
#ifdef SHRT_MAX
#define MAXPEL SHRT_MAX
#else
#define MAXPEL ((pel)((1<<(8*sizeof(pel)-1))-1))/* largest value fitting in a pel */
#endif


/*
 * The "Unique"-type macro is different (unique?) for regions, because some
 * regions structures are shared among several objects, and might have
 * to be made unique for that reason (i.e., references > 1).
 */
#define    ConsumeRegion(R)   MAKECONSUME(R,t1_KillRegion(R))
#define    UniqueRegion(e,R)  MAKEUNIQUE(R,t1_CopyRegion(e, R))


/*
 * The "region" Structure
 *
 * The region structure is an anchor for a linked list of "edgelist"
 * structures (see :hdref refid=edgelist..).  It also summarizes the
 * information in the edgelist structures (for example, the bounding
 * box of the region).  And, it contains scratch areas used during
 * the creation of a region.
 */
struct region
{
	XOBJ_COMMON						/* xobject common data define 3-26-91 PNM    */
									/* type = REGIONTYPE                         */
	struct fractpoint origin;		/* beginning handle:  X,Y origin of region      */
	struct fractpoint ending;		/* ending handle:  X,Y change after painting region */
	pel xmin, ymin;					/* minimum X,Y of region                        */
	pel xmax, ymax;					/* maximum X,Y of region                        */
	struct edgelist *anchor;		/* list of edges that bound the region      */

	/*
	 * Note that the ending handle and the bounding box values are stored
	 * relative to 'origin'.
	 *
	 * The above elements describe a region.  The following elements are
	 * scratchpad areas used while the region is being built:
	 */
	fractpel lastdy;				/* direction of last segment */
	fractpel firstx, firsty;			/* starting point of current edge */
	fractpel edgexmin, edgexmax;			/* x extent of current edge */
	struct edgelist *lastedge;
	struct edgelist *firstedge;			/* last and first edges in subpath */
	pel *edge;					/* pointer to array of X values for edge */
	fractpel edgeYstop;				/* Y value where 'edges' array ends */
//	void (*newedgefcn) (struct region *,
	int (*newedgefcn) (struct T1GlyphEngine *engine,	// TetiSoft
			struct region *R,
			fractpel xmin, fractpel xmax,
			fractpel ymin, fractpel ymax, int isdown);			/* function to use when building a new edge */
};


/*
 * The ISCOMPLEMENT flag indicates the region is reversed--it is the
 * "outside" of the nominal region.
 */
#define   ISCOMPLEMENT(flag)   ((flag)&0x80)


/*
 * The ISJUMBLED flag indicates the region is not sorted top-to-bottom.
 */
#define   ISJUMBLED(flag)      ((flag)&0x40)


/*
 * The ISINFINITE flag allows a quick check for an INFINITE region, which
 * is frequently intersected.
 */
#define   ISINFINITE(flag)     ((flag)&0x20)


/*
 * The ISRECTANGULAR flag tells us if a region is a rectangle.  We don't
 * always notice rectangles--if this flag is set, the region definitely
 * is a rectangle, but some rectangular regions will not have the flag
 * set.  The flag is used to optimize some paths.
 */
#define   ISRECTANGULAR(flag)  ((flag)&0x08)


/*
 * The "edgelist" Structure
 *
 * Regions are represented by a linked list of 'edgelist' structures.
 * When a region is complete, the structures are paired, one for the
 * left and one for the right edge.  While a region is being built,
 * this rule may be violated temporarily.
 *
 * An 'edgelist' structure contains the X values for a given span
 * of Y values.  The (X,Y) pairs define an edge.  We use the crack
 * and edge coordinate system, so that integer values of X and Y
 * go between pels.  The edge is defined between the minimum Y and
 * maximum Y.
 *
 * The linked list is kept sorted from top to bottom, that is, in
 * increasing y.  Also, if 'e1' is an edgelist structure and 'e2' is the
 * next one in the list, they must have exactly the same ymin,ymax values
 * or be totally disjoint.  These two requirements mean that if e2's ymin
 * is less than e1's ymax, it must be exactly equal to e1's ymin.  A
 * sublist of structures with identical ymin and ymax values is called a
 * 'swath'.
 *
 * In addition, edgelist structures are separately linked together based
 * on what subpath originally created them; each subpath is kept as a
 * separate circular linked list.  This information is ignored unless
 * continuity checking is invoked.  See subpath for a
 * complete description of this.
 */
struct edgelist
{
	XOBJ_COMMON					/* xobject common data define 3-26-91 PNM */
								/* type = EDGETYPE */
	struct edgelist *link;		/* pointer to next in linked list */
	struct edgelist *subpath;	/* informational link for "same subpath" */
	pel xmin, xmax;				/* range of edge in X */
	pel ymin, ymax;				/* range of edge in Y */
	pel *xvalues;				/* pointer to ymax-ymin X values */
};


/*
 * The end of the list is marked by either "link" being NULL, or by
 * ymin == ymax.  We define the VALIDEDGE
 * predicate to test for the opposite of these conditions:
 */
#define   VALIDEDGE(p)    ((p)!=NULL&&(p)->ymin<(p)->ymax)


/*
 * The "edgelist" structure follows the convention of TYPE1IMAGER user
 * objects, having a type field and a flag field as the first two
 * elements.  However, the user never sees "edgelist" structures
 * directly; he is given handles to "region" structures only.
 *
 * By having a type field, we can use the "copy" feature of Allocate()
 * to duplicate edge lists quickly.
 *
 * We also define two flag bits for this structure.  The ISDOWN bit is set
 * if the edge is going in the direction of increasing Y. The ISAMBIGUOUS
 * bit is set if the edge is identical to its neighbor (edge->link); such
 * edges may be "left" when they should be "right", or vice versa,
 * unnecessarily confusing the continuity checking logic.  The FixSubPaths()
 * routine in HINTS will swap ambiguous edges if that avoids crossing edges;
 * see fixsubp.
 */
#define   ISDOWN(f)       ((f)&0x80)
#define   ISAMBIGUOUS(f)  ((f)&0x40)


/*
 * Interior() rule enumerations:
 */
#define   WINDINGRULE -2
#define   EVENODDRULE -3

#define   CONTINUITY  0x80	/* can be added to above rules; e.g. WINDINGRULE+CONTINUITY */

#define   CD_FIRST         -1	/* enumeration of ChangeDirection type       */
#define   CD_CONTINUE       0	/* enumeration of ChangeDirection type        */
#define   CD_LAST           1	/* enumeration of ChangeDirection type        */

/*********
 * T1IMAGER.H
 *********/

typedef pointer xobject;
typedef pointer location;
typedef pointer path;
typedef pointer region;
typedef pointer XYspace;

#define   WINDINGRULE -2
#define   EVENODDRULE -3

#define   CONTINUITY  0x80	/* can be added to above rules; e.g. WINDINGRULE+CONTINUITY */

/*
 * Generic null object definition:
 */
#define    NULLOBJECT   ((xobject)NULL)

/*
 * Null path definition:
 */
#define    NULLPATH     NULLOBJECT

#define    NULLREGION   NULLOBJECT

#define    FF_PARSE_ERROR  5
#define    FF_PATH         1


/*********
 * TOKEN.H
 *********/

/* Special characters */
#define CONTROL_C           (3)

/* Token type codes */
#define TOKEN_INVALID       (-3)
#define TOKEN_BREAK         (-2)
#define TOKEN_EOF           (-1)
#define TOKEN_NONE          (0)
#define TOKEN_LEFT_PAREN    (1)
#define TOKEN_RIGHT_PAREN   (2)
#define TOKEN_LEFT_ANGLE    (3)
#define TOKEN_RIGHT_ANGLE   (4)
#define TOKEN_LEFT_BRACE    (5)
#define TOKEN_RIGHT_BRACE   (6)
#define TOKEN_LEFT_BRACKET  (7)
#define TOKEN_RIGHT_BRACKET (8)
#define TOKEN_NAME          (9)
#define TOKEN_LITERAL_NAME  (10)
#define TOKEN_INTEGER       (11)
#define TOKEN_REAL          (12)
#define TOKEN_RADIX_NUMBER  (13)
#define TOKEN_HEX_STRING    (14)
#define TOKEN_STRING        (15)
#define TOKEN_IMMED_NAME    (16)


/*********
 * type1.c
 *********/

/*******************/
/* Type1 Constants */
/*******************/
#define MAXSTACK 24		/* Adobe Type1 limit */
#define MAXCALLSTACK 10		/* Adobe Type1 limit */
#define MAXPSFAKESTACK 32	/* Max depth of fake PostScript stack (local) */
#define MAXSTRLEN 512		/* Max length of a Type 1 string (local) */
//#define MAXLABEL 256		/* Maximum number of new hints */
#define MAXSTEMS 128		/* Maximum number of VSTEM and HSTEM hints */
#define EPS 0.001		/* Small number for comparisons */

struct callstackentry
{
	psobj *currstrP;	/* current CharStringP */
	int currindex;		/* current strindex */
	unsigned short currkey;	/* current decryption key */
};

struct stem
{										/* representation of a STEM hint */
	int vertical;						/* TRUE if vertical, FALSE otherwise */
	double x, dx;						/* interval of vertical stem */
	double y, dy;						/* interval of horizontal stem */
	struct segment *lbhint, *lbrevhint;	/* left  or bottom hint adjustment */
	struct segment *rthint, *rtrevhint;	/* right or top    hint adjustment */
};

// TetiSoft: struct to hold type1.c statics to avoid global data
struct type1c_statics
{
	double escapementX, escapementY;
	double sidebearingX, sidebearingY;
	double accentoffsetX, accentoffsetY;

	struct segment *path;

	int errflag;

	psfont *Environment;
	struct XYspace *CharSpace;
	psobj *CharStringP, *SubrsP;
//	psobj *OtherSubrsP;		// TetiSoft: Unused
//	int *ModeP;			// TetiSoft: Unused
	struct segment *FlxOldPath;	/* save path before Flex feature */


	struct blues_struct *blues;	/* the blues structure */
	struct alignmentzone alignmentzones[MAXALIGNMENTZONES];
	int numalignmentzones;		/* total number of alignment zones */

	int InDotSection;		/* DotSection flag */
	struct stem stems[MAXSTEMS];	/* All STEM hints */
	int numstems;			/* Number of STEM hints */
	int currstartstem;		/* The current starting stem. */
	int oldvert, oldhor;		/* Remember hint in effect */
	int oldhorhalf, oldverthalf;	/* Remember which half of the stem */
	double wsoffsetX, wsoffsetY;	/* White space offset - for VSTEM3,HSTEM3 */
	int wsset;			/* Flag for whether we've set wsoffsetX,Y */

	int strindex;		/* index into PostScript string being interpreted */
	double currx, curry;	/* accumulated x and y values for hints */

	double Stack[MAXSTACK];
	int Top;
	struct callstackentry CallStack[MAXCALLSTACK];
	int CallTop;
	double PSFakeStack[MAXPSFAKESTACK];
	int PSFakeTop;

	unsigned short r;	/* Pseudo-random sequence of keys */
};


// TetiSoft: Placed most globals in GlyphEngine, otherwise only one font
// per Library base (instead of one font per GlyphEngine) is possible.
/*********************
 *** T1GlyphEngine ***
 *********************/

struct T1GlyphEngine
{
	struct GlyphEngine GE;
	struct FontRequest fontreq;
	void *WidthListPool;
	psobj *fontencoding;
	psobj *StdEncArrayP;
	psobj *PSISOLatin1EncArrayP;
	psobj *CEEncArrayP;
	psobj *ISO1Latin1EncArrayP;
	psobj *ISO2Latin2EncArrayP;
	psobj *ISO3Latin3EncArrayP;
	psobj *ISO4Latin4EncArrayP;
	psobj *ISO5CyrillicEncArrayP;
	psobj *ISO6ArabicEncArrayP;
	psobj *ISO7GreekEncArrayP;
	psobj *ISO8HebrewEncArrayP;
	psobj *ISO9Latin5EncArrayP;
	psobj *ISO10Latin6EncArrayP;
	psobj *ISO11ThaiEncArrayP;
	psobj *ISO13Latin7EncArrayP;
	psobj *ISO14Latin8EncArrayP;
	psobj *ISO15Latin9EncArrayP;
	psobj *WinLatin1EncArrayP;
	psobj *WinCyrillicEncArrayP;
	psobj *koi8rEncArrayP;
	psobj *E2EncArrayP;
	ULONG Has_Builtin_Encoding;
	long VMusage1, VMusage2;
	FontScalableRec vals;

	struct type1font *type1fontptr;
	struct XYspace *XYS;	/* coordinate space for character */

	struct XYspace *IDENTITY;
	struct XYspace identity;

	psfont *FontP;

	void *AmishPool;
	void *AmishPool2;

	char *vm_base;		/* Start of virtual memory area */
	char *vm_next;		/* Pointer to first free byte */
	long vm_free;		/* Count of free bytes */
	long vm_size;		/* Total size of memory */

	/* These variables are set by the caller */
	char *tokenStartP;	/* Pointer to token buffer in VM */
	char *tokenMaxP;	/* Pointer to end of VM we may use + 1 */
	/* These variables are set by P_TOKEN */
	int tokenLength;	/* Characters in token */
	boolean tokenTooLong;	/* Token too long for space available */
	int tokenType;		/* Type of token identified */
	psvalue tokenValue;	/* Token value */
	F_FILE *token_inputFileP; /* Current input file */
	char *tokenCharP;	/* Pointer to next character in token */
	/* decimal integer or real number mantissa */
	int token_m_sign;
	long token_m_value;
	long token_m_scale;
	/* real number exponent */
	int token_e_sign;
	long token_e_value;
	long token_e_scale;
	/* radix number */
	long token_r_base;
	long token_r_value;
	long token_r_scale;

#define  MAXCONTEXTS   16
	unsigned int SpaceID;
	struct doublematrix contexts[MAXCONTEXTS];

	char CurFontName[MAXFONTPATH];
	psfont TheCurrentFont;
	int readFontrc;

	struct oldhintstruct oldHint[MAXLABEL];

	int scanfont_rc;

#ifndef   MAXEDGE
#define   MAXEDGE     1000
#endif
	pel regions_workedge[MAXEDGE];
	pel *regions_currentworkarea;
	pel regions_currentsize;

	struct type1c_statics t1;

	char ProcessHints;
	char Continuity;
#ifdef DEBUG
	char LineDebug;
	char RegionDebug;
	char PathDebug;
	char FontDebug;
	char HintDebug;
	char OffPageDebug;
	char MustTraceCalls;
#endif
};

/**********************
 ***** Prototypes *****
 **********************/

/**
 * arith.c
 **/
fractpel FPmult(fractpel u, fractpel v);


/**
 * curves.c
 **/
struct segment *StepBezier(struct T1GlyphEngine *engine, struct region *R, fractpel xA, fractpel yA, fractpel xB, fractpel yB, fractpel xC, fractpel yC, fractpel xD, fractpel yD);


/**
 * fontfcn.c
 **/
int SearchDictName(psdict *dictP, psobj *keyP);
xobject fontfcnB(struct T1GlyphEngine *engine, struct XYspace *S, unsigned char *code, int *lenP, int *mode);
Bool fontfcnA(struct T1GlyphEngine *engine, char *env, int *mode);
void QueryFontLib(struct T1GlyphEngine *engine, char *env, char *infoName, pointer infoValue, int *rcodeP);


/**
 * hints.c
 **/
void InitHints(struct T1GlyphEngine *engine);
void CloseHints(struct T1GlyphEngine *engine, struct fractpoint *hintP);
void t1_ProcessHint(struct T1GlyphEngine *engine, struct hintsegment *hP, fractpel currX, fractpel currY, struct fractpoint *hintP);
void ApplyContinuity(struct T1GlyphEngine *engine, struct region *R);


/**
 * lines.c
 **/
void t1_StepLine(struct T1GlyphEngine *engine, struct region *R, fractpel x1, fractpel y1, fractpel x2, fractpel y2);


/**
 * t1objects.c
 **/
struct xobject *t1_Permanent(struct T1GlyphEngine *engine, struct xobject *obj);
struct xobject *t1_Destroy(struct T1GlyphEngine *engine, struct xobject *obj);
struct xobject *t1_Dup(struct T1GlyphEngine *engine, struct xobject *obj);
#ifdef PRAGMATICS
void Pragmatics(char *username, int value);
#endif
struct xobject *t1_Allocate(struct T1GlyphEngine *engine, int size, struct xobject *template, int extra);
void t1_Free(struct T1GlyphEngine *engine, struct xobject *obj);
void Consume(struct T1GlyphEngine *engine, int n, struct xobject *obj1, struct xobject *obj2, struct xobject *obj3);
struct xobject *t1_ArgErr(char *string, struct xobject *obj, struct xobject *ret);
struct xobject *t1_TypeErr(struct T1GlyphEngine *engine, char *name, struct xobject *obj, int expect, struct xobject *ret);
struct xobject *t1_Unique(struct T1GlyphEngine *engine, struct xobject *obj);


/**
 * paths.c
 **/
struct segment *t1_Loc(struct T1GlyphEngine *engine, struct XYspace *S, double x, double y);
struct segment *ILoc(struct T1GlyphEngine *engine, struct XYspace *S, int x, int y);
struct segment *Line(struct T1GlyphEngine *engine, struct segment *P);
struct segment *t1_Join(struct T1GlyphEngine *engine, struct segment *p1, struct segment *p2);
struct segment *t1_ClosePath(struct T1GlyphEngine *engine, struct segment *p0, int lastonly);
struct beziersegment *Bezier(struct T1GlyphEngine *engine, struct segment *B,	struct segment *C, struct segment *D);
#ifdef EXPERIMENT
struct hintsegment *Hint(struct T1GlyphEngine *engine, struct XYspace *S, double ref, double width, char orientation, char hinttype, char adjusttype, char direction, int label);
#endif
void QueryLoc(struct T1GlyphEngine *engine, struct segment *P, struct XYspace *S, double *xP, double *yP);

struct segment *t1_CopyPath(struct T1GlyphEngine *engine, struct segment *p0);
void t1_KillPath(struct T1GlyphEngine *engine, struct segment *p);
struct segment *PathTransform(struct T1GlyphEngine *engine, struct segment *p0, struct XYspace *S);
void t1_PathDelta(struct segment *p, struct fractpoint *pt);
struct segment *t1_PathSegment(struct T1GlyphEngine *engine, int type, fractpel x, fractpel y);
struct segment *t1_JoinSegment(struct T1GlyphEngine *engine, struct segment *before, int type, fractpel x, fractpel y, struct segment *after);
struct segment *BoxPath(struct T1GlyphEngine *engine, struct XYspace *S, int h, int w);
#ifdef PATHDEBUG
void t1_DumpPath(struct segment * p);
#endif

/**
 * regions.c
 **/
struct region *Interior(struct T1GlyphEngine *engine, struct segment *p, int fillrule);
void MoreWorkArea(struct T1GlyphEngine *engine, struct region *R, fractpel x1, fractpel y1, fractpel x2, fractpel y2);
void t1_KillRegion(struct T1GlyphEngine *engine, struct region *area);
struct region *t1_CopyRegion(struct T1GlyphEngine *engine, struct region *area);
struct segment *t1_RegionBounds(struct T1GlyphEngine *engine, struct region *R);
//void ChangeDirection(int type, struct region *R, fractpel x, fractpel y, fractpel dy);
int ChangeDirection(struct T1GlyphEngine *engine, int type, struct region *R, fractpel x, fractpel y, fractpel dy);	// TetiSoft
#ifdef DEBUG
void DumpArea(struct T1GlyphEngine *engine, struct region *area);
void DumpEdges(struct T1GlyphEngine *engine, struct edgelist *edges);
#endif

/**
 * scanfont.c
 **/

boolean Init_BuiltInEncoding(struct T1GlyphEngine *engine);
psobj *GetType1CharString(struct T1GlyphEngine *engine, psfont *fontP, unsigned char code);
int scan_font(struct T1GlyphEngine *engine, psfont *fontP);
int setencoding(struct T1GlyphEngine *engine, ULONG SymbolSet);	// TetiSoft

/**
 * spaces.c
 **/
struct XYspace *t1_CopySpace(struct T1GlyphEngine *engine, struct XYspace *S);
//int FindDeviceContext(pointer device);							// TetiSoft: now static
//int FindContext(double M[2][2]);								// TetiSoft: now static
//struct XYspace *Context(pointer device, double units);					// TetiSoft: now static
void UnConvert(struct XYspace *S, struct fractpoint *pt, double *xp, double *yp);
//struct xobject *t1_Xform(struct xobject *obj, double M[2][2]);				// TetiSoft: now static
struct XYspace *t1_Transform(struct T1GlyphEngine *engine, struct XYspace *obj, double cxx, double cyx, double cxy, double cyy);
//struct xobject *t1_Scale(struct xobject *obj, double sx, double sy);				// TetiSoft: now static
//struct xobject *xiRotate(struct xobject *obj, double degrees);				// TetiSoft: now static
//void PseudoSpace(struct XYspace *S, double M[2][2]);						// TetiSoft: now static
//void MatrixMultiply(double A[2][2], double B[2][2], double C[2][2]);				// TetiSoft: now static
//void MatrixInvert(double M[2][2], double Mprime[2][2]);					// TetiSoft: now static
void t1_InitSpaces(struct T1GlyphEngine *engine);
void QuerySpace(struct T1GlyphEngine *engine, struct XYspace *S, double *cxxP, double *cyxP, double *cxyP, double *cyyP);


/**
 * amisht1funcs.c
 **/
int MyType1OpenScalable(struct T1GlyphEngine *engine);
int MyType1SetTransform(struct T1GlyphEngine *engine);
//int MyType1GetGlyphs(struct T1GlyphEngine *engine, int i, struct _CharInfo **returnglyph);
int GetType1GlyphMap(struct T1GlyphEngine *engine, unsigned long GlyphCode, struct GlyphMap **gm_p);
void MyType1CloseFont(struct T1GlyphEngine *engine);


/**
 * amishio.c
 **/
F_FILE *T1Open(struct T1GlyphEngine *engine, char *fn);
int T1Getc(F_FILE *f);
int T1Ungetc(int c, F_FILE *f);
int T1Read(char *buffP, int size, int n, F_FILE *f);
int T1Close(struct T1GlyphEngine *engine, F_FILE *f);
void __asm T1eexec(register __a0 F_FILE *f);
void T1eexecASCII(F_FILE *f);


/**
 * amisht1malloc.c
 **/
void xiFree(struct T1GlyphEngine *engine, void *addr);
char *xiMalloc(struct T1GlyphEngine *engine, unsigned int size);
void *addmemory(struct T1GlyphEngine *engine, long size);
void delmemory(struct T1GlyphEngine *engine);

void *addmemory2(struct T1GlyphEngine *engine, long size);
void delmemory2(struct T1GlyphEngine *engine);
char *Xalloc(struct T1GlyphEngine *engine, int size);
void Xfree(struct T1GlyphEngine *engine, char *p);


/**
 * t1snap.c
 **/
struct segment *t1_Phantom(struct T1GlyphEngine *engine, struct xobject *obj);
struct xobject *t1_Snap(struct T1GlyphEngine *engine, struct segment *p);


/**
 * token.c
 **/
void scan_token(struct T1GlyphEngine *engine, psobj *inputP);


/**
 * type1.c
 **/
struct xobject *Type1Char(struct T1GlyphEngine *engine, psfont *env, struct XYspace *S, psobj *charstrP, psobj *subrsP, /* psobj *osubrsP,*/ struct blues_struct *bluesP /*, int *modeP*/);	// TetiSoft


/**
 * util.c
 **/
boolean vm_init(struct T1GlyphEngine *engine, int cnt);
void free_vm(struct T1GlyphEngine *engine);
char *vm_alloc(struct T1GlyphEngine *engine, int bytes);
void objFormatInteger(psobj *objP, int value);
void objFormatReal(psobj *objP, double value);
void objFormatBoolean(psobj *objP, boolean value);
void objFormatEncoding(psobj *objP, int length, psobj *valueP);
void objFormatArray(psobj *objP, int length, psobj *valueP);
void objFormatString(psobj *objP, int length, char *valueP);
void objFormatName(psobj *objP, int length, char *valueP);
void objFormatFile(psobj *objP, F_FILE *valueP);


/**
 * readfont.c
 **/
int readfont(char *filename, char **pfbuf, int *pfbuflen);
void freefont(char *fbuf);

/**
 * type1interface.c
 **/

void *OpenType1Engine(struct T1GlyphEngine *engine);
void CloseType1Engine(struct T1GlyphEngine *engine);
int ReadType1Font(struct T1GlyphEngine *engine);
int MyQueryFontLib(struct T1GlyphEngine *engine, char *env, pointer dest);
int SetTransformType1Font(struct T1GlyphEngine *engine);
void FatalError(char *line);

#endif
