341 lines
6.6 KiB
C
341 lines
6.6 KiB
C
/***
|
|
**
|
|
** Module: FReader
|
|
**
|
|
** Description:
|
|
** This is a module of the T1 to TT font converter. The module
|
|
** contains functions that decodes and decrypts the data of a
|
|
** T1 font file.
|
|
**
|
|
** Author: Michael Jansson
|
|
**
|
|
** Created: 5/26/93
|
|
**
|
|
***/
|
|
|
|
|
|
/**** INCLUDES */
|
|
/* General types and definitions. */
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
|
|
/* Special types and definitions. */
|
|
#include "titott.h"
|
|
#include "types.h"
|
|
#include "safemem.h"
|
|
#include "t1msg.h"
|
|
|
|
/* Module dependent types and prototypes. */
|
|
#include "freader.h"
|
|
#include "pfb.h"
|
|
|
|
|
|
/***** LOCAL TYPES */
|
|
struct FontFile {
|
|
|
|
/* Low-level I/O functions. */
|
|
errcode (FASTCALL *fclose)(struct t1file *);
|
|
short (FASTCALL *fgetc)(struct t1file *);
|
|
struct t1file *(*fopen)(const char *);
|
|
boolean (FASTCALL *fstatus)(const struct t1file *);
|
|
struct t1file *io;
|
|
|
|
/* Font file state. */
|
|
enum {prolog, eexec} state;
|
|
short nextbyte;
|
|
USHORT r;
|
|
};
|
|
|
|
|
|
/***** CONSTANTS */
|
|
static const USHORT c1 = 52845;
|
|
static const USHORT c2 = 22719;
|
|
|
|
|
|
/***** MACROS */
|
|
#define IOGetByte(f) ((*f->fgetc)(f->io))
|
|
#define IOError(f) ((*f->fstatus)(f->io))
|
|
#define IOOpen(f,n) ((*f->fopen)(n))
|
|
#define IOClose(f) ((*f->fclose)(f->io))
|
|
#define SetNextByte(ff, b) ff->nextbyte = (b)
|
|
#define NextByte(ff) (ff->nextbyte)
|
|
#define Eexec(ff) (boolean)(ff->state == eexec)
|
|
#define StartEexec(ff) ff->state = eexec
|
|
|
|
|
|
|
|
/***** STATIC FUNCTIONS */
|
|
/*-none-*/
|
|
|
|
|
|
|
|
/***** FUNCTIONS */
|
|
|
|
/***
|
|
** Function: GetByte
|
|
**
|
|
** Description:
|
|
** Pull one byte out of the T1 font file.
|
|
***/
|
|
short FASTCALL GetByte(struct FontFile *ff)
|
|
{
|
|
short b, nb;
|
|
|
|
b = IOGetByte(ff);
|
|
|
|
/* Decrypt it? */
|
|
if (Eexec(ff))
|
|
b = (short)Decrypt(&ff->r, (UBYTE)b);
|
|
|
|
/* Record look-a-head */
|
|
nb = NextByte(ff);
|
|
SetNextByte(ff, b);
|
|
|
|
return nb;
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
** Function: GetNewLine
|
|
**
|
|
** Description:
|
|
** Pull one whole line from the T1 font file, starting at
|
|
** the current position.
|
|
***/
|
|
char *GetNewLine(struct FontFile *ff, char *buf, const USHORT len)
|
|
{
|
|
short i = 0;
|
|
|
|
/* Get string. */
|
|
while ((buf[i] = (char)GetByte(ff))!='\n' &&
|
|
buf[i]!='\r' && ++i<((short)len-1));
|
|
|
|
/* Skip extra characters. */
|
|
if (buf[i]!='\n' && buf[i]!='\r')
|
|
while (!IOError(ff) && NextByte(ff)!='\n' && NextByte(ff)!='\r')
|
|
(void)GetByte(ff);
|
|
|
|
/* Terminate string. */
|
|
buf[i] = '\0';
|
|
|
|
/* Check for the start of the eexec section. */
|
|
if (!strcmp(buf, "eexec"))
|
|
StartEexec(ff);
|
|
|
|
/* Check error condition. */
|
|
if (IOError(ff))
|
|
return NULL;
|
|
|
|
return buf;
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
** Function: Get_Token
|
|
**
|
|
** Description:
|
|
** Pull one token from the T1 font file. A token
|
|
** is delimited by white space and various brackets.
|
|
***/
|
|
char *Get_Token(struct FontFile *ff, char *buf, const USHORT len)
|
|
{
|
|
short i = 0;
|
|
short nb;
|
|
|
|
/* Skip leading blanks. */
|
|
while (isspace(NextByte(ff)))
|
|
(void)GetByte(ff);
|
|
|
|
/* Get string. */
|
|
do {
|
|
buf[i] = (char)GetByte(ff);
|
|
nb = NextByte(ff);
|
|
} while (++i<((short)len-1) && !isspace(nb) && nb!='{' &&
|
|
nb!='(' && nb!='[' && nb!='/');
|
|
|
|
/* Skip extra characters. */
|
|
while (!IOError(ff) && !isspace(nb) && nb!='{' &&
|
|
nb!='(' && nb!='[' && nb!='/') {
|
|
(void)GetByte(ff);
|
|
nb = NextByte(ff);
|
|
}
|
|
|
|
/* Terminate string. */
|
|
buf[i] = '\0';
|
|
|
|
/* Check for the start of the eexec section. */
|
|
if (!strcmp(buf, "eexec"))
|
|
StartEexec(ff);
|
|
|
|
/* Check error condition. */
|
|
if (IOError(ff))
|
|
return NULL;
|
|
|
|
return buf;
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
** Function: GetSeq
|
|
**
|
|
** Description:
|
|
** Pull one sequence of bytes that are delimited by
|
|
** a given pair of characters, e.g. '[' and ']'.
|
|
***/
|
|
char *GetSeq(struct FontFile *ff,
|
|
char *buf,
|
|
const USHORT len)
|
|
{
|
|
char d1, d2;
|
|
short i = 0;
|
|
short inside = 0;
|
|
|
|
/* Skip leading blanks. */
|
|
while (NextByte(ff)!='[' &&
|
|
NextByte(ff)!='{' &&
|
|
NextByte(ff)!='(' &&
|
|
!IOError(ff))
|
|
(void)GetByte(ff);
|
|
|
|
/* match the bracket. */
|
|
d1 = (char)NextByte(ff);
|
|
if (d1=='[')
|
|
d2 = ']';
|
|
else if (d1=='{')
|
|
d2 = '}';
|
|
else if (d1=='(')
|
|
d2 = ')';
|
|
else
|
|
return NULL;
|
|
|
|
|
|
/* Get string. */
|
|
(void)GetByte(ff);
|
|
inside=1;
|
|
do {
|
|
buf[i] = (char)GetByte(ff);
|
|
if (buf[i]==d1)
|
|
inside++;
|
|
if (buf[i]==d2)
|
|
inside--;
|
|
} while (inside && ++i<((short)len-1));
|
|
|
|
/* Terminate string. */
|
|
buf[i] = '\0';
|
|
|
|
/* Check error condition. */
|
|
if (IOError(ff))
|
|
return NULL;
|
|
|
|
return buf;
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
** Function: FRInit
|
|
**
|
|
** Description:
|
|
** Initite the resources needed to read/decode data from
|
|
** a T1 font file.
|
|
***/
|
|
errcode FRInit(const char *name, const enum ftype type, struct FontFile **ff)
|
|
{
|
|
errcode status = SUCCESS;
|
|
short b;
|
|
|
|
if (((*ff)=(struct FontFile *)Malloc(sizeof(struct FontFile)))==NULL) {
|
|
SetError(status = NOMEM);
|
|
} else {
|
|
|
|
/* Initiat the handle. */
|
|
memset((*ff), '\0', sizeof(**ff));
|
|
|
|
/* Initiate low-level I/O. */
|
|
switch (type) {
|
|
case pfb_file:
|
|
(*ff)->fgetc = PFBGetByte;
|
|
(*ff)->fclose = PFBFreeIOBlock;
|
|
(*ff)->fstatus = PFBFileError;
|
|
(*ff)->fopen = PFBAllocIOBlock;
|
|
break;
|
|
case mac_file:
|
|
#if MACFILEFORMAT
|
|
(*ff)->fgetc = MACGetByte;
|
|
(*ff)->fclose = MACFreeIOBlock;
|
|
(*ff)->fstatus = MACFileError;
|
|
(*ff)->fopen = MACAllocIOBlock;
|
|
break;
|
|
#endif
|
|
case ascii_file:
|
|
#if ASCIIFILEFORMAT
|
|
(*ff)->fgetc = ASCIIGetByte;
|
|
(*ff)->fclose = ASCIIFreeIOBlock;
|
|
(*ff)->fstatus = ASCIFileError;
|
|
(*ff)->fopen = ASCIIAllocIOBlock;
|
|
break;
|
|
#endif
|
|
default:
|
|
LogError(MSG_ERROR, MSG_BADFMT, NULL);
|
|
SetError(status = BADINPUTFILE);
|
|
break;
|
|
}
|
|
|
|
(*ff)->io = NULL;
|
|
if (((*ff)->io = IOOpen((*ff),name))==NULL) {
|
|
SetError(status = BADINPUTFILE);
|
|
} else {
|
|
(*ff)->state = prolog;
|
|
(*ff)->r = 55665;
|
|
|
|
b=GetByte(*ff);
|
|
SetNextByte((*ff), b);
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
** Function: FRCleanUp
|
|
**
|
|
** Description:
|
|
** Free the resources used when reading/decoding data from
|
|
** a T1 font file.
|
|
***/
|
|
errcode FRCleanUp(struct FontFile *ff)
|
|
{
|
|
errcode status = SUCCESS;
|
|
|
|
if (ff) {
|
|
if (ff->io)
|
|
status = IOClose(ff);
|
|
Free(ff);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
** Function: Decrypt
|
|
**
|
|
** Description:
|
|
** Decrypt a byte.
|
|
***/
|
|
UBYTE FASTCALL Decrypt(USHORT *r, const UBYTE cipher)
|
|
{
|
|
UBYTE plain;
|
|
|
|
plain = (UBYTE)(cipher ^ (*r>>8));
|
|
*r = (USHORT)((cipher+*r) * c1 + c2);
|
|
|
|
return plain;
|
|
}
|