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


#ifdef MATHIEEE
#include <mieeedoub.h>
#endif

#ifdef MATH881
#include <m68881.h>
#endif

#ifdef MATHSTANDARD
#include <math.h>
#endif

#include <string.h>

#include "myfontstruct.h"
#include "fontfilest.h"

extern int _FPERR;
void __stdargs _CXFERR(int code);


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

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


/* defines for flags */
#define UNGOTTENC (0x01)
#define FIOEOF    (0x80)
#define FIOERROR  (0x40)

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

#define F_BUFSIZ (512)


#define T1getc(f)			T1Getc(f)
#define T1ungetc(c,f)		T1Ungetc(c,f)
#define T1fgetc(f)			T1Getc(f)
#define T1fread(a,b,c,d)	T1Read(a,b,c,d)


/*********
 * 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

/***================================================================***/
/*  Routines for managing virtual memory                              */
/***================================================================***/
extern long vm_free;
extern long vm_size;
extern char *vm_next;

/***================================================================***/
/*  Macros for managing virtual memory                                */
/***================================================================***/
#define vm_next_byte()  (vm_next)
#define vm_free_bytes()  (vm_free)
#define vm_avail(B)     (B <= 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 */
};


/*********
 * CLUTS.H
 *********/

#define   KillCLUT(T)
#define   CopyCLUT(T)                T
#define   UniqueCLUT(T)


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

#define   StepConic(R,xA,yA,xB,yB,xC,yC,r)      t1_StepConic(R,xA,yA,xB,yB,xC,yC,r)
#define   StepBezier(R,xA,yA,xB,yB,xC,yC,xD,yD) t1_StepBezier(R,xA,yA,xB,yB,xC,yC,xD,yD)

#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


/*********
 * FONTS.H
 *********/

#define   CopyFont(f)     f
#define   UniqueFont(f)   f
#define   KillFont(f)
#define   KillText(t)
#define   CopyText(t)     t
#define   I_DumpText(t)
#define   CoerceText(t)   t
#define   TextDelta(t,pt)
#define   XformText(p,s)
#define   GimeSpace()     FALSE

#define   TraceClose()


/*********
 * HINTS.H
 *********/

#define   CloseHints(hintP)   t1_CloseHints(hintP)
#define   ProcessHint(hP, currX, currY, hintP)   t1_ProcessHint((struct hintsegment *)hP, currX, currY, hintP)
#define   ApplyContinuity(R)  t1_ApplyContinuity(R)


/*********
 * LINES.H
 *********/

#define   StepLine(R,x1,y1,x2,y2)   t1_StepLine(R,x1,y1,x2,y2)
#define   Bresenham(e,x1,y1,x2,y2)  t1_Bresenham(e,x1,y1,x2,y2)


/*********
 * OBJECTS.H
 *********/
#define   ON          (~0)	/* all bits on                                  */
#ifndef FALSE
#define   FALSE       0		/* handy zero value                             */
#endif
#ifndef TRUE
#define   TRUE        1		/* handy non-zero value                         */
#endif
#ifndef MIN
#define   MIN(a,b)    (((a)<(b)) ? a : b)
#endif
#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
#define   REGIONTYPE     3
#define   PICTURETYPE    4
#define   SPACETYPE      5
#define   LINESTYLETYPE  6
#define   EDGETYPE       7
#define   STROKEPATHTYPE 8
#define   CLUTTYPE       9

/*
 * 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))


#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(name, obj, expect, whenBAD, consumables, rettype) { \
    if (obj->type != expect) { \
         (Consume)consumables; \
         return((rettype)t1_TypeErr(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)ArgErr(msg, obj, 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 )

#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)


void Trace0();
char *Trace1(), *Trace2(), *Trace3(), *Trace4(), *Trace5(), *Trace6();

extern char MustCheckArgs;
extern char MustTraceCalls;
extern char MustCrash;
extern char InternalTrace;
extern char LineIOTrace;

extern char ProcessHints;

extern char SaveFontPaths;

extern short CRASTERCompressionType;

extern char ConicDebug;
extern char LineDebug;
extern char RegionDebug;
extern char PathDebug;
extern char FontDebug;
extern char SpaceDebug;
extern char StrokeDebug;
extern char MemoryDebug;
extern char HintDebug;
extern char ImageDebug;
extern char OffPageDebug;

extern short CachedChars;
extern short CachedFonts;
extern int CacheBLimit;
extern char Continuity;

/*
We define other routines formatting parameters
*/
#define    DumpArea(area)    t1_DumpArea(area)
#define    DumpText(text)    t1_DumpText(text)
#define    DumpEdges(e)      t1_DumpEdges(e)

