home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 12 Font
/
12-Font.zip
/
T1FONT.ZIP
/
t1font.c
next >
Wrap
Text File
|
1991-10-14
|
35KB
|
1,164 lines
/********************************************************************
* *
* Title: t1font - Adobe Type 1 Font Utility *
* *
* Author: Ken Borgendale 14 OCT 91 *
* *
* Copyright: *
* t1font Copyright (C) IBM Corp., 1991 *
* *
* Function: *
* This utility does encode and decode functions against *
* Adobe type 1 fonts. The font can be in one of 3 forms: *
* *
* 1. binary - (.pfb format) This form is used on the IBM *
* PC and keeps the eexec information in binary. *
* 2. ascii - (.pfa format) This form is used in Unix and *
* to download to PostScript. It keeps eexec *
* information in hex. *
* 3. expanded- (.pfx format) This form is private to t1font *
* and decodes the eexec information so humans *
* can read and modify it. *
* *
* t1font allows the font to be converted between these forms. *
* The default action is to convert decoded and ascii fonts to *
* binary, and to convert binary fonts to ascii. *
* *
* Syntax: *
* t1font infile outfile -abxdq *
* -a = Output ascii (hex) font *
* -b = Output binary (compressed) font *
* -x = Output expanded (decrypted) font *
* -d = Show debug information *
* -q = Quiet mode (no info messages) *
* *
* Compile Options: *
* OS/2: -G2srm -W3 -AL t1font.def *
* DOS: -Gsrm -W3 -AL *
* RS/6000: -DXLC *
* *
* Notes: *
* 1. The fact that this code allows you to decrypt and modify *
* type 1 fonts does not mean you have the legal right to *
* do so. You should check the licence agreements for the *
* font to determine if this is a valid thing to do. *
* *
* 2. The information about what the font means is derived from*
* "Adobe Type 1 Font Format", available at your local book *
* store. *
* *
* 3. The only real way to parse a type 1 font is with a *
* PostScript (forth) parser. This is a simplistic parser, *
* but it matches the ATM parser for the most part. *
* *
* 4. The resulting files are mixed between Unix and DOS rules *
* for CR and LF. There is an LF is all cases which should *
* make all DOS C programs work. A CR in the binary ASCII *
* section is expanded to CRLF. An LF in the input is just *
* left that way. *
* *
* 5. The expanded mode parser corrects charstring lengths, *
* but does very little other checking. The fact that the *
* conversion works does not mean the font is any good. *
* *
********************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
* Define unsigned types and other compiler sensitive stuff
*/
#ifdef XLC /* RS/6000 */
#define NEAR
#define MAINENT
#define OPTSEP '-'
#else /* Microsoft C 6.0 */
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned long ulong;
typedef unsigned int uint;
#define NEAR near
#define MAINENT _cdecl
#define OPTSEP '/'
#endif
#define MAXCHARSTR 32700
/*
* Define section headers for pfb files
*/
typedef struct {
uchar id; /* Always 0x80 */
uchar type; /* 1=ASCII, 2=binary, 3=eof */
long len; /* Section length */
} PFBHDR;
PFBHDR pfb;
/*
* Charstring command table
*/
struct cstable {
ushort val; /* Value - escape command are val+32 */
uchar NEAR * name;
} CSTable[] = {
1, "hstem", /* Single byte commands */
3, "vstem",
4, "vmoveto",
5, "rlineto",
6, "hlineto",
7, "vlineto",
8, "rrcurveto",
9, "closepath",
10, "callsubr",
11, "return",
13, "hsbw",
14, "endchar",
21, "rmoveto",
22, "hmoveto",
30, "vhcurveto",
31, "hvcurveto",
32+0, "dotsection", /* Escapes */
32+1, "vstem3",
32+2, "hstem3",
32+6, "seac",
32+7, "sbw",
32+12, "div",
32+16, "callothersub",
32+17, "pop",
32+33, "setcurrentpoint",
100+0, "|-", /* Terminators */
100+0, "ND",
100+1, "|",
100+1, "NP",
100+3, "noaccess",
100+1, "put",
100+0, "def",
0, "ERROR",
};
/*
* Defines and constants
*/
const uchar hexdig[] = {"0123456789abcdef"};
const uint c1 = 52845;
const uint c2 = 22719;
/*
* Function prototypes
*/
void help (void); /* Show simple help */
void parseargs (int argc, uchar * * argv);
void binaryfile (void); /* Input file is binary */
void outchar (uchar ch); /* Output character */
void asciifile (void); /* Input file is ascii */
void expandfile (void); /* Input file is expanded */
void putonechar(uchar ch); /* Put one char from expanded mode */
void expeexec(uchar ch); /* Expanded mode eexec */
void expcharstr(uchar ch); /* Expanded mode charstring */
void encryptnum(long num); /* Output number to encryption */
void charstrnum(long v); /* Put out number in charstring */
void setbinary(uchar type); /* Write binary mode header */
void eexec (uchar ch); /* Process one eexec char */
void normchar (uchar ch); /* Process normal eexec char */
void charstr (uchar ch); /* Process one charstring char */
uchar decrypt (uchar cipher); /* eexec decrypt */
uchar decryptch (uchar cipher); /* Charstring decrypt */
uchar encrypt(uchar cipher); /* eexec encrypt */
uchar encryptch(uchar plain); /* Charstring encrypt */
void outhexchar (uchar ch); /* Output a hex byte */
void outval (long v); /* Output number */
void outcmd (uchar ch); /* Output command */
void maxcol(void); /* Check for end of line */
void warning(uchar * warn); /* Output a warning */
/*
* Global variables. A number of these global variables come from
* the fact that much of the parse is a state machine, where the
* functions are called for each character parsed.
*/
FILE * inf; /* Input file */
FILE * outf; /* Output file */
uchar * infname; /* Input file name */
uchar * outfname; /* Output file name */
uint rdn, rch; /* random number current values */
long thisval, oldval; /* evaluate numbers as they pass by */
long cscnt; /* Charstring count */
int col; /* current output column */
uchar mode; /* eexec mode */
uchar cmode; /* charstring mode */
uchar xmode; /* expansion mode */
uchar deflenIV; /* Defining lenIV */
int lenIV; /* ignore length for charstrings */
int ignore; /* Current ignore state */
uchar token[512]; /* Current token */
uchar line[512]; /* Input line */
int tokenpos; /* Token position */
long bytecnt; /* Byte count for binary mode */
long cntloc; /* Where to update count */
uchar debugflag; /* -d option */
uchar quietflag; /* -q option */
uchar outtype; /* Do only hex output */
uchar inform; /* Format of input */
uchar justnl; /* Just stuffed nl */
uchar hexval; /* Current hex value */
uchar oddnib; /* Currently at odd nibble */
uchar RDtype; /* font uses RD instead of -| */
uchar negflag; /* Number is negative */
uchar * CharStr; /* Charstring build buffer */
int CharPos; /* Charstring current length */
uchar glyph[32]; /* Glyph or Subr name */
#define PFASCII 0
#define PFBINARY 1
#define PFEXPAND 2
#define PFUNDEF 3
#define XMOUTSIDE 0
#define XMSUBRS 1
#define XMCHARS 2
/*
* Put out short help
*/
void help (void) {
puts("\nt1font - Adobe Type 1 Font Utility Version 1.0 14 Oct 1991\n");
puts("t1font infile outfile -abx");
puts("-a = Output ascii (hex) font");
puts("-b = Output binary (compressed) font");
puts("-x = Output expanded (decrypted) font");
puts("\nThis utility converts between three forms of the Adobe type 1");
puts("fonts. The binary form is used on the PC, the ascii form is sent");
puts("to PostScript and used in Unix. The expanded form allows some");
puts("editing of the decrypted font.");
puts("\nKen Borgendale - kwb@betasvm2.vnet.ibm.com");
exit (1);
}
/*
* Main function of Adobe Type 1 Font Utility
*/
MAINENT main(int argc, uchar ** argv) {
uchar ch;
/*
* Parse arguments
*/
parseargs(argc, argv);
inf = fopen(infname, "rb");
if (!inf) {
fputs("Input file open error - ", stderr);
fputs(infname, stderr);
fputc('\n', stderr);
exit (5);
}
/*
* Look at the first character to decide what type the input is
*/
ch = (uchar)fgetc(inf); /* Peek at the first character */
switch (ch) {
case '%':
inform = PFASCII;
ungetc(ch, inf); /* Position back */
break;
case '#':
inform = PFEXPAND;
break;
case 0x80:
inform = PFBINARY;
ungetc(ch, inf); /* Position back */
break;
default:
fputs("Unknown input file type - ", stderr);
fputs(infname, stderr);
fputc('\n', stderr);
exit (9);
} /* endswitch */
/*
* Default output type
*/
if (outtype==PFUNDEF) {
if (inform==PFBINARY)
outtype = PFASCII;
else outtype = PFBINARY;
}
if (inform == outtype) {
fputs("Input file already in desired output format\n", stderr);
exit (10);
}
/*
* Open output file
*/
outf = fopen(outfname, "wb");
if (!outf) {
fputs("Output file open error - ", stderr);
fputs(outfname, stderr);
fputc('\n', stderr);
exit (6);
}
if (outtype==PFEXPAND) { /* Put out marker for expanded font */
fputc('#', outf);
}
if (outtype==PFBINARY) { /* Put out text section start */
fwrite("\x80\1\0\0\0\0", 6, 1, outf);
cntloc = 2;
}
/*
* Initialize global variables
*/
col = 0;
ignore = 4;
mode = 4;
cmode = 0;
rdn = 55665;
lenIV = 4;
/*
* Call the routine based on the input file type
*/
switch (inform) {
case PFASCII: /* Ascii input */
asciifile();
break;
case PFBINARY: /* Binary input */
binaryfile();
break;
case PFEXPAND: /* Expanded input */
expandfile();
break;
} /* endswitch */
/*
* Finish up
*/
if (outtype==PFBINARY) { /* Put out eof */
setbinary(3);
}
fclose(inf);
fclose(outf);
return 0;
}
/*
* Parse arguments
*/
void parseargs (int argc, uchar * * argv) {
uchar swchar;
int argcnt;
int filecnt;
uchar * argp;
argcnt = 1;
filecnt = 0;
outtype = PFUNDEF;
/* Read the arguments and decide what we are doing */
while (argcnt<argc) {
argp = argv[argcnt];
/* Check for switches. Files may not start with - or / */
if (*argp == '-' || *argp == OPTSEP) {
/* Process switches */
swchar = (uchar)tolower(argp[1]);
argp += 2;
switch (swchar) {
case '?':
help(); /* Does not return */
/* Hex output mode */
case 'a':
outtype = PFASCII;
break;
/* Binary output mode */
case 'b':
outtype = PFBINARY;
break;
/* Debug option - currently undocumented */
case 'd':
debugflag = 1;
break;
/* Quiet option - currently undocumented */
case 'q':
quietflag = 1;
break;
/* Expansion mode option */
case 'x':
outtype = PFEXPAND;
break;
default:
fputs("Unknown options: ", stderr);
fputs(argp-2, stderr);
fputc('\n', stderr);
}
} else {
if (*argp=='?') {
help(); /* Does not return */
}
switch(++filecnt) {
case 1:
infname = argp;
break;
case 2:
outfname = argp;
break;
default:
fputs("Extra parameter ignored: ", stderr);
fputs(argp, stderr);
fputc('\n', stderr);
}
}
argcnt++;
}
/*
* Make sure two files were specified. The extensions and output
* file name could be defaulted, but this routine is not used often
* enough to be a big problem.
*/
if (filecnt<2) {
fputs("Two files must be specified.\n", stderr);
help();
}
}
/*
* Process a binary input file
*/
void binaryfile(void) {
long len;
uchar ch;
while (!feof(inf)) {
pfb.id = 0;
fread(&pfb, 6, 1, inf);
if (pfb.id!=0x80) { /* Check for .pfb file */
fputs("Bad input file - ", stderr);
fputs(infname, stderr);
fputc('\n', stderr);
exit(7);
}
len = pfb.len;
if (pfb.type==3) break; /* eof */
switch (pfb.type) {
case 1: /* ascii */
while (len) {
ch = (uchar) fgetc(inf);
outchar(ch);
len--;
}
break;
case 2: /* binary */
while (len) {
ch = (uchar) fgetc(inf);
if (outtype) {
eexec(ch);
} else {
outhexchar(ch);
}
len--;
}
if (outtype==PFASCII)
outchar('\n');
break;
default:
fputs("Bad header type - ", stderr);
fputs(infname, stderr);
fputc('\n', stderr);
exit (8);
} /* endswitch */
}
}
/*
* Output a character keeping track of tokens
*/
void outchar (uchar ch) {
if (ch==' ' || ch=='\t' || ch=='\r' || ch=='\n') {
/* check tokens */
if (tokenpos) {
token[tokenpos]=0;
switch (tokenpos) {
case 3:
if (!strcmp(token, "def")) {
if (deflenIV) {
if (thisval<8)
lenIV = (int)thisval;
deflenIV = 0;
}
}
break;
case 5:
if (!strcmp(token, "eexec")) {
mode = 0;
}
break;
case 6:
if (!strcmp(token, "/lenIV")) {
deflenIV = 1;
}
break;
}
}
thisval = 0;
tokenpos = 0;
} else {
if (ch>='0' && ch<='9') {
tokenpos = 0;
thisval *= 10;
thisval += (ch-'0');
} else {
token[tokenpos++] = ch;
}
}
if (justnl) { /* Ignore LF if we just stuffed one */
justnl = 0;
if (ch==0x0a) return;
}
fputc(ch, outf); /* Output the character */
bytecnt++;
if (ch==0x0d) { /* Stuff LF for all CRs */
fputc(0x0a, outf);
bytecnt++;
justnl = 1;
}
}
/*
* Process an ascii input file
*/
void asciifile(void) {
uchar ch;
uchar * lp;
int i, val;
while (!feof(inf)) {
lp = fgets(line, 511, inf);
if (!lp) break;
reloop:
if (mode==4) { /* Outside of eexec */
while (*lp) outchar(*lp++);
} else {
if (!mode && outtype==PFBINARY) {
setbinary(2);
mode = 1;
}
/*
* Check for end of eexec mode
*/
i = strspn(line, "0\r\n");
if (i>16 && !line[i]) {
mode = 4;
tokenpos = 0;
if (outtype==PFBINARY)
setbinary(1);
goto reloop;
}
/*
* Process an eexec line
*/
while (*lp) {
if (*lp>='0' && *lp <= '9') {
val = *lp - '0';
} else {
ch = (uchar) tolower(*lp);
if (ch>='a' && ch<='f') {
val = ch-'a'+10;
} else {
lp++;
continue;
}
}
/*
* Accumulate digits
*/
if (oddnib) {
hexval |= val;
if (outtype==PFEXPAND) {
eexec(hexval);
} else {
fputc(hexval, outf);
bytecnt++;
}
} else {
hexval = (uchar)(val<<4);
}
oddnib ^= 1;
lp++;
}
}
}
}
/*
* Process an expanded input file
*/
void expandfile(void) {
uchar * lp;
int i;
/* Allocate space for charstring build */
CharStr = malloc(MAXCHARSTR);
xmode = XMOUTSIDE;
cmode = 0;
/* Loop for all input */
while (!feof(inf)) {
lp = fgets(line, 511, inf);
if (!lp) break;
reloopx:
if (mode==4) { /* Outside eexec */
while (*lp) outchar(*lp++);
} else {
/* eexec start */
if (!mode) {
if (outtype==PFBINARY)
setbinary(2);
mode = 1;
for (i=0; i<4; i++) {
putonechar('x');
}
}
/* Check eexec end condition */
i = strspn(line, "0\r\n");
if (i>16 && !line[i]) {
mode = 4;
tokenpos = 0;
if (outtype==PFBINARY)
setbinary(1);
if (outtype==PFASCII) {
outchar('\n');
}
goto reloopx;
}
while (*lp) {
/* process chars */
switch (mode) {
case 1: /* Outside charstring */
expeexec(*lp);
break;
case 2: /* Inside charstring */
expcharstr(*lp);
break;
} /* endswitch */
lp++;
}
}
}
}
/*
* Put out one character from expanded mode
*/
void putonechar(uchar ch) {
uchar x;
x = encrypt(ch);
if (outtype==PFBINARY) {
fputc(x, outf);
bytecnt++;
} else {
outhexchar(x);
}
}
/*
* Parse one character in expanded eexec mode.
*
* This is basically a parse for the start of an charstring.
* We have to be careful not to output the length field of a charstring
* until we have parsed the charstring to find its actual length.
*/
void expeexec(uchar ch) {
if (ch==' ' || ch=='\t' || ch=='\r' || ch=='\n') {
if (tokenpos==2 &&
((token[0]=='-' && token[1]=='|') ||
(token[0]=='R' && token[1]=='D')) ) {
mode=2;
if (token[0]=='R') RDtype = 1;
else RDtype = 0;
rch = 4330;
cscnt = oldval;
memset(CharStr, 'y', lenIV);
CharPos = lenIV;
}
if (tokenpos) { /* Allow multiple blanks */
if (tokenpos>0) {
token[tokenpos] = 0;
if (*token=='/') {
strncpy(glyph, token, 31);
if (xmode==XMCHARS) {
cmode = 1; /* Buffer charstring */
}
if (!strcmp(token, "/Subrs")) {
xmode = XMSUBRS;
}
if (!strcmp(token, "/CharStrings")) {
xmode = XMCHARS;
}
} else {
if (tokenpos==3) {
if (!strcmp(token, "end")) {
xmode = XMOUTSIDE;
}
if (!strcmp(token, "dup")) {
if (xmode==XMSUBRS) {
cmode = 2;
}
}
}
}
}
/* Start delayed mode for subr tokens */
if (cmode==2 && tokenpos<0) {
strcpy(glyph, "Subr "); /* Keep for errors */
ltoa(thisval, glyph+5, 10);
cmode = 1;
}
oldval = thisval;
thisval = 0;
tokenpos = 0;
}
} else {
if (tokenpos<=0 && ch>='0' && ch<='9') {
tokenpos = -1;
thisval *= 10;
thisval += (ch-'0');
} else {
/* Slash starts a new token */
if (ch=='/') tokenpos = 0;
token[tokenpos++] = ch;
}
}
if (cmode != 1) { /* Delay if might be charstring */
if (ch!=0x0a || !justnl)
putonechar(ch);
}
justnl = 0;
}
/*
* Output an encrypted number with a leading space
*/
void encryptnum(long num) {
uchar chx[16];
uchar *cp;
ltoa(num, chx, 10);
putonechar(' ');
cp = chx;
while (*cp) {
putonechar(*cp);
cp++;
}
}
/*
* Parse one character in expanded charstring mode
*/
void expcharstr(uchar ch) {
uchar * cp;
int i;
int value;
if (ch==' ' || ch=='\t' || ch=='\r' || ch=='\n') {
if (tokenpos<0) {
if (negflag)
thisval = -thisval;
charstrnum(thisval);
}
if (tokenpos>0) {
token[tokenpos]=0;
i=0;
value = 200;
while (CSTable[i].val) {
if (!strcmp(token, CSTable[i].name)) {
value = CSTable[i].val;
break;
}
i++;
}
if (value>199) {
warning("Unknown readchar token, charstr ended");
}
/* Put operator into charstr */
if (value<100) {
if (value>=32) {
CharStr[CharPos] = 12;
CharPos++;
value -= 32;
}
CharStr[CharPos] = (uchar) value;
CharPos++;
}
/*
* End charstring - put whole charstring out
*/
if (value>=100) { /* End of charstr */
if (CharPos != (int)cscnt) {
warning("Incorrect charstring len");
}
encryptnum(CharPos);
putonechar(' ');
if (RDtype) {
putonechar('R');
putonechar('D');
} else {
putonechar('-');
putonechar('|');
}
putonechar(' ');
cp = CharStr;
for (i=0; i<CharPos; i++) {
putonechar(encryptch(*cp));
cp++;
}
putonechar(' ');
cp = token;
while (*cp) {
putonechar(*cp);
cp++;
}
cmode = 0;
mode = 1;
putonechar('\n');
justnl = 1;
}
}
tokenpos = 0;
} else {
if (tokenpos<=1 && ch>='0' && ch<='9') {
if (tokenpos>=0) {
negflag = 0;
if (tokenpos==1) {
if (*token=='-')
negflag=1;
else goto notnum;
}
tokenpos = -1;
thisval = 0;
}
thisval *= 10;
thisval += (ch-'0');
} else {
notnum:
token[tokenpos++] = ch;
}
}
}
/*
* Add a charstring number to the charstring buffer
*/
void charstrnum(long v) {
short s;
long val;
int i;
/*
* Single byte encoding
*/
if (labs(v) <= 107) {
CharStr[CharPos] = (uchar)(v + 139);
CharPos++;
return;
}
/*
* Double byte encoding
*/
if (labs(v) <= 1131) {
s = (short) abs((short)v);
s -= 108;
if (v<0) {
CharStr[CharPos] = (uchar)((s>>8)+251);
} else {
CharStr[CharPos] = (uchar)((s>>8)+247);
}
CharStr[CharPos+1] = (uchar)s;
CharPos += 2;
return;
}
/*
* Four byte encoding. Do this in a way that works for both
* little-endian and big-endian.
*/
CharStr[CharPos] = 255;
val = v;
for (i=1; i<=4; i++) {
CharStr[CharPos+i] = (uchar)val;
val >>= 8;
}
CharPos += 5;
}
/*
* Update the length an write the next entry for binary mode
*/
void setbinary(uchar type) {
fseek(outf, cntloc, SEEK_SET);
fwrite(&bytecnt, 4, 1, outf);
fseek(outf, 0L, SEEK_END);
bytecnt = 0;
fputc('\x80', outf);
fputc(type, outf);
cntloc = ftell(outf);
if (type != 3) { /* Adobe does not put the len on EOF */
fwrite("\0\0\0\0", 4, 1, outf);
}
}
/*
* Process one eexec character. This is a state machine.
*/
void eexec(uchar ch) {
ch = decrypt(ch);
switch (mode) {
case 0: /* Ignore at front */
if (!--ignore) mode=1;
break;
case 1: /* In normal chars */
normchar(ch);
break;
case 2: /* At front of charstring */
ch = decryptch(ch);
cscnt--;
if (!--ignore) mode=3;
break;
case 3: /* Normal charstring */
charstr(ch);
if (!--cscnt) {
mode = 1;
}
}
}
/*
* Check if we should put out end of line
*/
void maxcol(void) {
if (col>70) {
fputc(0x0d, outf);
fputc(0x0a, outf);
col = 0;
}
}
/*
* Output hex character. Maintain column position and add line breaks
* as necessary.
*/
void outhexchar(uchar ch) {
fputc(hexdig[ch>>4], outf);
fputc(hexdig[ch&15], outf);
col += 2;
if (col>=78) {
fputc(0x0d, outf);
fputc(0x0a, outf);
col = 0;
}
}
/*
* Normal character in eexec range. This routine evaluates numeric
* operands, and look for special tokens.
*/
void normchar(uchar ch) {
if (ch==' ' || ch=='\t' || ch=='\r' || ch=='\n') {
if (tokenpos==2 &&
((token[0]=='-' && token[1]=='|') ||
(token[0]=='R' && token[1]=='D')) ) {
mode=2;
cmode = 0;
ignore = lenIV;
rch = 4330;
cscnt = oldval;
} else {
fputc(ch, outf);
col++;
if (ch=='\n' || ch=='\r') col = 0;
maxcol();
}
oldval = thisval;
thisval = 0;
tokenpos = 0;
} else {
if (ch>='0' && ch<='9') {
tokenpos = 0;
thisval *= 10;
thisval += (ch-'0');
} else {
token[tokenpos++] = ch;
}
fputc(ch, outf);
col++;
}
}
/*
* Character string character. Within a character string, commands and
* integer operands are encoded so as to minimize memory usage.
* This routine is a state machine.
*/
void charstr(uchar ch) {
long temp;
ch = decryptch(ch); /* Do second decode */
switch (cmode) {
case 0: /* In base charstring processing */
if (ch<32) { /* Process command */
if (ch==12) cmode=1; /* Escape */
else outcmd(ch);
} else {
if (ch<247) { /* Single byte integer */
outval((long)ch-139);
} else {
if (ch==255) { /* Start four byte integer */
cmode = 4;
ignore = 4;
thisval = 0;
} else { /* 2 byte integer */
if (ch<251) {
cmode = 2;
thisval = ch-247;
} else {
cmode = 3;
thisval = ch-251;
}
thisval <<= 8;
}
}
}
break;
case 1: /* Escape command */
outcmd((uchar)(ch+32));
cmode = 0;
break;
case 2: /* Two byte positive number */
thisval += ch + 108;
outval(thisval);
cmode = 0;
break;
case 3: /* Two byte negative number */
thisval = 0 - thisval - ch - 108;
outval(thisval);
cmode = 0;
break;
case 4: /* Long integer */
temp = ch;
temp <<= ((4-ignore)*8);
thisval |= temp;
if (!--ignore) {
outval(thisval);
cmode = 0;
}
}
}
/*
* Decrypt one byte of normal eexec data (Adobe algorithm)
*/
uchar decrypt(uchar cipher) {
uchar plain;
plain = (uchar)(cipher ^ (rdn>>8));
rdn = (cipher+rdn) * c1 + c2;
return plain;
}
/*
* Decrypt one byte in a charstring (Adobe algorithm)
*/
uchar decryptch(uchar cipher) {
uchar plain;
plain = (uchar)(cipher ^ (rch>>8));
rch = (cipher+rch) * c1 + c2;
return plain;
}
/*
* Encrypt one byte of normal eexec data (Adobe algorithm)
*/
uchar encrypt(uchar plain) {
uchar cipher;
cipher = (uchar)(plain ^ (rdn>>8));
rdn = (cipher+rdn) * c1 + c2;
return cipher;
}
/*
* Encrypt one byte in a charstring (Adobe algorithm)
*/
uchar encryptch(uchar plain) {
uchar cipher;
cipher = (uchar)(plain ^ (rch>>8));
rch = (cipher+rch) * c1 + c2;
return cipher;
}
/*
* Output a value. Keep track of the size so we can put in line ends
* as necessary.
*/
void outval(long v) {
char chx[16];
ltoa(v, chx, 10);
col += strlen(chx);
col++;
fputc(' ', outf);
fputs(chx, outf);
maxcol();
}
/*
* Output a charstring command. Look up the name in the table.
*/
void outcmd(uchar ch) {
uint i;
i=0;
while (CSTable[i].val && CSTable[i].val!=ch) i++;
fputc(' ', outf);
fputs(CSTable[i].name, outf);
col += strlen(CSTable[i].name);
col++;
maxcol();
}
/*
* Output a warning. Put out the message and the name of the glyph
* or Subr number we are currently working on.
*/
void warning(uchar * warn) {
if (!quietflag) {
fputs(warn, stderr);
fputs(" - ", stderr);
fputs(glyph, stderr); /* Last glyph we saw */
fputc('\n', stderr);
}
}