/** * $Id:$ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * The contents of this file may be used under the terms of either the GNU * General Public License Version 2 or later (the "GPL", see * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or * later (the "BL", see http://www.blender.org/BL/ ) which has to be * bought from the Blender Foundation to become active, in which case the * above mentioned GPL option does not apply. * * The Original Code is Copyright (C) 2002 by NaN Holding BV. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ /* * fromtype1 - * Convert an Adobe type 1 font into .of or .sf format. * * Paul Haeberli - 1990 * Version: $Id: psfont.c,v 1.4 2000/07/21 09:05:28 nzc Exp $ */ #include "blender.h" #include "objfnt.h" #define SKIP 4 #define LINELEN 2048 #define NOTHEX (100) #define MC1 52845 #define MC2 22719 #define MAXSUBRS 1000 #define MAXCHARS 1000 #define MAXTRIES 30 static void rcurveto( int dx1, int dy1, int dx2, int dy2, int dx3, int dy3); void makeobjfont(int savesplines); static void drawchar(int c); static void runprog(); static int startx, starty; static int curx, cury; static int nextx, nexty; static int delx, dely; static int started; /* postscript commands */ #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 HSBW (13) #define ENDCHAR (14) #define RMOVETO (21) #define HMOVETO (22) #define VHCURVETO (30) #define HVCURVETO (31) #define DOTSECTION (256+0) #define VSTEM3 (256+1) #define HSTEM3 (256+2) #define SEAC (256+6) #define SBW (256+7) #define DIV (256+12) #define CALLOTHERSUBR (256+16) #define POP (256+17) #define SETCURRENTPOINT (256+33) #define WHAT0 (0) char oneline[LINELEN]; objfnt *fnt; unsigned short int mr; char *bindat; int datbytes; int firsted; short chardata[2000]; int nshorts; int thecharwidth, thesidebearing; int npnts, nloops; int nvertpos; int fakepos; int fakemax; float beztol = 100.0; /* extern: uit de libfm */ char *my_subrs[MAXSUBRS]; unsigned int my_sublen[MAXSUBRS]; char *my_chars[MAXCHARS]; unsigned int my_charlen[MAXCHARS]; char *my_charname[MAXCHARS]; int my_nsubrs, my_nchars; short sidebearing[MAXCHARS]; char tok[LINELEN]; int sp_npnts, sp_nloops; /* * interpreter globals */ float mat[2][2]; char *pcstack[100]; char *pc; int pcsp; int coordpos; int coordsave[7][2]; int incusp; int retstack[1000]; int retsp; int stack[1000]; int sp; int savesplines = 1; pschar ISOcharlist[NASCII] = { "/space", 040, 0, "/exclam", 041, 0, "/quotedbl", 042, 0, "/numbersign", 043, 0, "/dollar", 044, 0, "/percent", 045, 0, "/ampersand", 046, 0, "/quoteright", 047, 0, "/parenleft", 050, 0, "/parenright", 051, 0, "/asterisk", 052, 0, "/plus", 053, 0, "/comma", 054, 0, "/hyphen", 055, 0, "/period", 056, 0, "/slash", 057, 0, "/zero", 060, 0, "/one", 061, 0, "/two", 062, 0, "/three", 063, 0, "/four", 064, 0, "/five", 065, 0, "/six", 066, 0, "/seven", 067, 0, "/eight", 070, 0, "/nine", 071, 0, "/colon", 072, 0, "/semicolon", 073, 0, "/less", 074, 0, "/equal", 075, 0, "/greater", 076, 0, "/question", 077, 0, "/at", 0100, 0, "/A", 0101, 0, "/B", 0102, 0, "/C", 0103, 0, "/D", 0104, 0, "/E", 0105, 0, "/F", 0106, 0, "/G", 0107, 0, "/H", 0110, 0, "/I", 0111, 0, "/J", 0112, 0, "/K", 0113, 0, "/L", 0114, 0, "/M", 0115, 0, "/N", 0116, 0, "/O", 0117, 0, "/P", 0120, 0, "/Q", 0121, 0, "/R", 0122, 0, "/S", 0123, 0, "/T", 0124, 0, "/U", 0125, 0, "/V", 0126, 0, "/W", 0127, 0, "/X", 0130, 0, "/Y", 0131, 0, "/Z", 0132, 0, "/bracketleft", 0133, 0, "/backslash", 0134, 0, "/bracketright", 0135, 0, "/asciicircum", 0136, 0, "/underscore", 0137, 0, "/quoteleft", 0140, 0, "/a", 0141, 0, "/b", 0142, 0, "/c", 0143, 0, "/d", 0144, 0, "/e", 0145, 0, "/f", 0146, 0, "/g", 0147, 0, "/h", 0150, 0, "/i", 0151, 0, "/j", 0152, 0, "/k", 0153, 0, "/l", 0154, 0, "/m", 0155, 0, "/n", 0156, 0, "/o", 0157, 0, "/p", 0160, 0, "/q", 0161, 0, "/r", 0162, 0, "/s", 0163, 0, "/t", 0164, 0, "/u", 0165, 0, "/v", 0166, 0, "/w", 0167, 0, "/x", 0170, 0, "/y", 0171, 0, "/z", 0172, 0, "/braceleft", 0173, 0, "/bar", 0174, 0, "/braceright", 0175, 0, "/asciitilde", 0176, 0, "/", 0177, 0, /* nonstandard defs */ "/quotedblleft", 0200, 0, "/quotedblright", 0201, 0, "/quotedblbase", 0202, 0, "/quotesinglbase", 0203, 0, "/guilsinglleft", 0204, 0, "/guilsinglright", 0205, 0, "/endash", 0206, 0, "/dagger", 0207, 0, "/daggerdbl", 0210, 0, "/trademark", 0211, 0, "/bullet", 0212, 0, "/perthousand", 0213, 0, "/Lslash", 0214, 0, "/OE", 0215, 0, "/lslash", 0216, 0, "/oe", 0217, 0, /* endnonstandard defs */ "/dotlessi", 0220, 0, "/grave", 0221, 0, "/acute", 0222, 0, "/circumflex", 0223, 0, "/tilde", 0224, 0, "/", 0225, 0, "/breve", 0226, 0, "/dotaccent", 0227, 0, "/", 0230, 0, "/", 0231, 0, "/ring", 0232, 0, "/", 0233, 0, "/", 0234, 0, "/hungarumlaut", 0235, 0, "/ogonek", 0236, 0, "/caron", 0237, 0, "/", 0240, 0, "/exclamdown", 0241, 0, "/cent", 0242, 0, "/sterling", 0243, 0, "/florin", 0244, 0, "/yen", 0245, 0, "/brokenbar", 0246, 0, "/section", 0247, 0, "/dieresis", 0250, 0, "/copyright", 0251, 0, "/ordfeminine", 0252, 0, "/guillemotleft", 0253, 0, "/logicalnot", 0254, 0, "/hyphen", 0255, 0, "/registered", 0256, 0, "/macron", 0257, 0, "/degree", 0260, 0, "/plusminus", 0261, 0, "/twosuperior", 0262, 0, "/threesuperior", 0263, 0, "/acute", 0264, 0, "/mu", 0265, 0, "/paragraph", 0266, 0, "/periodcentered", 0267, 0, "/cedilla", 0270, 0, "/onesuperior", 0271, 0, "/ordmasculine", 0272, 0, "/guillemotright", 0273, 0, "/onequarter", 0274, 0, "/onehalf", 0275, 0, "/threequarters", 0276, 0, "/questiondown", 0277, 0, "/Agrave", 0300, 0, "/Aacute", 0301, 0, "/Acircumflex", 0302, 0, "/Atilde", 0303, 0, "/Adieresis", 0304, 0, "/Aring", 0305, 0, "/AE", 0306, 0, "/Ccedilla", 0307, 0, "/Egrave", 0310, 0, "/Eacute", 0311, 0, "/Ecircumflex", 0312, 0, "/Edieresis", 0313, 0, "/Igrave", 0314, 0, "/Iacute", 0315, 0, "/Icircumflex", 0316, 0, "/Idieresis", 0317, 0, "/Eth", 0320, 0, "/Ntilde", 0321, 0, "/Ograve", 0322, 0, "/Oacute", 0323, 0, "/Ocircumflex", 0324, 0, "/Otilde", 0325, 0, "/Odieresis", 0326, 0, "/multiply", 0327, 0, "/Oslash", 0330, 0, "/Ugrave", 0331, 0, "/Uacute", 0332, 0, "/Ucircumflex", 0333, 0, "/Udieresis", 0334, 0, "/Yacute", 0335, 0, "/Thorn", 0336, 0, "/germandbls", 0337, 0, "/agrave", 0340, 0, "/aacute", 0341, 0, "/acircumflex", 0342, 0, "/atilde", 0343, 0, "/adieresis", 0344, 0, "/aring", 0345, 0, "/ae", 0346, 0, "/ccedilla", 0347, 0, "/egrave", 0350, 0, "/eacute", 0351, 0, "/ecircumflex", 0352, 0, "/edieresis", 0353, 0, "/igrave", 0354, 0, "/iacute", 0355, 0, "/icircumflex", 0356, 0, "/idieresis", 0357, 0, "/eth", 0360, 0, "/ntilde", 0361, 0, "/ograve", 0362, 0, "/oacute", 0363, 0, "/ocircumflex", 0364, 0, "/otilde", 0365, 0, "/odieresis", 0366, 0, "/divide", 0367, 0, "/oslash", 0370, 0, "/ugrave", 0371, 0, "/uacute", 0372, 0, "/ucircumflex", 0373, 0, "/udieresis", 0374, 0, "/yacute", 0375, 0, "/thorn", 0376, 0, "/ydieresis", 0377, 0, }; short STDvsISO [][2] = { 0341, 0306, /* AE */ 0351, 0330, /* Oslash */ 0302, 0222, /* acute */ 0361, 0346, /* ae */ 0306, 0226, /* breve */ 0317, 0237, /* caron */ 0313, 0270, /* cedilla */ 0303, 0223, /* circumflex */ 0250, 0244, /* currency */ 0310, 0250, /* dieresis */ 0307, 0227, /* dotaccent */ 0365, 0220, /* dotlessi */ 0373, 0337, /* germandbls */ 0301, 0221, /* grave */ 0315, 0235, /* hungarumlaut */ 0055, 0255, /* hyphen */ 0305, 0257, /* macron */ 0316, 0236, /* ogenek */ 0343, 0252, /* ordfeminine */ 0353, 0272, /* ordmasculine */ 0371, 0370, /* oslash */ 0264, 0267, /* periodcentered */ 0312, 0232, /* ring */ 0304, 0224, /* tilde */ }; /* from objfont.c de rest zit in lfm_s !!*/ /* START 5.2 */ static void applytocharverts(objfnt *fnt, int c, int (*func)()) { int index; chardesc *cd; short *sptr; int nverts; index = chartoindex(fnt,c); if(index<0) return; cd = fnt->my_chars+index; if(cd->data) { sptr = cd->data; switch(fnt->type) { case TM_TYPE: while(1) { switch(*sptr++) { case TM_BGNTMESH: case TM_SWAPTMESH: case TM_ENDBGNTMESH: break; case TM_RETENDTMESH: case TM_RET: return; } nverts = *sptr++; while(nverts--) { (func)(sptr); sptr+=2; } } break; case PO_TYPE: while(1) { switch(*sptr++) { case PO_BGNLOOP: case PO_ENDBGNLOOP: break; case PO_RETENDLOOP: case PO_RET: return; break; } nverts = *sptr++; while(nverts--) { (func)(sptr); sptr+=2; } } break; case SP_TYPE: while(1) { switch(*sptr++) { case SP_MOVETO: (func)(sptr); sptr+=2; break; case SP_LINETO: (func)(sptr); sptr+=2; break; case SP_CURVETO: (func)(sptr+0); (func)(sptr+2); (func)(sptr+4); sptr+=6; break; case SP_CLOSEPATH: break; case SP_RETCLOSEPATH: return; break; case SP_RET: return; break; } } break; default: fprintf(stderr,"applytocharverts: bad obj font type\n"); } } } int chartoindex(objfnt *fnt, int c) { if(ccharmin) return -1; if(c>fnt->charmax) return -1; return c-fnt->charmin; } chardesc *getchardesc(objfnt *fnt, int c) { int index; index = chartoindex(fnt,c); if(index<0) return 0; return fnt->my_chars+index; } static int xmin, xmax, ymin, ymax; static int bboxcalc(short v[2]) { if(v[0]xmax) xmax = v[0]; if(v[1]>ymax) ymax = v[1]; return 0; } static void calccharbboxes(objfnt *fnt) { int c; chardesc *cd; for(c=fnt->charmin; c<=fnt->charmax; c++) { xmin = ymin = NOBBOX; xmax = ymax = -NOBBOX; applytocharverts(fnt, c, bboxcalc); cd = getchardesc(fnt,c); if(xmin == NOBBOX) { cd->llx = NOBBOX; cd->lly = NOBBOX; cd->urx = NOBBOX; cd->ury = NOBBOX; } else { cd->llx = xmin; cd->lly = ymin; cd->urx = xmax; cd->ury = ymax; } } } objfnt *newobjfnt(int type, int charmin, int charmax, int fscale) { objfnt *fnt; short *sptr; int i; fnt = (objfnt *)mallocN(sizeof(objfnt), "newobjfnt"); fnt->freeaddr = 0; fnt->type = type; fnt->charmin = charmin; fnt->charmax = charmax; fnt->my_nchars = fnt->charmax-fnt->charmin+1; fnt->scale = fscale; fnt->my_chars = (chardesc *)mallocN(fnt->my_nchars*sizeof(chardesc), "newobjfnt2"); bzero(fnt->my_chars,fnt->my_nchars*sizeof(chardesc)); return fnt; } static void addchardata (objfnt * fnt, int c, short * data, int nshorts) { int index; chardesc *cd; index = chartoindex(fnt,c); if(index<0) { fprintf(stderr,"Addchardata bad poop\n"); return; } cd = fnt->my_chars+index; fnt->freeaddr = 0; cd->datalen = nshorts*sizeof(short); cd->data = (short *)mallocN(cd->datalen, "addchardata"); bcopy(data,cd->data,cd->datalen); } static void addcharmetrics(objfnt *fnt, int c, int movex, int movey) { int index; chardesc *cd; index = chartoindex(fnt,c); if(index<0) { fprintf(stderr,"Addcharmetrics bad poop\n"); return; } cd = fnt->my_chars+index; cd->movex = movex; cd->movey = movey; } static void fakechar(objfnt *fnt, int c, int width) { short chardata[1]; chardata[0] = PO_RET; addchardata(fnt,c,chardata,1); addcharmetrics(fnt,c,width,0); } void freeobjfnt(objfnt * fnt) { int i; chardesc *cd; cd = fnt->my_chars; for(i=0; imy_nchars; i++) { if(cd->data) freeN(cd->data); cd++; } freeN(fnt->my_chars); freeN(fnt); } /* END 5.2 */ int sizeoffile(FILE * f) { register int pos, ret; pos = ftell(f); if ((ret = fseek(f,0,2)) < 0) { fprintf(stderr,"sizeoffile: seek error\n"); return(0); } ret = ftell(f); if (fseek(f,pos,0) < 0) { fprintf(stderr,"sizeoffile: seek error\n"); return(0); } return ret; } short STDtoISO(short c) { short i = (sizeof(STDvsISO) / (2 * sizeof(short))) - 1; for (;i >= 0; i--){ if (STDvsISO[i][0] == c) return (STDvsISO[i][1]); } return(c); } /* * read the font matrix out of the font file * */ char * newfgets(char * s, int n, PackedFile * pf){ int read = 0; int c; char * p; p = s; while (n > 0){ c = ((char *) pf->data)[pf->seek]; pf->seek++; if (pf->seek > pf->size){ if (read == 0) return (0); *p = 0; return(s); } if (c == 10 || c == 13){ *p = 0; return(s); } *p++ = c; n--; } *p = 0; return(s); } int readfontmatrix(PackedFile * pf, float mat[2][2]) { char *cptr; float a, b, c, d, e, f; pf->seek = 0; /* look for the FontMatrix def */ while(1) { if(!newfgets(oneline, LINELEN, pf)) { fprintf(stderr,"fromtype1: no FontMatrix found\n"); return(-1); } cptr = strchr(oneline,'/'); if(cptr) { if(strncmp(cptr,"/FontMatrix",11) == 0) { cptr = strchr(cptr,'['); if(!cptr) { fprintf(stderr,"fromtype1: bad FontMatrix line\n"); return(-1); } sscanf(cptr+1,"%f %f %f %f %f %f\n",&a,&b,&c,&d,&e,&f); break; } } } mat[0][0] = 1000.0*a; mat[1][0] = 1000.0*b; mat[0][1] = 1000.0*c; mat[1][1] = 1000.0*d; return(0); } /* * Decryption support * * */ static void resetdecrypt(int n) { mr = n; } /* * decryption subroutines * */ char mdecrypt(char cipher) { char plain; plain = (cipher^(mr>>8)); mr = (cipher+mr)*MC1 + MC2; return plain; } static void decryptdata(char * cptr, int n) { while(n--) { *cptr = mdecrypt(*cptr); cptr++; } } static int decryptprogram(char *buf, int len) { int i; resetdecrypt(4330); for(i=0; i='0' && i<='9') hextab[i] = i-'0'; else if(i>='a' && i<='f') hextab[i] = 10+i-'a'; else if(i>='A' && i<='F') hextab[i] = 10+i-'A'; else hextab[i] = NOTHEX; } } pf->seek = 0; /* allocate buffers */ totlen = pf->size; hexdat = (char *)mallocN(totlen, "hexdat"); bindat = (char *)mallocN(totlen, "bindat"); /* look for eexec part of file */ while(1) { if(!newfgets(oneline, LINELEN, pf)) { fprintf(stderr,"fromtype1: no currentfile eexec found\n"); return(-1); } oneline[16] = 0; if(strcmp(oneline,"currentfile eexe") == 0) break; } /* initialize decryption variables */ mr = 55665; /* first byte == 0 for binary data (???) */ c = ((char *) pf->data)[pf->seek]; if (hextab[c] != NOTHEX){ /* read all the hex bytes into the hex buffer */ hexbytes = 0; while(newfgets(oneline, LINELEN, pf)) { hptr = (char *)oneline; while(*hptr) { if(hextab[*hptr] != NOTHEX) hexdat[hexbytes++] = *hptr; hptr++; } } /* check number of hex bytes */ if(hexbytes & 1) hexbytes--; datbytes = hexbytes/2; /* translate hex data to binary */ hptr = hexdat; bptr = bindat; c = datbytes; while(c--) { *bptr++ = (hextab[hptr[0]]<<4)+hextab[hptr[1]]; hptr += 2; } /* decrypt the data */ decryptdata(bindat,datbytes); } else { datbytes = pf->size - pf->seek; memcpy(bindat, ((char *) pf->data) + pf->seek, datbytes); if ((bindat[2] << 8 + bindat[3]) == 0x800){ /* order data (remove 6 bytes headers) */ i = datbytes; hptr = bptr = bindat + 4; hptr += 2; while (i > 0){ if (i > 2046) c = 2046; else c = i; memcpy(bptr, hptr, c); bptr += 2046; hptr += 2046 + 6; i -= 2046 + 6; datbytes -= 6; } /* decrypt the data */ decryptdata(bindat+4,datbytes); } else{ decryptdata(bindat+6,datbytes); } } #ifdef DEBUG outf = fopen(outname,"wb"); fwrite(bindat,datbytes,1,outf); fclose(outf); #endif freeN(hexdat); return 1; } /* * fake file reading funcs * * */ static void fakefopen() { fakepos = 0; fakemax = datbytes; } static void fakegettoken(char *str) { int c; char *cptr; char *start; start = (char *) str; cptr = bindat+fakepos; c = *cptr++; fakepos++; if(c != '\n') { while(isspace(c)) { c = *cptr++; fakepos++; } while (fakeposfakemax) { fprintf(stderr,"fromtype1: unexpected eof\n"); strcpy(start, "end"); } } static int fakefgets(char *buf,int max) { char *cptr; cptr = (char *)(bindat+fakepos); while(max--) { *buf++ = *cptr; fakepos++; if(*cptr == 10 || *cptr == 13) return 1; cptr++; if(fakepos>fakemax) return 0; } return 0; } char *fakefread(int n) { fakepos += n; return bindat+fakepos-n; } static void applymat(float mat[][2], float *x, float *y) { float tx, ty; tx = ((*x)*mat[0][0])+((*y)*mat[0][1]); ty = ((*x)*mat[1][0])+((*y)*mat[1][1]); *x = tx; *y = ty; } static void setcharlist() { char *name, found; int i, j; for(i=0; imy_nsubrs) { fprintf(stderr,"bad Subr index %d\n",index); /*exit(1);*/ } /* get the number of bytes to read */ fakegettoken(tok); nread = atoi(tok); fakegettoken(tok); /* read in the subroutine */ my_sublen[index] = nread; my_subrs[index] = fakefread(nread); fakegettoken(tok); } /* look for the CharStrings */ while(1) { fakegettoken(tok); cptr = strchr(tok,'/'); if(cptr && strcmp(cptr,"/CharStrings") == 0) break; } fakegettoken(tok); /* skip my_ncharscrings */ fakegettoken(tok); /* skip dict */ fakegettoken(tok); /* skip dup */ fakegettoken(tok); /* skip begin */ fakegettoken(tok); /* skip newline */ /* read the CharStrings one by one */ my_nchars = 0; for(i=0; i=7) { fprintf(stderr,"subr2: bad poop\n"); /*exit(1);*/ } coordsave[coordpos][0] = x; coordsave[coordpos][1] = y; coordpos++; } static void subr0() { int x0, y0; int x1, y1; int x2, y2; int x3, y3; int xpos, ypos, noise; ypos = pop(); xpos = pop(); noise = pop(); if(coordpos!=7) { fprintf(stderr,"subr0: bad poop\n"); /*exit(1);*/ } x0 = coordsave[0][0]; y0 = coordsave[0][1]; x1 = coordsave[1][0]+x0; y1 = coordsave[1][1]+y0; x2 = coordsave[2][0]; y2 = coordsave[2][1]; x3 = coordsave[3][0]; y3 = coordsave[3][1]; rcurveto(x1,y1,x1+x2,y1+y2,x1+x2+x3,y1+y2+y3); x1 = coordsave[4][0]; y1 = coordsave[4][1]; x2 = coordsave[5][0]; y2 = coordsave[5][1]; x3 = coordsave[6][0]; y3 = coordsave[6][1]; rcurveto(x1,y1,x1+x2,y1+y2,x1+x2+x3,y1+y2+y3); getpos(&x0,&y0); retpush(y0); retpush(x0); incusp = 0; } static void append_poly_offset(short ofsx, short ofsy, short * data) { int nverts; if (data == 0) return; while(1) { switch(chardata[nshorts++] = *data++) { case PO_BGNLOOP: nshorts --; /* voor de eerste keer */ break; case PO_RETENDLOOP: case PO_RET: return; break; } nverts = chardata[nshorts++] = *data++; while(nverts--) { chardata[nshorts++] = (*data++) + ofsx; chardata[nshorts++] = (*data++) + ofsy; } } } static void append_spline_offset(short ofsx, short ofsy, short * data) { int nverts = 0; if (data == 0) return; while(1) { switch(chardata[nshorts++] = *data++) { case SP_MOVETO: case SP_LINETO: nverts = 1; break; case SP_CURVETO: nverts = 3; break; case SP_RETCLOSEPATH: case SP_RET: return; break; } for (; nverts > 0; nverts--) { chardata[nshorts++] = (*data++) + ofsx; chardata[nshorts++] = (*data++) + ofsy; } } } /* * graphics follows * * */ /* poly output stuff */ static void setwidth(int w, int x) { thecharwidth = w; thesidebearing = x; } static void poly_beginchar() { npnts = 0; nloops = 0; } static void poly_endchar() { if(nloops == 0) chardata[nshorts++] = PO_RET; else chardata[nshorts++] = PO_RETENDLOOP; } static void poly_close() { chardata[nvertpos] = npnts; npnts = 0; } static void poly_pnt(float x, float y) { short v[3]; int ix, iy; applymat(mat,&x,&y); ix = floor(x); iy = floor(y); if(npnts == 0) { if(nloops == 0) { chardata[nshorts++] = PO_BGNLOOP; nvertpos = nshorts++; } else { chardata[nshorts++] = PO_ENDBGNLOOP; nvertpos = nshorts++; } nloops++; } chardata[nshorts++] = ix; chardata[nshorts++] = iy; npnts++; } /* spline output stuff */ static void spline_beginchar() { sp_npnts = 0; sp_nloops = 0; } static void spline_endchar() { if(sp_nloops == 0) chardata[nshorts++] = SP_RET; else chardata[nshorts++] = SP_RETCLOSEPATH; } static void spline_close() { chardata[nshorts++] = SP_CLOSEPATH; sp_npnts = 0; sp_nloops = 0; } static void spline_line(float x0, float y0, float x1, float y1) { applymat(mat,&x0,&y0); applymat(mat,&x1,&y1); if(sp_npnts == 0) { chardata[nshorts++] = SP_MOVETO; chardata[nshorts++] = floor(x0); chardata[nshorts++] = floor(y0); sp_npnts++; sp_nloops++; } chardata[nshorts++] = SP_LINETO; chardata[nshorts++] = floor(x1); chardata[nshorts++] = floor(y1); sp_npnts++; } static void spline_curveto(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) { applymat(mat,&x0,&y0); applymat(mat,&x1,&y1); applymat(mat,&x2,&y2); applymat(mat,&x3,&y3); if(sp_npnts == 0) { chardata[nshorts++] = SP_MOVETO; chardata[nshorts++] = floor(x0); chardata[nshorts++] = floor(y0); sp_npnts++; sp_nloops++; } chardata[nshorts++] = SP_CURVETO; chardata[nshorts++] = floor(x1); chardata[nshorts++] = floor(y1); chardata[nshorts++] = floor(x2); chardata[nshorts++] = floor(y2); chardata[nshorts++] = floor(x3); chardata[nshorts++] = floor(y3); } static void savestart(int x, int y) { startx = x; starty = y; started = 1; } static void sbpoint( int x, int y) { curx = x; cury = y; } static void moveto( int x, int y) { curx = x; cury = y; savestart(curx,cury); } static void rmoveto( int x, int y) { if(incusp) { delx = x; dely = y; } else { curx += x; cury += y; savestart(curx,cury); } } static void drawline(float x0, float y0, float x1, float y1, float dx0, float dy0, float dx1, float dy1) { if(x0!=x1 || y0!=y1) poly_pnt(x1,y1); } static void rlineto( int x, int y) { float dx, dy; nextx = curx + x; nexty = cury + y; dx = nextx-curx; dy = nexty-cury; if (savesplines) spline_line( curx, cury, nextx, nexty); else drawline( curx, cury, nextx, nexty,dx,dy,dx,dy); curx = nextx; cury = nexty; } static void closepath() { float dx, dy; if(started) { dx = startx-curx; dy = starty-cury; if (savesplines) { spline_close(); } else { drawline( curx, cury, startx, starty,dx,dy,dx,dy); poly_close(); } started = 0; } } static void bezadapt( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float beztol) { float ax0,ay0,ax1,ay1,ax2,ay2,ax3,ay3; float bx0,by0,bx1,by1,bx2,by2,bx3,by3; float midx, midy; float linx, liny, dx, dy, mag; midx = (x0+3*x1+3*x2+x3)/8.0; midy = (y0+3*y1+3*y2+y3)/8.0; linx = (x0+x3)/2.0; liny = (y0+y3)/2.0; dx = midx-linx; dy = midy-liny; mag = dx*dx+dy*dy; if(mag<(beztol*beztol)) drawline(x0,y0,x3,y3,x1-x0,y1-y0,x3-x2,y3-y2); else { ax0 = x0; ay0 = y0; ax1 = (x0+x1)/2; ay1 = (y0+y1)/2; ax2 = (x0+2*x1+x2)/4; ay2 = (y0+2*y1+y2)/4; ax3 = midx; ay3 = midy; bezadapt(ax0,ay0,ax1,ay1,ax2,ay2,ax3,ay3,beztol); bx0 = midx; by0 = midy; bx1 = (x1+2*x2+x3)/4; by1 = (y1+2*y2+y3)/4; bx2 = (x2+x3)/2; by2 = (y2+y3)/2; bx3 = x3; by3 = y3; bezadapt(bx0,by0,bx1,by1,bx2,by2,bx3,by3,beztol); } } static void drawbez( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) { bezadapt(x0,y0,x1,y1,x2,y2,x3,y3,beztol); } static void rcurveto( int dx1, int dy1, int dx2, int dy2, int dx3, int dy3) { int x0, y0; int x1, y1; int x2, y2; int x3, y3; x0 = curx; y0 = cury; x1 = curx+dx1; y1 = cury+dy1; x2 = curx+dx2; y2 = cury+dy2; x3 = curx+dx3; y3 = cury+dy3; if (savesplines) { spline_curveto( x0, y0, x1, y1, x2, y2, x3, y3); } else{ drawbez( x0, y0, x1, y1, x2, y2, x3, y3); } curx = x3; cury = y3; } /* * saveobjfont - * save an object font. * */ /* generic routines */ void makeobjfont(int savesplines) { int i, j, c; if(savesplines) fnt = newobjfnt(SP_TYPE, 32, 32+NASCII-1, 9840); else fnt = newobjfnt(PO_TYPE, 32, 32+NASCII-1, 9840); for(i=0; i=0) { /*printf("decoding %s\n", ISOcharlist[i].name);*/ nshorts = 0; drawchar(ISOcharlist[i].prog); addchardata(fnt,c,chardata,nshorts); addcharmetrics(fnt,c,thecharwidth,0); sidebearing[c] = thesidebearing; } else if(c == ' ') { printf("faking space %d\n",i); fakechar(fnt,' ',400); } } } /* * run the character program * * */ static void drawchar(int c) { if (savesplines) { spline_beginchar(); } else { poly_beginchar(); } initstack(); initpcstack(); initretstack(); pc = my_chars[c]; runprog(); if (savesplines){ spline_endchar(); } else { poly_endchar(); } } static int docommand(int cmd) { int x, y, w, c1, c2; int dx1, dy1; int dx2, dy2; int dx3, dy3; float fdx1, fdy1; int i, sub, n, p, nlen; char *subpc; chardesc *cd; short *ndata; switch(cmd) { case WHAT0: fprintf(stderr,"\nYUCK: WHAT0\n"); break; case HSTEM: pop(); pop(); /*printf("hstem: %d %d\n", pop(), pop());*/ break; case VSTEM: pop(); pop(); /*printf("vstem: %d %d\n", pop(), pop());*/ break; case VMOVETO: y = pop(); rmoveto(0,y); break; case RLINETO: y = pop(); x = pop(); rlineto(x,y); break; case HLINETO: x = pop(); rlineto(x,0); break; case VLINETO: y = pop(); rlineto(0,y); break; case RRCURVETO: dy3 = pop(); dx3 = pop(); dy2 = pop(); dx2 = pop(); dy1 = pop(); dx1 = pop(); rcurveto(dx1,dy1,dx1+dx2,dy1+dy2,dx1+dx2+dx3,dy1+dy2+dy3); break; case CLOSEPATH: closepath(); break; case CALLSUBR: sub = pop(); subpc = my_subrs[sub]; if(!subpc) { fprintf(stderr,"\nYUCK no sub addr\n"); } pushpc(pc); pc = subpc; break; case RETURN: pc = poppc(); break; case HSBW: w = pop(); x = pop(); setwidth(w, x); sbpoint(x,0); break; case ENDCHAR: closepath(); break; case RMOVETO: y = pop(); x = pop(); rmoveto(x,y); break; case HMOVETO: x = pop(); rmoveto(x,0); break; case VHCURVETO: dy3 = 0; dx3 = pop(); dy2 = pop(); dx2 = pop(); dy1 = pop(); dx1 = 0; rcurveto(dx1,dy1,dx1+dx2,dy1+dy2,dx1+dx2+dx3,dy1+dy2+dy3); break; case HVCURVETO: dy3 = pop(); dx3 = 0; dy2 = pop(); dx2 = pop(); dy1 = 0; dx1 = pop(); rcurveto(dx1,dy1,dx1+dx2,dy1+dy2,dx1+dx2+dx3,dy1+dy2+dy3); break; case DOTSECTION: break; case VSTEM3: /*printf("vstem3\n");*/ pop(); pop(); pop(); pop(); pop(); pop(); break; case HSTEM3: /*printf("hstem3\n");*/ pop(); pop(); pop(); pop(); pop(); pop(); break; case SEAC: if (0) { printf("seac: %3d %3d %3d %3d %3d\n", pop(), pop(), pop(), pop(), pop()); } else{ c2 = STDtoISO(pop()); /* accent */ c1 = STDtoISO(pop()); /* letter */ cd = getchardesc(fnt, c1); if (cd) { memcpy(chardata, cd->data, cd->datalen); nshorts = cd->datalen / sizeof(short); } cd = getchardesc(fnt, c2); if (cd && cd->data && cd->datalen) { nlen = cd->datalen / sizeof(short); ndata = cd->data; if (nshorts) { if (savesplines) { switch (chardata[nshorts - 1]){ case SP_RET: nshorts--; break; case SP_RETCLOSEPATH: chardata[nshorts - 1] = SP_CLOSEPATH; break; } } else { switch (chardata[nshorts - 1]){ case PO_RET: printf("PO_RET in character disription ?\n"); nshorts--; break; case PO_RETENDLOOP: if (ndata[0] == PO_BGNLOOP) { chardata[nshorts - 1] = PO_ENDBGNLOOP; } else { printf("new character doesn't start with PO_BGNLOOP ?\n"); } break; } } } /* i.p.v. the sidebearing[c1] moet misschen thesidebearing gebruikt worden */ dy1 = pop(); dx1 = pop() + sidebearing[c1] - sidebearing[c2]; pop(); fdx1 = dx1; fdy1 = dy1; applymat(mat, &fdx1, &fdy1); dx1 = floor(fdx1); dy1 = floor(fdy1); if (savesplines) { append_spline_offset(dx1, dy1, ndata); } else{ append_poly_offset(dx1, dy1, ndata); } /*printf("first: %d %d\n", cd->data[0], cd->data[1]);*/ } fflush(stdout); } break; case SBW: w = pop(); y = pop(); fprintf(stderr,"sbw: width: %d %d\n",w,y); y = pop(); x = pop(); fprintf(stderr,"sbw: side: %d %d\n",x,y); setwidth(w, x); sbpoint(x,y); break; case DIV: x = pop(); y = pop(); push(x/y); break; case CALLOTHERSUBR: sub = pop(); n = pop(); if(sub == 0) subr0(); else if(sub == 1) subr1(); else if(sub == 2) subr2(); else { for(i=0; i=0 && v<=31) { if(v == 12) { w = *pc++; cmd = 256+w; } else cmd = v; if(!docommand(cmd)) { return; } } else if(v>=32 && v<=246) { num = v-139; push(num); } else if(v>=247 && v<=250) { w = *pc++; num = (v-247)*256+w+108; push(num); } else if(v>=251 && v<=254) { w = *pc++; num = -(v-251)*256-w-108; push(num); } else if(v == 255) { num = *pc++; num <<= 8; num |= *pc++; num <<= 8; num |= *pc++; num <<= 8; num |= *pc++; push(num); } } }