#define   Permanent(obj)    t1_Permanent((struct xobject *)obj)
#define   Temporary(obj)    t1_Temporary(obj)
#define   Destroy(obj)      t1_Destroy((struct xobject *)obj)
#define   Dup(obj)          t1_Dup((struct xobject *)obj)
#define   Pragmatics(f,v)   t1_Pragmatics(f,v)

#define   Allocate(n,t,s)   t1_Allocate(n,(struct xobject *)t,s)
#define   Free(obj)         t1_Free((struct xobject *)obj)
#define   NonObjectFree(a)  xiFree(a)
#define   Consume           t1_Consume
#define   ArgErr(s,o,r)     t1_ArgErr(s,(struct xobject *)o,(struct xobject *)r)
#define   TypeErr(n,o,e,r)  t1_TypeErr(n,(struct xobject *)o,e,(struct xobject *)r)
#define   Copy(obj)         t1_Copy(obj)
#define   Unique(obj)       t1_Unique((struct xobject *)obj)


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

#define   USER                       t1_User

#define   Context(d,u)               t1_Context(d,u)
#define   Rotate(o,d)                xiRotate((struct object *)o,d)
#define   Scale(o,sx,sy)             t1_Scale((struct xobject *)o,sx,sy)
#define   QuerySpace(S,f1,f2,f3,f4)  t1_QuerySpace(S,f1,f2,f3,f4)
#define   Warp(s1,o,s2)              t1_Warp(s1,o,s2)
#define   DeviceResolution           t1_DeviceResolution
#define   CopySpace(s)               t1_CopySpace((struct XYspace *)s)
#define   Xform(o,M)                 t1_Xform(o,M)
#define   UnConvert(S,pt,xp,yp)      t1_UnConvert(S,pt,xp,yp)
#define   MatrixMultiply(A,B,C)      t1_MMultiply(A,B,C)
#define   MatrixInvert(A,B)          t1_MInvert(A,B)
#define   PseudoSpace(S,M)           t1_PseudoSpace(S,M)
#define   FindContext(M)             t1_FindContext(M)

