/* t1accent -- adds the new accents into Type1 fonts Copyright (C) 1998 Petr Olsak, Version April 1998 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #ifndef max #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) #endif #define MAXGBUF 30000 /* the size of array for all CharStrings */ #define MAXIMEM 8000 /* the work space for decrypted CharString */ #define MAXBUF 200 /* limit of the work buffer */ #define MAXSTACK 25 /* maximum of Type1 stack, sufficient */ #define MAXSUBS 300 /* maximum number of subroutines */ #define MAXINFILES 200 /* maximum number of processed pfb files */ #define MAXVARS 200 /* maximum number of VAR declared in conf file */ #define MAXNEWCHARS 200 /* maximum number of CHAR declared in conf file */ #define MAXREMARKS 20 /* maximum number of REM lines */ #define MAXCHARS 300 /* maximum number of chars in input pfb file */ /* main string memory will be allocated via malloc: static char gbuf[MAXGBUF]; */ unsigned char *pbuf, *gbuf, *fixpbuf; unsigned char *csname[50]; /* the array of control sequences */ int cscode[50]; int last_csname, start_type1code; char buf[MAXBUF]; /* temporary buffer */ char fname[MAXBUF]; char RDcommand[3], NDcommand[3], NPcommand[3]; char pattern[MAXBUF]; int pip, ispattern; int lenIV; int numfiles=0; unsigned char *infile[MAXINFILES]; int imem[MAXIMEM]; /* the decrypted Chartrings */ unsigned int pim=1, fixpim, topim; int numrems = 0; unsigned char *remark[MAXREMARKS]; int srcisread = 0, nameisread = 0; unsigned char *srcdir, *newname, *oriname; int diffname; int numsubs=0, pfbnumsubs, pfbchars; struct subrtype { /* structure for new subroutine */ unsigned int code; unsigned char *name; int vvaxis, lx, ly, ux, uy ; } subr[MAXSUBS]; int numvars=0; struct varstruct { /* structure for variable declared by VAR */ unsigned char *name; float value; } variable[MAXVARS]; int numchars=0; int sumchars; struct newcharstruct { /* structure for new char declared by CHAR */ unsigned char *name, *origname, *origcode; unsigned int owncode; int origlen, nsub, x, y, dsbx, dwx, dy, type; } newchar[MAXNEWCHARS]; struct savedsubrstruct { /* structure for /Subrs from pfb */ unsigned char *code; int len; } savedsubr[MAXSUBS]; struct savedcharstruct { /* structure for /CharStrings from pfb */ unsigned char *code, *name; int len; } savedchars[MAXCHARS]; unsigned char *encvector[256]; /* encoding vector */ int encisread=0; int prst = 0; float rs[MAXSTACK]; /* stack with real numbers */ float scaleX, scaleY, curX, curY; /* global variables */ int cX, cY, lX, lY, uX, uY, inpath, pX, pY, vvax, glX, glY, guX, guY; int line=0; FILE *fin, *fenc, *fpfb, *fpps; #define VALUE 0 #define HSTEM 1 #define VSTEM 3 #define VMOVETO 4 #define RLINETO 5 #define HLINETO 6 #define VLINETO 7 #define RRCURVETO 8 #define CLOSEPATH 9 #define CALLSUBR 10 #define RETURN 11 #define ESCAPE 12 #define HSBW 13 #define ENDCHAR 14 #define RMOVETO 21 #define HMOVETO 22 #define VHCURVETO 30 #define HVCURVETO 31 #define DOTSECTION 1200 #define VSTEM3 1201 #define HSTEM3 1202 #define SEAC 1206 #define SBW 1207 #define DIV 1212 #define CALLOTHERSUBR 1216 #define POP 1217 #define SETCURRENTPOINT 1233 #define MOVETO 1301 #define LINETO 1302 #define CURVETO 1303 #define RCURVETO 1304 #define SCALED 1310 #define VVAXIS 1311 #define BGROUP 1401 #define EGROUP 1402 #define NUMSUB 1403 #define PUTORIGIN 1501 #define PUTSIDEBAR 1522 #define PUTCENTER 1503 #define PUTAFTER 1504 #define UNKNOWN 1599 #define MAGIC 31243 #define BEGIN 1 #define CLOSE 2 #define CURXY 3 #define CURX 4 #define CURY 5 #define CURXY6 6 #define CURHV4 7 #define CURVH4 8 #define SAVECHAR 1 #define SAVESUBR 2 void error (char* format, char* value) { /* prints an error message and exists */ if (line>0) fprintf(stderr,"\nError: (line %d) -- ", line); else fprintf(stderr,"\nError: -- "); if (value) fprintf(stderr, format, value); else fprintf(stderr, format); fprintf(stderr,"\n"); exit(2); } unsigned char* add_gbuf(unsigned char* p) { /* stores a new string in global buffer */ unsigned char *pp; pp=pbuf; pbuf += strlen(p)+1; if (pbuf >= &gbuf[MAXGBUF]) error ("MAXGBUF (global string memory) overflows",NULL); strcpy(pp, p); return pp; } void store_gbuf(int c) { /* stores a new byte in global buffer */ if (pbuf >= &gbuf[MAXGBUF]) error ("MAXGBUF (global string memory) overflows",NULL); pbuf[0] = c; pbuf++; } void init_csnames(void) { /* initialises standard operator names in global buffer */ int i=0; gbuf = pbuf = (unsigned char*) malloc(MAXGBUF); if (!gbuf) error ("cannot allocated main strig memory", NULL); csname[i] = add_gbuf("{"); cscode[i++] = BGROUP; csname[i] = add_gbuf("}"); cscode[i++] = EGROUP; start_type1code = i; csname[i] = add_gbuf("hstem"); cscode[i++] = HSTEM; csname[i] = add_gbuf("vstem"); cscode[i++] = VSTEM; csname[i] = add_gbuf("vmoveto"); cscode[i++] = VMOVETO; csname[i] = add_gbuf("rlineto"); cscode[i++] = RLINETO; csname[i] = add_gbuf("hlineto"); cscode[i++] = HLINETO; csname[i] = add_gbuf("vlineto"); cscode[i++] = VLINETO; csname[i] = add_gbuf("rrcurveto"); cscode[i++] = RRCURVETO; csname[i] = add_gbuf("closepath"); cscode[i++] = CLOSEPATH; csname[i] = add_gbuf("callsubr"); cscode[i++] = CALLSUBR; csname[i] = add_gbuf("return"); cscode[i++] = RETURN; csname[i] = add_gbuf("escape"); cscode[i++] = ESCAPE; csname[i] = add_gbuf("hsbw"); cscode[i++] = HSBW; csname[i] = add_gbuf("endchar"); cscode[i++] = ENDCHAR; csname[i] = add_gbuf("rmoveto"); cscode[i++] = RMOVETO; csname[i] = add_gbuf("hmoveto"); cscode[i++] = HMOVETO; csname[i] = add_gbuf("vhcurveto"); cscode[i++] = VHCURVETO; csname[i] = add_gbuf("hvcurveto"); cscode[i++] = HVCURVETO; csname[i] = add_gbuf("dotsection"); cscode[i++] = DOTSECTION; csname[i] = add_gbuf("vstem3"); cscode[i++] = VSTEM3; csname[i] = add_gbuf("hstem3"); cscode[i++] = HSTEM3; csname[i] = add_gbuf("seac"); cscode[i++] = SEAC; csname[i] = add_gbuf("sbw"); cscode[i++] = SBW; csname[i] = add_gbuf("div"); cscode[i++] = DIV; csname[i] = add_gbuf("callothersubr"); cscode[i++] = CALLOTHERSUBR; csname[i] = add_gbuf("pop"); cscode[i++] = POP; csname[i] = add_gbuf("setcurrentpoint"); cscode[i++] = SETCURRENTPOINT; csname[i] = add_gbuf("moveto"); cscode[i++] = MOVETO; csname[i] = add_gbuf("lineto"); cscode[i++] = LINETO; csname[i] = add_gbuf("curveto"); cscode[i++] = CURVETO; csname[i] = add_gbuf("rcurveto"); cscode[i++] = RCURVETO; csname[i] = add_gbuf("scaled"); cscode[i++] = SCALED; csname[i] = add_gbuf("vvaxis"); cscode[i++] = VVAXIS; last_csname=i-1; buf[MAXBUF-1] = 0; } /* The decrypting algorithm from pfb is token over the t1disasm from t1utils by I. Lee Hetherington */ int immediate_eexec; /* int32 must be at least 32-bit and uint16 must be at least 16-bit */ #if INT_MAX >= 0x7FFFFFFFUL typedef int int32; #else typedef long int32; #endif #if USHRT_MAX >= 0xFFFFUL typedef unsigned short uint16; #else typedef unsigned int uint16; #endif typedef unsigned char byte; static uint16 er, cr; static uint16 c1 = 52845, c2 = 22719; int first_byte; int is_pfb; int32 pfb_remaining; int in_eexec; int savedchar, is_textspace; #define cgetc() cdecrypt((byte) (egetc() & 0xff)) static int bgetc() { /* returns a single character at a time from a PFB file. This stream is mixed ASCII and binary bytes. The section headers are removed, and \r is replaced by \n in ASCII sections. */ int c; c = fgetc(fpfb); if (c == EOF) { fprintf(stderr,"remaining = %d", pfb_remaining); return EOF; } if (first_byte) { /* Determine if this is a PFB file by looking at first byte. */ if (c != 0x80) error ("the file %s is not in pfb format", fname); first_byte = 0; } /* PFB */ if (pfb_remaining == 0) { /* beginning of block---we know c == 0x80 at this point */ c = fgetc(fpfb); switch (c) { case 1: is_pfb = 1; break; case 2: is_pfb = 2; break; case 3: return EOF; default: error("the file %s is not in PFB format", fname); } /* get block length */ pfb_remaining = (int32) (fgetc(fpfb) & 0xff); pfb_remaining |= (int32) (fgetc(fpfb) & 0xff) << 8; pfb_remaining |= (int32) (fgetc(fpfb) & 0xff) << 16; pfb_remaining |= (int32) (fgetc(fpfb) & 0xff) << 24; /* get character */ c = fgetc(fpfb); if (c == EOF) return EOF; } --pfb_remaining; /* in ASCII section change return to newline */ if (is_pfb == 1 && c == '\r') { c = fgetc(fpfb); if (c != '\n') { ungetc(c, fpfb); c = '\n' ; } else --pfb_remaining; } return c; } static byte edecrypt(byte cipher) { /* an eexec decryption */ byte plain; plain = (byte) (cipher ^ (er >> 8)); er = (uint16) ((cipher + er) * c1 + c2); return plain; } static byte cdecrypt(byte cipher) { /* a CharString decryption */ byte plain; plain = (byte) (cipher ^ (cr >> 8)); cr = (uint16) ((cipher + cr) * c1 + c2); return plain; } static int egetc() { /* returns a single byte at a time through (possible) eexec decryption. When immediate_eexec is 1 it fires up the eexec decryption machinery. */ int c; if (savedchar >= 0) { c = savedchar; savedchar = -1; return c; } if ((c = bgetc()) == EOF) return EOF; if (!in_eexec) { if (immediate_eexec) { /* start eexec decryption */ in_eexec = 1; er = 55665; /* toss out four random bytes */ (void) edecrypt((byte) (bgetc() & 0xff)); (void) edecrypt((byte) (bgetc() & 0xff)); (void) edecrypt((byte) (bgetc() & 0xff)); (void) edecrypt((byte) (bgetc() & 0xff)); } return c; } else { c = edecrypt((byte) (c & 0xff)); if (is_textspace && c == '\r') { if ((c = bgetc()) == EOF) return EOF; c = edecrypt((byte) (c & 0xff)); if (c!='\n') { savedchar = c; c = '\n'; } } return c; } } int Fgetc (FILE *fh) { /* This is a low level input filter for config file. It transforms white space to space and ignores a % comment */ int c; restart: c = fgetc(fh); if (c=='\n') line++; if (c=='\t' || c=='\r' || c=='\n' || c==0) c = ' '; if (c=='%') { while (c!='\n' && c!=EOF) c = fgetc(fh); line++; if (c=='\n') goto restart; } return c; } void store_stack(float val) { /* stores one value to rs[] stack */ if (prst>=MAXSTACK) error ("stack overflow", NULL); rs[prst++] = val; } int read_token(FILE *fh, int status) { /* reads one token (word or number separated by white space) from input stream. If status then function returns the number of control sequence. The value stores into stack. */ int c, p; c = ' '; buf[0] = 0; while (c==' ') c = Fgetc(fh); if (c==EOF) return EOF; p = 0; while (c!=' ' && c!=EOF) { if (p>MAXBUF-2) error("control sequence '%s' too long", buf); buf[p++] = c; c = Fgetc(fh); } buf[p] = 0; if (status == 0) return 0; p = 0; if (buf[0] == '-') p = 1; if (isdigit(buf[p]) || (buf[p]=='.' && isdigit(buf[p+1]))) { store_stack (atof(buf)); return VALUE; } for (p=0;p operands from rs[] stack plus one operator declared by 'code'. save_code() does an optimalisation of code (rlineto -> hlineto) too. */ int i, x, y; if (MAXIMEM-pim prst) num = prst; prst -= num; switch (code) { /* optimalisation */ case RMOVETO: x = rs[prst]; y = rs[prst+1]; if (x==0 && y==0) break; if (x==0) { imem[pim++] = y; imem[pim++] = MAGIC; imem[pim++] = VMOVETO; } if (y==0) { imem[pim++] = x; imem[pim++] = MAGIC; imem[pim++] = HMOVETO; } if (x!=0 && y!=0) { imem[pim++] = x; imem[pim++] = y; imem[pim++] = MAGIC; imem[pim++] = RMOVETO; } break; case RLINETO: x = rs[prst]; y = rs[prst+1]; if (x==0 && y==0) break; if (x==0) { imem[pim++] = y; imem[pim++] = MAGIC; imem[pim++] = VLINETO; } if (y==0) { imem[pim++] = x; imem[pim++] = MAGIC; imem[pim++] = HLINETO; } if (x!=0 && y!=0) { imem[pim++] = x; imem[pim++] = y; imem[pim++] = MAGIC; imem[pim++] = RLINETO; } break; case RRCURVETO: x = rs[prst]; y = rs[prst+5]; if (x==0 && y==0) { imem[pim++] = rs[prst+1]; imem[pim++] = rs[prst+2]; imem[pim++] = rs[prst+3]; imem[pim++] = rs[prst+4]; imem[pim++] = MAGIC; imem[pim++] = VHCURVETO; break; } y = rs[prst+1]; x = rs[prst+4]; if (x==0 && y==0) { imem[pim++] = rs[prst]; imem[pim++] = rs[prst+2]; imem[pim++] = rs[prst+3]; imem[pim++] = rs[prst+5]; imem[pim++] = MAGIC; imem[pim++] = HVCURVETO; break; } default: for (i=0;iMAXINFILES-2) error ("MAXINFILES (max number of IN files) overflow", NULL); infile[numfiles++] = add_gbuf(buf); } } void read_enc(void) { /* reads an ENC declaration plus .enc file */ int c, p, code, saveline; if(encisread) error("second ENC declaration is not allowed", NULL); if(read_token(fin,0)==EOF) error("unexcepted end of file", NULL); if(strlen(buf) > MAXBUF-5) error("ENC file name is too long (%s)", buf); strcat(buf, ".enc"); strcpy(fname, buf); fenc = fopen(fname, "r"); if (!fenc) error("cannot open %s for reading\n", fname); saveline = line; line = 1; c = 0; while (c!='[' && c!=EOF) c = Fgetc(fenc); if (c==EOF) error ("no '[' in encoding file %s", fname); code = 0; while (1) { while (c!='/' && c!=']' && c!=EOF) c = Fgetc(fenc); if (c==EOF) error ("unexpected end of encoding file %s", fname); if (c==']' && code==256) break; if (c==']') error ("less than 256 entries in encoding vector (/%s)",buf); p=0; c = Fgetc(fenc); while (c!=' ' && c!='/' && c!=EOF) { if (p>MAXBUF-2) error ("too long char name (%s) in enc file", buf); buf[p++] = c; c = Fgetc(fenc); } if (p==0) error ("empty char name in enc. file %s", fname); if (code > 255) error ("more than 256 entries in encoding vector (/%s)",buf); buf[p] = 0; if (strcmp(buf,".notdef")==0) encvector[code++] = NULL; else encvector[code++] = add_gbuf(buf); } fclose(fenc); line = saveline; encisread=1; } void read_rem(void) { /* reads a remark string */ int c; c = ' '; while (c==' ') c = Fgetc(fin); if (c != '"') error ("the '\"' (begin of string) after REM expected", NULL); if (numrems >= MAXREMARKS) error ("MAXREMARKS (maximum REM lines) exceeded", NULL); remark[numrems++] = pbuf; while ((c=Fgetc(fin)) != '"' && c != EOF && pbuf < &gbuf[MAXGBUF]) { pbuf[0] = c; pbuf++; } if (c == EOF) error ("the REM string is unterminated", NULL); if (pbuf == &gbuf[MAXGBUF]) error ("MAXGBUF overflow during REM reading", NULL); store_gbuf(0); } void read_var(void) { /* reads the VAR declaration from config file */ int c; c = ' '; while (c==' ') c = Fgetc(fin); if (c!='/') error("the /name of variable expected", NULL); read_token(fin, 0); if (buf[0]==0) error("empty /name of variable", NULL); variable[numvars].name = add_gbuf(buf); if (read_token(fin,1) != VALUE) error("the number expected (%s)", buf); variable[numvars++].value = rs[--prst]; return; } void read_src(void) { if(srcisread) error("second SRC declaration is not allowed", NULL); read_token(fin, 0); srcdir = add_gbuf(buf); srcisread = 1; } void read_name(void) { if(nameisread) error("second NAME declaration is not allowed", NULL); read_token(fin, 0); oriname = add_gbuf(buf); read_token(fin, 0); if (strcmp (buf, "->") != 0) error("the '->' expected", NULL); read_token(fin, 0); newname = add_gbuf(buf); diffname = strlen(newname) - strlen(oriname); nameisread = 1; } void read_bbox(void) { int i=0; if (read_token(fin,1) != VALUE) i = 1; if (read_token(fin,1) != VALUE) i = 1; if (read_token(fin,1) != VALUE) i = 1; if (read_token(fin,1) != VALUE) i = 1; if (i) error("the number expected (%s)", buf); glX = min(glX, rs[prst-4]); glY = min(glY, rs[prst-3]); guX = max(guX, rs[prst-2]); guY = max(guY, rs[prst-1]); prst = 0; } void read_sub(void) { /* reads the SUB declaration from config file */ int c; c = ' '; while (c==' ') c = Fgetc(fin); if (c!='/') error("the /name of subroutine expected", NULL); read_token(fin, 0); if (buf[0]==0) error("empty /name of subroutine", NULL); if (numsubs>=MAXSUBS) error ("MAXSUBS (number of SUB's) exceeded", NULL); subr[numsubs].name = add_gbuf(buf); c = ' '; while (c==' ') c = Fgetc(fin); if (c!='{') error("the '{' expected", NULL); read_code(1); return; } void read_char(void) { /* reads the CHAR declaration from config file */ int c, p; c = ' '; while (c==' ') c = Fgetc(fin); if (c!='/') error("the /name of new char expected", NULL); read_token(fin, 0); if (buf[0]==0) error("empty /name new char", NULL); newchar[numchars].name = add_gbuf(buf); c = ' '; while (c==' ') c = Fgetc(fin); if (c=='{') { read_code(0); newchar[numchars].nsub = -1; newchar[numchars++].origname = NULL; return; } if (c!='/') error("the /name of base char or '{' expected", NULL); read_token(fin, 0); if (buf[0]==0) error("empty /name of base char", NULL); newchar[numchars].origname = add_gbuf(buf); newchar[numchars].owncode = 0; c = ' '; while (c==' ') c = Fgetc(fin); if (c!='/') { ungetc(c, fin); if (read_token(fin, 1) != VALUE) error("value or /name of subroutine expected (%s)", buf); if (read_token(fin, 1) != VALUE) error("value expected (%s)", buf); if (read_token(fin, 1) != VALUE) error("value expected (%s)", buf); prst -= 3; newchar[numchars].dsbx = rs[prst]; newchar[numchars].dy = rs[prst+1]; newchar[numchars].dwx = rs[prst+2]; read_token(fin, 0); if (strcmp(buf,"correct")!=0) error("the correct operator expected (%s)", buf); c = ' '; while (c==' ') c = Fgetc(fin); } else newchar[numchars].dsbx = newchar[numchars].dwx = newchar[numchars].dy = 0; if (c!='/') error("the /name of subroutine expected (%s)", buf); read_token(fin, 0); if (buf[0]==0) error("empty /name of subroutine", NULL); newchar[numchars].nsub = -1; if (strcmp(buf,".noinsert")==0) { numchars++; return; } for(p=0;p=0) { glY = min(glY, subr[newchar[i].nsub].ly + newchar[i].y + newchar[i].dy); guY = max(guY, subr[newchar[i].nsub].uy + newchar[i].y + newchar[i].dy); } } unsigned int convert_code(unsigned char* st, int l) { /* converts the decrypted CharString or Subrs from per-byte format to imem[] format. */ int p; int32 val; int b; unsigned int out; out = pim; for (p=0; p= 32) { if (b >= 32 && b <= 246) val = b - 139; else if (b >= 247 && b <= 250) val = (b - 247)*256 + 108 + st[++p]; else if (b >= 251 && b <= 254) val = -(b - 251)*256 - 108 - st[++p]; else { val = (st[++p] & 0xff) << 24; val |= (st[++p] & 0xff) << 16; val |= (st[++p] & 0xff) << 8; val |= (st[++p] & 0xff) << 0; /* in case an int32 is larger than four bytes---sign extend */ #if MAX_INT > 0x7FFFFFFFUL for (i = 4; i < sizeof(int32); i++) val |= 0xff << (i * 8); #endif } imem[pim++] = val; } else { imem[pim++] = MAGIC; if (b==12) b = 100*b + st[++p]; imem[pim++] = b; } if (pim >= MAXIMEM-5) error ("imem[MAXIMEM] overflow", NULL); } imem[pim++] = MAGIC; imem[pim++] = MAGIC; topim = pim; return out; } void insert_newcode (unsigned int pim, int p) { /* insert a new code: dx dy rmoveto num callsubr -dx -dy rmoveto into code at imem[i] and does some optimalisation */ unsigned int npim, lpim, i; int dx, dy, wx, sbx, c, shift; int tmem[] = {0, 0, MAGIC, RMOVETO, 0, MAGIC, CALLSUBR, 0, 0, MAGIC, RMOVETO}; lpim = 11; wx = MAGIC; sbx = 0; while (1) { c = imem[pim++]; if (c != MAGIC) continue; c = imem[pim++]; if (c==VSTEM || c==VSTEM3 || c==DIV) continue; if (c==HSTEM) { imem[pim-4] += newchar[p].dy; continue; } if (c==HSTEM3) { imem[pim-8] += newchar[p].dy; imem[pim-6] += newchar[p].dy; imem[pim-4] += newchar[p].dy; continue; } if (c==HSBW) { if (imem[pim-4]==MAGIC && imem[pim-3]==DIV) { imem[pim-6] += newchar[p].dwx * imem[pim-5]; wx = imem[pim-6] / imem[pim-5]; imem[pim-7] += newchar[p].dsbx; sbx = imem[pim-7]; } else { imem[pim-3] += newchar[p].dwx; wx = imem[pim-3]; imem[pim-4] += newchar[p].dsbx; sbx = imem[pim-4]; } continue; } if (c==SEAC || c==SBW) { fprintf (stderr,"\nWarning: seac or sbw in base char, /%s unchanged\n", newchar[p].name); return; } if (c==MAGIC) { fprintf(stderr, "\nWarning: the /%s is unchanged\n", newchar[p].name); return; } if (wx==MAGIC) { fprintf (stderr,"\nWarning: hsbw not found in base char, /%s unchanged\n", newchar[p].name); return; } if (newchar[p].nsub == -1) { if (newchar[p].dy == 0) return; tmem[0] = 0; tmem[1] = newchar[p].dy; tmem[2] = MAGIC; tmem[3] = RMOVETO; lpim = 4; } else { dx = newchar[p].x; dy = newchar[p].y + newchar[p].dy; if (newchar[p].type == PUTORIGIN) dx -= sbx; if (newchar[p].type == PUTCENTER) dx += wx/2 - sbx - subr[newchar[p].nsub].vvaxis; if (newchar[p].type == PUTAFTER) dx += wx-sbx; if (dx == 0 && dy == 0) { /* remove rmoveto */ tmem[0] = newchar[p].nsub + pfbnumsubs; tmem[1] = MAGIC; tmem[2] = CALLSUBR; tmem[3] = 0; tmem[4] = newchar[p].dy; tmem[5] = MAGIC; tmem[6] = RMOVETO; lpim = 7; } else if (dx == 0) { /* rmoveto -> vmoveto */ tmem[0] = dy; tmem[1] = MAGIC; tmem[2] = VMOVETO; tmem[3] = newchar[p].nsub + pfbnumsubs; tmem[4] = MAGIC; tmem[5] = CALLSUBR; tmem[6] = 0; tmem[7] = -dy + newchar[p].dy; tmem[8] = MAGIC; tmem[9] = RMOVETO; lpim = 10; } else if (dy == 0) { /* rmoveto -> hmoveto */ tmem[0] = dx; tmem[1] = MAGIC; tmem[2] = HMOVETO; tmem[3] = newchar[p].nsub + pfbnumsubs; tmem[4] = MAGIC; tmem[5] = CALLSUBR; tmem[6] = -dx; tmem[7] = newchar[p].dy; tmem[8] = MAGIC; tmem[9] = RMOVETO; lpim = 10; } else { /* default */ tmem[0] = dx; tmem[1] = dy; tmem[4] = newchar[p].nsub + pfbnumsubs; tmem[7] = -dx; tmem[8] = -dy + newchar[p].dy; } } if (c==RMOVETO) { /* next command is rmoveto */ tmem[lpim-4] += imem[pim-4] ; tmem[lpim-3] += imem[pim-3] ; npim = pim - 4; } else if (c==VMOVETO) { /* next command is vmoveto */ tmem[lpim-3] += imem[pim-3] ; npim = pim - 3; } else if (c==HMOVETO) { /* next command is hmoveto */ tmem[lpim-4] += imem[pim-3]; npim = pim - 3; } else { /* next command is another */ pim -= 3; while (imem[pim] != MAGIC && pim >= fixpim) pim--; if (imem[pim] != MAGIC) error ("something wrong", NULL); pim += 2; npim = pim; } dx = tmem[lpim-4]; dy = tmem[lpim-3]; if (dx == 0 && dy == 0) lpim -=4 ; /* new rmoveto is irrelevant */ else if (dx == 0) { /* new vmoveto */ tmem[lpim-4] = dy; tmem[lpim-3] = MAGIC; tmem[lpim-2] = VMOVETO; lpim--; } else if (dy == 0) { /* new hmoveto */ tmem[lpim-3] = MAGIC; tmem[lpim-2] = HMOVETO; lpim--; } shift = lpim - (pim - npim); if (topim+shift >= MAXIMEM) error ("MAXIMEM overflow", NULL); if (shift < 0) for (i=pim; i 0) for (i=topim-1; i>=pim; i--) imem[i+shift] = imem[i]; topim += shift; for (i=0; i0 && buf[p] != ' ') p--; if (p==0) error ("the %s parameter not found", RDcommand); l = atoi (&buf[p]); l -= lenIV; getpfb(); /* ignore the space after RDcommand */ if (status==SAVECHAR) { while(p>=0 && buf[p] == ' ') p--; if (p<0) error ("the CharName not found", NULL); buf[p+1] = 0; savedchars[num].name = add_gbuf(buf); savedchars[num].code = pbuf; savedchars[num].len = l; } else { savedsubr[num].len = l; savedsubr[num].code = pbuf; } is_textspace = 0; cr = 4330; for (p=0; p pbuf && found[0]!='/') found--; if (found==pbuf) error ("'/?? {%s...' not found",text); found++; p = 0; while (p<3 && found[p]!=' ' && found[p]!='{') command[p] = found[p++]; if (p==3) error ("'/?? {%s...' must be two character string", text); command[p] = 0; } void replace_name (void) { unsigned char *lbuf; int i, len; if (!nameisread) return; lbuf = strstr (pbuf, oriname); while (lbuf) { if (diffname > 0) { i = strlen(lbuf); while (i>0) lbuf[i+diffname] = lbuf[i--]; } if (diffname < 0) { i = -diffname; while (lbuf[i]) lbuf[i+diffname] = lbuf[i++]; lbuf[i+diffname] = 0; } len = strlen(newname); for (i=0; i MAXBUF-5) error("pfb file name is too long (%s)",fname); strcat(fname, ".pfb"); if (srcisread) { if (strlen(srcdir)+strlen(fname) >= MAXBUF) error("dirname+pfb file name is too long (%s)",srcdir); strcpy (buf, fname); strcpy (fname, srcdir); strcat (fname, buf); } fpfb = fopen(fname, "rb"); if (!fpfb) error("cannot open pfb file %s", fname); fprintf (stderr, "(%s", fname); strcpy (buf, infile[p]); strcat(buf,".pps"); fpps = fopen(buf, "w"); if (!fpps) error("cannot write to file %s", buf); convert_pfb(); fclose(fpfb); fclose(fpps); fprintf (stderr, "->%s.pps)\n", infile[p]); } return 0; }