/*
 * 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(s)  if ( (--(s->references) == 0) ||\
                      ( (s->references == 1) && ISPERMANENT(s->flag) ) )\
                        Free(s)

#define    ConsumeSpace(s)  MAKECONSUME(s,KillSpace(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 __stdargs (*convert) (struct fractpoint *pt, struct XYspace *S, double x, double y);
						/* calculate "fractpoint" X,Y from double X,Y */

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

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

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

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

	fractpel __stdargs (*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(p)    MAKECONSUME(p,KillPath(p))
#define    UniquePath(p)     MAKEUNIQUE(p,CopyPath(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"       */

#define   Loc(S,x,y)                   t1_Loc(S,(double)x,(double)y)
#define   ILoc(S,x,y)                  t1_ILoc(S,x,y)
#define   Line(P)                      t1_Line(P)
#define   Join(p1,p2)                  t1_Join((struct segment *)p1,(struct segment *)p2)
#define   ClosePath(p)                 t1_ClosePath(p,0)
#define   CloseLastSubPath(p)          t1_ClosePath(p,1)
#define   Conic(B,C,s)                 t1_Conic(B,C,(double)s)
#define   RoundConic(M,C,r)            t1_RoundConic(M,C,(double)r)
#define   ArcP3(S,P2,P3)               t1_ArcP3(S,P2,P3)
#define   ArcCA(S,C,d)                 t1_ArcCA(S,C,(double)d)
#define   Bezier(B,C,D)                t1_Bezier(B,C,D)
#define   Hint(S,r,w,o,h,a,d,l)        t1_Hint(S,r,w,o,h,a,d,l)
#define   Reverse(p)                   t1_Reverse(p)
#define   ReverseSubPaths(p)           t1_ReverseSubPaths(p)
#define   AddLoc(p1,p2)                t1_Join(p1,p2)
#define   SubLoc(p1,p2)                t1_SubLoc(p1,p2)
#define   DropSegment(p)               t1_DropSegment(p)
#define   HeadSegment(p)               t1_HeadSegment(p)
#define   QueryLoc(P,S,x,y)            t1_QueryLoc(P,S,x,y)
#define   QueryPath(p,t,B,C,D,r)       t1_QueryPath(p,t,B,C,D,r)
#define   QueryBounds(p,S,x1,y1,x2,y2)  t1_QueryBounds(p,S,x1,y1,x2,y2)

#define   CopyPath(p)             t1_CopyPath((struct segment *)p)
#define   KillPath(p)             t1_KillPath((struct segment *)p)
#define   PathTransform(p,m)      t1_PathXform(p,m)
#define   PathDelta(p,pt)         t1_PathDelta((struct segment *)p,pt)
#define   BoundingBox(h,w)        t1_BoundingBox(h,w)
#define   PathSegment(t,x,y)      t1_PathSegment(t,(fractpel)x,(fractpel)y)
#define   JoinSegment(b,t,x,y,a)  t1_JoinSegment(b,t,(fractpel)x,(fractpel)y,a)
#define   Hypoteneuse(dx,dy)      t1_Hypoteneuse(dx,dy)
#define   BoxPath(S,h,w)          t1_BoxPath(S,h,w)


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

#define    CopyPicture(p)         p
#define    UniquePicture(p)       p
#define    KillPicture(p)
#define    BegHandle(o,m)         o
#define    EndHandle(o,m)         o
#define    PictureBounds(P)       P

struct picture
{
	struct fractpoint origin;
	struct fractpoint ending;
};


/*********
 * 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(R, x1, y1, x2, y2, dy) { \
   if (dy < 0) { \
      if (R->lastdy >= 0) \
          ChangeDirection(CD_CONTINUE, R, x1, y1, dy); \
      if (y2 < R->edgeYstop) \
          MoreWorkArea(R, x1, y1, x2, y2); \
   } \
   else if (dy > 0) { \
      if (R->lastdy <= 0) \
          ChangeDirection(CD_CONTINUE, R, x1, y1, dy); \
      if (y2 > R->edgeYstop) \
          MoreWorkArea(R, x1, y1, x2, y2); \
   } \
   else /* dy == 0 */ ChangeDirection(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,KillRegion(R))
#define    UniqueRegion(R)    MAKEUNIQUE(R,CopyRegion(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      */
	struct picture *thresholded;	/* region defined by thresholded picture*/

	/*
	 * 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 *,
			fractpel, fractpel, fractpel,
			fractpel, int);			/* function to use when building a new edge */
	struct strokeinfo *strokeinfo;			/* scratchpad info during stroking only */
};


/*
 * 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)


#define  EmptyRegion   t1_EmptyRegion


/*
 * 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   Interior(p,rule)        t1_Interior(p,rule)
#define   Union(a1,a2)            t1_Union(a1,a2)
#define   Intersect(a1,a2)        t1_Intersect(a1,a2)
#define   Complement(area)        t1_Complement(area)
#define   Overlap(a1,a2)          t1_OverLap(a1,a2)

#define   ChangeDirection(type,R,x,y,dy)  t1_ChangeDirection(type,R,x,y,dy)
#define   CD_FIRST         -1	/* enumeration of ChangeDirection type       */
#define   CD_CONTINUE       0	/* enumeration of ChangeDirection type        */
#define   CD_LAST           1	/* enumeration of ChangeDirection type        */
#define    MoreWorkArea(R,x1,y1,x2,y2)     t1_MoreWorkArea(R,x1,y1,x2,y2)
#define    KillRegion(area)   t1_KillRegion((struct region *)area)
#define    CopyRegion(area)   t1_CopyRegion((struct region *)area)
#define    BoxClip(R,xmin,ymin,xmax,ymax)  t1_BoxClip(R,xmin,ymin,xmax,ymax)
#define    SortSwath(a,p,f)   t1_SortSwath(a,p,f)
#define    SwathUnion(b,e)    t1_SwathUnion(b,e)
#define    RegionBounds(r)    t1_RegionBounds((struct region *)r)
#define    CoerceRegion(p)    t1_CoerceRegion(p)
#define    MoveEdges(R,dx,dy) t1_MoveEdges(R,dx,dy)
#define    UnJumble(R)        t1_UnJumble(R)


/*********
 * STROKES.H
 *********/

#define   CopyLineStyle(s)    s
#define   CopyStrokePath(p)   p
#define   KillStrokePath(p)
#define   KillLineStyle(s)
#define   CoercePath(sp)      sp
#define   DoStroke(sp)        sp


/*********
 * T1IMAGER.H
 *********/
typedef pointer xobject;
typedef pointer location;
typedef pointer path;
typedef pointer region;
typedef pointer XYspace;
/*
Here are some TYPE1IMAGER functions that are defined in terms of others:
*/

#define   t1_AddLoc(p1,p2)    t1_Join(p1,p2)

#ifndef   NONAMES
/*
Define the simple form of all the subroutine names:
*/
#define   Bezier(B,C,D)      t1_Bezier(B,C,D)
#define   ClosePath(p)       t1_ClosePath(p,0)
#define   Complement(area)   t1_Complement(area)
#define   HeadSegment(p)     t1_HeadSegment(p)
#define   Interior(p,rule)   t1_Interior(p,rule)
#define   Line(P)            t1_Line(P)
#define   Phantom(o)         t1_Phantom((struct xobject *)o)
#define   Loc(S,x,y)         t1_Loc(S,(double)x,(double)y)
#define   Snap(o)            t1_Snap((struct segment *)o)
#define   Transform(o,cxx,cyx,cxy,cyy)  t1_Transform(o,(double)cxx,(double)cyx,\
    (double)cxy,(double)cyy)

#endif

#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


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


#define FIRSTCOL  32

struct type1font
{
	CharInfoPtr pDefault;
	CharInfoRec glyphs[256 - FIRSTCOL];
};


/*********
 * 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)


/*
 * -------------------------------------------------------------------------
 * Globals shared  -- (everyone else KEEP YOUR MITTS OFF THEM!)
 * -------------------------------------------------------------------------
 */

/* These variables are set by the caller */
extern char *tokenStartP;	/* Pointer to token buffer in VM */
extern char *tokenMaxP;		/* Pointer to end of VM we may use + 1 */

/* These variables are set by P_TOKEN */
extern int tokenLength;		/* Characters in token */
extern boolean tokenTooLong;	/* Token too long for space available */
extern int tokenType;		/* Type of token identified */
extern psvalue tokenValue;	/* Token value */


/*********
 * TRIG.H
 *********/
#ifndef PI
#define PI  3.14159265358979323846
#endif

#define   DegreeCos(d)    (cos((PI / 180) * d))
#define   DegreeSin(d)    (sin((PI / 180) * d))





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


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


/**
 * curves.c
 **/
struct segment *StepBezier(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);
boolean initFont(int cnt);
int readFont(char *env);
xobject fontfcnB(struct XYspace *S, unsigned char *code, int *lenP, int *mode);
Bool fontfcnA(char *env, int *mode);
void QueryFontLib(char *env, char *infoName, pointer infoValue, int *rcodeP);


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


/**
 * lines.c
 **/
void StepLine(struct region *R, fractpel x1, fractpel y1, fractpel x2, fractpel y2);
void Bresenham(pel *edgeP, fractpel x1, fractpel y1, fractpel x2, fractpel y2);


/**
 * objects
 **/
struct xobject *t1_Permanent(struct xobject *obj);
struct xobject *t1_Temporary(struct xobject *obj);
struct xobject *t1_Destroy(struct xobject *obj);
struct xobject *t1_Dup(struct xobject *obj);

void FatalError(char *line);
#define t1_abort(line) FatalError(line)

void Pragmatics(char *username, int value);
char *ErrorMsg(void);
struct xobject *t1_Allocate(int size, struct xobject *template, int extra);
void t1_Free(struct xobject *obj);
void Consume(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(char *name, struct xobject *obj, int expect, struct xobject *ret);
struct xobject *t1_Copy(struct xobject *obj);
struct xobject *t1_Unique(struct xobject *obj);


/**
 * paths.c
 **/
struct segment *t1_Loc(struct XYspace *S, double x, double y);
struct segment *ILoc(struct XYspace *S, int x, int y);
struct segment *Line(struct segment *P);
struct segment *t1_Join(struct segment *p1, struct segment *p2);
struct segment *t1_ClosePath(struct segment *p0, int lastonly);
struct beziersegment *Bezier(struct segment *B,	struct segment *C, struct segment *D);
struct hintsegment *Hint(struct XYspace *S, double ref, double width, char orientation, char hinttype, char adjusttype, char direction, int label);
struct segment *Reverse(struct segment *p);
struct segment *ReverseSubPaths(struct segment *p);
struct segment *SubLoc(struct segment *p1, struct segment *p2);
struct segment *DropSegment(struct segment *path);
struct segment *HeadSegment(struct segment *path);
void QueryLoc(struct segment *P, struct XYspace *S, double *xP, double *yP);
void QueryPath(struct segment *path, int *typeP, struct segment **Bp, struct segment **Cp, struct segment **Dp, double *fP);
void QueryBounds(struct segment *p0, struct XYspace *S, double *xminP, double *yminP, double *xmaxP, double *ymaxP);

struct segment *t1_CopyPath(struct segment *p0);
void t1_KillPath(struct segment *p);
struct segment *PathTransform(struct segment *p0, struct XYspace *S);
void t1_PathDelta(struct segment *p, struct fractpoint *pt);
struct segment *BoundingBox(pel h, pel w);
struct segment *t1_PathSegment(int type, fractpel x, fractpel y);
struct segment *t1_JoinSegment(struct segment *before, int type, fractpel x, fractpel y, struct segment *after);
struct segment *BoxPath(struct XYspace *S, int h, int w);


/**
 * regions.c
 **/
struct region *Interior(struct segment *p, int fillrule);

void MoreWorkArea(struct region *R, fractpel x1, fractpel y1, fractpel x2, fractpel y2);
void t1_KillRegion(struct region *area);
struct region *t1_CopyRegion(struct region *area);
struct region *BoxClip(struct region *R, pel xmin, pel ymin, pel xmax, pel ymax);
struct edgelist *SortSwath(struct edgelist *anchor, struct edgelist *edge, struct edgelist *(*swathfcn) (struct edgelist *, struct edgelist *));
struct edgelist *SwathUnion(struct edgelist *before0, struct edgelist *edge);
struct segment *t1_RegionBounds(struct region *R);
struct region *CoerceRegion(struct textpath *tp);
void MoveEdges(struct region *R, fractpel dx, fractpel dy);
void UnJumble(struct region *region);

void ChangeDirection(int type, struct region *R, fractpel x, fractpel y, fractpel dy);
void DumpArea(struct region *area);
void DumpEdges(struct edgelist *edges);


/**
 * scanfont.c
 **/
boolean Init_BuiltInEncoding(void);
psobj *GetType1CharString(psfont *fontP, unsigned char code);
int scan_font(psfont *FontP);


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


/**
 * t1funcs.c
 **/
int MyType1OpenScalable(FontPtr *ppFont, char *fileName, FontScalablePtr vals);
int MyType1SetTransform(FontPtr pFont, FontScalablePtr vals);
int MyType1GetGlyphs(FontPtr pFont, int i, CharInfoPtr *returnglyph);
void MyType1CloseFont(FontPtr pFont);


/**
 * t1info.c (replaced by amishinfo.c)
 **/
void T1FillFontInfo(FontPtr pFont, FontScalablePtr Vals, char *Filename, char *Fontname);


/**
 * t1io.c
 **/
F_FILE *T1Open(char *fn, char *mode);
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(F_FILE *f);
void __asm T1eexec(register __a0 F_FILE *f);


/**
 * t1malloc.c
 **/
void xiFree(void *addr);
char *xiMalloc(unsigned int size);
void addmemory(long size);
void delmemory(void);

void addmemory2(long size);
void delmemory2(void);
char *Xalloc(int size);
void Xfree(char *p);


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


/**
 * token.c
 **/
void scan_token(psobj *inputP);


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


/**
 * util.c
 **/
boolean vm_init(int cnt);
void free_vm(void);
char *vm_alloc(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);
