1*34009Sedward /* @(#)psdit.c 1.4 04/17/88 */ 230594Ssam #ifndef lint 330594Ssam static char Notice[] = "Copyright (c) 1984, 1985 Adobe Systems Incorporated"; 432179Sedward static char *RCSID = "$Header: psdit.c,v 2.1 85/11/24 11:50:41 shore Rel $"; 530594Ssam #endif 630595Ssam # define XMOD 732179Sedward /* 832179Sedward * Changed by Edward Wang (edward@ucbarpa.berkeley.edu) to handle graphics, 932179Sedward * 17 Feb, 87, with code provided by John Coker (john@renoir.berkeley.edu) 1032179Sedward * and Peehong Chen (phc@renoir.berkeley.edu). 1132179Sedward */ 1230594Ssam /* psdit.c 1330594Ssam * 1430594Ssam * Copyright (c) 1984, 1985 Adobe Systems Incorporated 1530594Ssam * 1630594Ssam * ditroff intermediate file to PostScript translator 1730594Ssam * 1830594Ssam * Original Version: Barry Hayes spring/summer 1984 1930594Ssam * Edit History: 2030594Ssam * Andrew Shore: Sat Nov 23 20:05:26 1985 2130594Ssam * End Edit History. 2230594Ssam * 2330594Ssam * RCSLOG: 2430594Ssam * $Log: psdit.c,v $ 2530594Ssam * Revision 2.1 85/11/24 11:50:41 shore 2630594Ssam * Product Release 2.0 2732179Sedward * 2830594Ssam * Revision 1.8 85/11/23 20:09:44 shore 2930594Ssam * test for termination of included PostScript was bad 3032179Sedward * 3130594Ssam * Revision 1.7 85/11/21 14:23:56 shore 3230594Ssam * added envget check for PSLIBDIR 3332179Sedward * 3430594Ssam * Revision 1.6 85/11/20 00:43:43 shore 3530594Ssam * support for included PostScript 3630594Ssam * big rework on FlushShow, word "breaks" 3730594Ssam * removed FlushFont and made them instant 3830594Ssam * Still no Gremlin support yet 3932179Sedward * 4030594Ssam * Revision 1.5 85/10/03 10:48:09 shore 4130594Ssam * added FlushShow to xf fix ! 4232179Sedward * 4330594Ssam * Revision 1.4 85/10/02 16:20:32 shore 4432179Sedward * fixed xf bug 4530594Ssam * mounting a font causes a font switch! 4632179Sedward * 4730594Ssam * Revision 1.3 85/07/09 13:10:20 shore 4830594Ssam * added fclose on map file 4932179Sedward * 5030594Ssam * Revision 1.2 85/05/14 11:24:23 shore 5130594Ssam * added flush to trailer 5230594Ssam * fixed read bug when mounting fonts 5330594Ssam */ 5430594Ssam 5532179Sedward /* 5630594Ssam output language from troff: 5730594Ssam all numbers are character strings 5830594Ssam 5930594Ssam sn size in points 6030594Ssam fn font as number from 1-n 6130594Ssam cx ascii character x 6230594Ssam Cxyz funny char xyz. terminated by white space 6330594Ssam Hn go to absolute horizontal position n 6430594Ssam Vn go to absolute vertical position n (down is positive) 6530594Ssam hn go n units horizontally (relative) 6630594Ssam vn ditto vertically 6730594Ssam nnc move right nn, then print c (exactly 2 digits!) 6830594Ssam (this wart is an optimization that shrinks output file size 6930594Ssam about 35% and run-time about 15% while preserving ascii-ness) 7030594Ssam Dt ...\n draw operation 't': 7130594Ssam Dl x y line from here by x,y 7230594Ssam Dc d circle of diameter d with left side here 7330594Ssam De x y ellipse of axes x,y with left side here 7430594Ssam Da x y r arc counter-clockwise by x,y of radius r 7532179Sedward Dp ... bordered polygon 7632179Sedward DP ... unbordered polygon 7732179Sedward D~ x y x y ... b-spline by x,y then x,y ... 7832179Sedward Dg ... gremlin curve 7932179Sedward Dz ... bezier curve 8030594Ssam nb a end of line (information only -- no action needed) 8130594Ssam a = space before line, a = after 8230594Ssam w paddable word space -- no action needed 8330594Ssam pn new page begins -- set v to 0 8430594Ssam { push current environment (font info & location) 8530594Ssam } pop a saved environment 8630594Ssam txxxx print string xxxx using natural widths 8730594Ssam #...\n comment 8830594Ssam x ...\n device control functions: 8930594Ssam x i[nit] init 9030594Ssam x T s name of device is s 9130594Ssam x r[es] n h v resolution is n/inch 9230594Ssam h = min horizontal motion, v = min vert 9330594Ssam x p[ause] pause (can restart) 9430594Ssam x s[top] stop -- done for ever 9530594Ssam x t[railer] generate trailer 9630594Ssam x f[font] n s font position n contains font s 9730594Ssam x H[eight] n set character height to n 9830594Ssam x S[slant] n set slant to N 9930594Ssam 10030594Ssam Adobe Extension for included PostScript: 10130594Ssam % 10230594Ssam (raw postscript...) 10330594Ssam .\n 10430594Ssam 10530594Ssam */ 10630594Ssam 10730594Ssam #include <stdio.h> 10830594Ssam #include <ctype.h> 10930594Ssam #include <signal.h> 11030594Ssam #include <pwd.h> 11130594Ssam #ifdef SYSV 11230594Ssam extern struct passwd *getpwuid(); 11330594Ssam #endif 11430594Ssam #include "transcript.h" 11530594Ssam 11630594Ssam #include "dev.h" 11730594Ssam 11830594Ssam char *malloc(); 11930594Ssam 12030594Ssam #define NFONT 10 12130594Ssam 12230594Ssam /* DIT state consists of: */ 12332179Sedward int hpos; /* current horizontal position */ 12432179Sedward int vpos; /* current vertical position */ 12532179Sedward int fontsize; /* current font size */ 12632179Sedward int fontheight; /* current character height */ 12732179Sedward int fontslant; /* current font slant */ 12832179Sedward int font; /* current font */ 12932179Sedward int resolution; /* device resolution */ 13032179Sedward int minhoriz; /* minimum horizontal motion */ 13132179Sedward int minvert; /* minimum vertical motion */ 13230594Ssam 13332179Sedward int onspecial; 13432179Sedward int specfont; 13532179Sedward int prevfont; 13632179Sedward int pfont; 13730594Ssam 13830594Ssam /* {} push/pop stack */ 13930594Ssam #define DSTACK 10 14032179Sedward struct ditstack { 14132179Sedward int hpos, vpos, fontsize, fontheight, fontslant, font; 14230594Ssam } ditstack[DSTACK]; 14332179Sedward int dlevel = 0; 14430594Ssam 14530594Ssam #define ErrorTolerance 48 14630594Ssam #define PSWID 0x00000FFF 14730594Ssam #define ISPSPROC 0x000FF000 14830594Ssam 14930594Ssam /* PSscale is equivalent to (x * PSmag / 72000) + 0.5 */ 15030594Ssam #define PSmag 16 15132179Sedward #define PSscale(x) (((x) + 2250) / 4500) 15230594Ssam 15330594Ssam /* we maintain PS coords with PSmag times the precision */ 15430594Ssam /* current PS state is: */ 15530594Ssam 15632179Sedward int PSx; /* current horizontal position */ 15732179Sedward int PSy; /* current vertical position */ 15832179Sedward int savex, savey; /* position of start of current show string */ 15930594Ssam 16030594Ssam /* ps move types -- note that XMOVE|YMOVE == XYMOVE ! */ 16132179Sedward #define NONE 0 16232179Sedward #define XMOVE 1 16332179Sedward #define YMOVE 2 16432179Sedward #define XYMOVE 3 16530594Ssam 16632179Sedward int movepending = NONE; 16730594Ssam 16830594Ssam /* buffer string for show -- save up adjacent chars */ 16930594Ssam #define SHOWSIZE 400 17032179Sedward char showbuf[SHOWSIZE + 3]; /* extras are for quoting */ 17132179Sedward int showind = 0; /* index into string of next available byte */ 17232179Sedward int PSshowlen = 0; /* size in big units of buffered string */ 17332179Sedward int nshow = 0; /* actual number of show chars in showbuf */ 17432179Sedward int startx; /* troff starting pos of current string */ 17532179Sedward int thisw; 17630594Ssam 17730594Ssam /* #define NONE 0 */ 17832179Sedward #define HMOT 1 17932179Sedward #define VMOT 2 18032179Sedward #define CPUT 4 18132179Sedward #define BRK 8 18232179Sedward #define FNT 16 18332179Sedward int lastcmd; 18430594Ssam 18532179Sedward int output = 0; /* do we do output at all? */ 18632179Sedward int nolist = 0; /* output page list if > 0 */ 18732179Sedward int olist[20]; /* pairs of page numbers */ 18832179Sedward int spage = 9999; /* stop every spage pages */ 18932179Sedward int scount = 0; 19032179Sedward int stopped = 0; 19132179Sedward int pageno = 0; 19232179Sedward int firstpage = TRUE; 19330594Ssam 19432179Sedward struct dev dev; 19532179Sedward struct font *fontbase[NFONT+1]; 19632179Sedward short *pstab; 19732179Sedward int dres; /* resolution from DESC */ 19832179Sedward int nsizes; /* number of point sizes from DESC */ 19932179Sedward int nfonts; /* number of fonts from DESC */ 20032179Sedward int smnt; /* index of first special font */ 20132179Sedward int nchtab; 20232179Sedward char *chname; 20332179Sedward short *chtab; 20432179Sedward char *fitab[NFONT+1]; 20532179Sedward char *widthtab[NFONT+1]; /* widtab would be a better name */ 20632179Sedward char *codetab[NFONT+1]; /* device codes */ 20730594Ssam 20832179Sedward int *pswidths[NFONT+1]; /* ps width tables */ 20932179Sedward int fontdelta[NFONT+1]; /* nonzero if xf overwrites font i */ 21030594Ssam 21130594Ssam /* font position info: */ 21232179Sedward struct { 21330594Ssam char *name; 21430594Ssam int number; 21530594Ssam } fontname[NFONT+1]; 21630594Ssam 21730594Ssam #define FATAL 1 21830594Ssam #define BMASK 0377 21930594Ssam 22030594Ssam #ifdef DEBUG 22132179Sedward int dbg = 0; 22230594Ssam int fdbg = 0; 22332179Sedward #define debugp(xxx) (dbg != 0 ? (dbg--, printf xxx, fflush(stdout)) : 0) 22430594Ssam #else 22530594Ssam #define debugp(x) 22630594Ssam #endif 22730594Ssam 22832179Sedward char devname[20] = "psc"; 22930594Ssam 23032179Sedward char *infilename = "stdin"; /* input file name */ 23132179Sedward char *prologfile = PSDITPRO; 23232179Sedward char *ditdir = DitDir; 23330594Ssam 23432179Sedward char *prog; /* argv[0] - program name */ 23530594Ssam 236*34009Sedward /* for curve and polygon drawing */ 23732179Sedward #define MAXPOINTS 200 238*34009Sedward double x[MAXPOINTS], y[MAXPOINTS]; 239*34009Sedward int numpoints; 24032179Sedward 24130594Ssam main(argc, argv) 24232179Sedward int argc; 24332179Sedward char *argv[]; 24430594Ssam { 24532179Sedward FILE *fp; 24632179Sedward int done(); 24730594Ssam 24832179Sedward prog = argv[0]; 24932179Sedward while (argc > 1 && argv[1][0] == '-') { 25032179Sedward switch (argv[1][1]) { 25132179Sedward case 'f': 25232179Sedward case 'F': 25332179Sedward if (argv[1][2]) 25432179Sedward ditdir = &argv[1][2]; 25532179Sedward else { 25632179Sedward ditdir = argv[2]; 25732179Sedward argv++; 25832179Sedward argc--; 25932179Sedward } 26032179Sedward break; 26132179Sedward case 'p': 26232179Sedward if (argv[1][2]) 26332179Sedward prologfile = &argv[1][2]; 26432179Sedward break; 26532179Sedward case 'o': 26632179Sedward outlist(&argv[1][2]); 26732179Sedward break; 26832179Sedward case 'd': 26932179Sedward #ifdef DEBUG 27032179Sedward dbg = atoi(&argv[1][2]); 27132179Sedward if (dbg == 0) 27232179Sedward dbg = 1; 27332179Sedward #endif DEBUG 27432179Sedward break; 27532179Sedward case 'b': /* ignore busy */ 27632179Sedward break; 27732179Sedward case 'w': /* ignore wait */ 27832179Sedward break; 27932179Sedward case 's': 28032179Sedward spage = atoi(&argv[1][2]); 28132179Sedward if (spage <= 0) 28232179Sedward spage = 9999; 28332179Sedward break; 28430594Ssam } 28532179Sedward argc--; 28632179Sedward argv++; 28730594Ssam } 28830594Ssam 28932179Sedward if (signal(SIGINT, done) == SIG_IGN) { 29032179Sedward signal(SIGINT, SIG_IGN); 29132179Sedward signal(SIGQUIT, SIG_IGN); 29232179Sedward signal(SIGHUP, SIG_IGN); 29332179Sedward } else { 29432179Sedward signal(SIGQUIT, done); 29532179Sedward signal(SIGHUP, done); 29632179Sedward } 29732179Sedward signal(SIGTERM, done); 29830594Ssam 29932179Sedward preface(); 30030594Ssam 30132179Sedward if (argc <= 1) 30232179Sedward conv(stdin); 30332179Sedward else 30432179Sedward while (--argc > 0) { 30532179Sedward if (strcmp(*++argv, "-") == 0) 30632179Sedward fp = stdin; 30732179Sedward else if ((fp = fopen(*argv, "r")) == NULL) { 30832179Sedward fprintf(stderr, "%s: can't open %s\n", 30932179Sedward prog, *argv); 31032179Sedward pexit(prog, 2); 31132179Sedward } 31232179Sedward infilename = *argv; 31332179Sedward conv(fp); 31432179Sedward (void) fclose(fp); 31532179Sedward } 31632179Sedward done(); 31730594Ssam } 31830594Ssam 31932179Sedward /* process list of page numbers to be printed */ 32032179Sedward outlist(s) 32132179Sedward register char *s; 32230594Ssam { 32332179Sedward int n1, n2, i; 32430594Ssam 32532179Sedward nolist = 0; 32632179Sedward while (*s) { 32732179Sedward n1 = 0; 32832179Sedward if (isdigit (*s)) 32932179Sedward do 33032179Sedward n1 = 10 * n1 + *s++ - '0'; 33132179Sedward while (isdigit(*s)); 33232179Sedward else 33332179Sedward n1 = -9999; 33432179Sedward n2 = n1; 33532179Sedward if (*s == '-') { 33632179Sedward s++; 33732179Sedward n2 = 0; 33832179Sedward if (isdigit(*s)) 33932179Sedward do 34032179Sedward n2 = 10 * n2 + *s++ - '0'; 34132179Sedward while (isdigit(*s)); 34232179Sedward else 34332179Sedward n2 = 9999; 34430594Ssam } 34532179Sedward olist[nolist++] = n1; 34632179Sedward olist[nolist++] = n2; 34732179Sedward if (*s != '\0') 34832179Sedward s++; 34930594Ssam } 35032179Sedward olist[nolist] = 0; 35130594Ssam #ifdef DEBUG 35232179Sedward if (dbg) 35332179Sedward for (i = 0; i < nolist; i += 2) 35432179Sedward printf("%3d %3d\n", olist[i], olist[i + 1]); 35532179Sedward #endif 35630594Ssam } 35730594Ssam 35832179Sedward conv(fp) /* convert a file */ 35932179Sedward register FILE *fp; 36030594Ssam { 36132179Sedward register int c, k; 36232179Sedward int m, n, n1, m1; 36332179Sedward char str[100], buf[300]; 36430594Ssam 36532179Sedward while ((c = getc(fp)) != EOF) 36632179Sedward switch (c) { 36732179Sedward case '\n': case ' ': case '\0': 36830594Ssam break; 36932179Sedward case '{': /* push down current environment */ 37032179Sedward t_push(); 37130594Ssam break; 37232179Sedward case '}': 37332179Sedward t_pop(); 37430594Ssam break; 37532179Sedward case '0': case '1': case '2': case '3': case '4': 37632179Sedward case '5': case '6': case '7': case '8': case '9': 37732179Sedward /* two motion digits plus a character */ 37832179Sedward hmot((c - '0') * 10 + getc(fp) - '0'); 37932179Sedward lastcmd = HMOT; 38032179Sedward put1(getc(fp), (char *) 0); 38132179Sedward lastcmd = CPUT; 38230594Ssam break; 38332179Sedward case 'c': /* single ascii character */ 38432179Sedward put1(getc(fp), (char *) 0); 38532179Sedward lastcmd = CPUT; 38630594Ssam break; 38732179Sedward case 'C': 38832179Sedward fscanf(fp, "%s", str); 38932179Sedward put1s(str); 39032179Sedward lastcmd = CPUT; 39132179Sedward break; 39232179Sedward case 't': /* straight text */ 39332179Sedward fgets(buf, sizeof buf, fp); 39432179Sedward t_text(buf); 39532179Sedward lastcmd = CPUT; 39632179Sedward break; 39732179Sedward case 'D': /* draw function */ 39832179Sedward fgets(buf, sizeof buf, fp); 39932179Sedward switch (buf[0]) { 40032179Sedward case 'l': /* draw a line */ 40132179Sedward sscanf(buf + 1, "%d %d", &n, &m); 40232179Sedward drawline(n, m); 40332179Sedward break; 40432179Sedward case 'c': /* circle */ 40532179Sedward sscanf(buf + 1, "%d", &n); 40632179Sedward drawcirc(n); 40732179Sedward break; 40832179Sedward case 'e': /* ellipse */ 40932179Sedward sscanf(buf + 1, "%d %d", &m, &n); 41032179Sedward drawellip(m, n); 41132179Sedward break; 41232179Sedward case 'a': /* arc */ 41332179Sedward sscanf(buf + 1, "%d %d %d %d", 41432179Sedward &n, &m, &n1, &m1); 41532179Sedward drawarc(n, m, n1, m1); 41632179Sedward break; 41732179Sedward case '~': /* b-spline */ 41832179Sedward case 'g': /* gremlin curve */ 41932179Sedward case 'z': /* bezier cubic */ 420*34009Sedward drawcurve(buf); 42132179Sedward break; 42232179Sedward case 'p': /* filled polygon */ 42332179Sedward case 'P': /* bordered filled polygon */ 424*34009Sedward drawpoly(buf); 42532179Sedward break; 42632179Sedward case 't': /* line thickness */ 42732179Sedward case 's': /* line style */ 42832179Sedward sscanf(buf + 1, "%d", &n); 42932179Sedward printf("%d D%c\n", n, buf[0]); 43032179Sedward break; 43132179Sedward default: 43232179Sedward fprintf(stderr, 43332179Sedward "%s: unknown drawing function %s\n", 43432179Sedward prog, buf); 43532179Sedward exit(2); 43632179Sedward } 43732179Sedward break; 43832179Sedward case 'i': 43932179Sedward fscanf(fp, "%d", &n); 44032179Sedward printf("%d Di\n", n); 44132179Sedward break; 44232179Sedward case 's': 44332179Sedward fscanf(fp, "%d", &n); 44432179Sedward t_size(n); 44532179Sedward lastcmd = FNT; 44632179Sedward break; 44732179Sedward case 'f': 44832179Sedward fscanf(fp, "%s", str); 44932179Sedward setfont(t_font(str)); 45032179Sedward lastcmd = FNT; 45132179Sedward break; 45232179Sedward case 'H': /* absolute horizontal motion */ 45332179Sedward while ((c = getc(fp)) == ' ') 45432179Sedward ; 45532179Sedward k = 0; 45632179Sedward do 45732179Sedward k = 10 * k + c - '0'; 45832179Sedward while (isdigit(c = getc(fp))); 45932179Sedward ungetc(c, fp); 46032179Sedward hgoto(k); 46132179Sedward lastcmd = HMOT; 46232179Sedward break; 46332179Sedward case 'h': /* relative horizontal motion */ 46432179Sedward while ((c = getc(fp)) == ' ') 46532179Sedward ; 46632179Sedward k = 0; 46732179Sedward do 46832179Sedward k = 10 * k + c - '0'; 46932179Sedward while (isdigit(c = getc(fp))); 47032179Sedward ungetc(c, fp); 47132179Sedward hmot(k); 47232179Sedward lastcmd = HMOT; 47332179Sedward break; 47432179Sedward case 'w': 47532179Sedward FlushShow(1); 47632179Sedward lastcmd = BRK; 47732179Sedward break; 47832179Sedward case 'V': 47932179Sedward fscanf(fp, "%d", &n); 48032179Sedward vgoto(n); 48132179Sedward lastcmd = VMOT; 48232179Sedward break; 48332179Sedward case 'v': 48432179Sedward fscanf(fp, "%d", &n); 48532179Sedward vmot(n); 48632179Sedward lastcmd = VMOT; 48732179Sedward break; 48832179Sedward case 'p': /* new page */ 48932179Sedward fscanf(fp, "%d", &n); 49032179Sedward t_page(n); 49132179Sedward lastcmd = NONE; 49232179Sedward break; 49332179Sedward case 'n': /* end of line -- ignore */ 49432179Sedward while (getc(fp) != '\n') 49532179Sedward ; 49632179Sedward FlushShow(1); 49732179Sedward lastcmd = BRK; 49832179Sedward break; 49932179Sedward case '#': /* comment */ 50032179Sedward /* maybe should pass through as a PS comment */ 50132179Sedward while (getc(fp) != '\n') 50232179Sedward ; 50332179Sedward break; 50432179Sedward case 'x': /* device control */ 50532179Sedward devcntrl(fp); 50632179Sedward break; 50732179Sedward case '%': /* imbedded PostScript */ 50832179Sedward /* copy everything up to but NOT including a line */ 50932179Sedward /* with at single "." */ 51032179Sedward FlushShow(0); 51132179Sedward MoveTo(); 51232179Sedward DoMove(); 51332179Sedward printf("\n%% included PostScript\n"); 51432179Sedward while (fgets(buf, sizeof buf, fp) != NULL) { 51532179Sedward if (strcmp(".\n", buf) == 0) 51632179Sedward break; 51732179Sedward fputs(buf, stdout); 51832179Sedward } 51932179Sedward break; 52032179Sedward default: 52132179Sedward fprintf(stderr, "%s: bad input char \\%03o (%c)\n", 52232179Sedward prog, c, c); 52330594Ssam exit(2); 52430594Ssam } 52530594Ssam } 52630594Ssam 52730594Ssam /* put in PostScript prolog */ 52832179Sedward preface() 52930594Ssam { 53032179Sedward register FILE *prolog; 53132179Sedward char hostname[256]; 53232179Sedward char tempfile[512]; 53332179Sedward struct passwd *pswd; 53432179Sedward long clock; 53532179Sedward char *libdir; 53630594Ssam 53732179Sedward printf("%%!%s\n", COMMENTVERSION); 53832179Sedward pswd = getpwuid(getuid()); 53932179Sedward (void) gethostname(hostname, sizeof hostname); 54032179Sedward printf("%%%%Creator: %s:%s (%s)\n", hostname, 54132179Sedward pswd->pw_name, pswd->pw_gecos); 54232179Sedward printf("%%%%Title: %s (ditroff)\n", infilename); 54332179Sedward printf("%%%%CreationDate: %s", (time(&clock), ctime(&clock))); 54432179Sedward printf("%%%%EndComments\n"); 54532179Sedward if ((libdir = envget("PSLIBDIR")) == NULL) 54632179Sedward libdir = LibDir; 54732179Sedward mstrcat(tempfile, libdir, prologfile, sizeof tempfile); 54832179Sedward if (copyfile(tempfile, stdout) != 0) { 54932179Sedward fprintf(stderr, "%s: can't copy prolog file %s\n", 55032179Sedward prog, tempfile); 55132179Sedward exit(2); 55232179Sedward } 55332179Sedward printf("ditstart\n"); 55430594Ssam } 55530594Ssam 55632179Sedward devcntrl(fp) /* interpret device control functions */ 55732179Sedward FILE *fp; 55830594Ssam { 55932179Sedward char str[20], str1[50], buf[50]; 56032179Sedward int c, n, res, minh, minv; 56130594Ssam 56232179Sedward fscanf(fp, "%s", str); 56332179Sedward switch (str[0]) { /* crude for now */ 56430594Ssam case 'i': /* initialize */ 56532179Sedward fileinit(); 56632179Sedward t_init(); 56732179Sedward lastcmd = NONE; 56832179Sedward break; 56930594Ssam case 'T': /* device name */ 57032179Sedward /* 57132179Sedward fscanf(fp, "%s", devname); 57232179Sedward if (strcmp(devname, "psc")) { 57332179Sedward fprintf(stderr, "%s: device not psc\n", prog); 57432179Sedward exit(2); 57532179Sedward } 57632179Sedward */ 57732179Sedward printf("(%s)xT\n", devname); 57832179Sedward lastcmd = NONE; 57932179Sedward break; 58030594Ssam case 't': /* trailer */ 58132179Sedward t_trailer(); 58232179Sedward lastcmd = NONE; 58332179Sedward break; 58430594Ssam case 'p': /* pause -- can restart */ 58532179Sedward t_reset('p'); 58632179Sedward lastcmd = NONE; 58732179Sedward break; 58830594Ssam case 's': /* stop */ 58932179Sedward t_reset('s'); 59032179Sedward lastcmd = NONE; 59132179Sedward break; 59230594Ssam case 'r': /* resolution assumed when prepared */ 59332179Sedward fscanf(fp, "%d %d %d", &res, &minh, &minv); 59432179Sedward t_res(res, minh, minv); 59532179Sedward lastcmd = NONE; 59632179Sedward break; 59730594Ssam case 'f': /* font used */ 59832179Sedward fscanf(fp, "%d %s", &n, str); 59932179Sedward fgets(buf, sizeof buf, fp); /* in case theres a filename */ 60032179Sedward ungetc('\n', fp); /* fgets goes too far */ 60132179Sedward str1[0] = 0; /* in case there is nothing to come in */ 60232179Sedward sscanf(buf, "%s", str1); 60332179Sedward loadfont(n, str, str1); 60432179Sedward lastcmd = FNT; 60532179Sedward break; 60630594Ssam case 'H': /* char height */ 60732179Sedward fscanf(fp, "%d", &n); 60832179Sedward t_charht(n); 60932179Sedward lastcmd = FNT; 61032179Sedward break; 61130594Ssam case 'S': /* slant */ 61232179Sedward fscanf(fp, "%d", &n); 61332179Sedward t_slant(n); 61432179Sedward lastcmd = FNT; 61532179Sedward break; 61630595Ssam #ifdef XMOD 61730595Ssam case 'X': { /* \X command from ditroff */ 61830595Ssam int last; 61930595Ssam char largebuf[128]; 62030595Ssam fscanf (fp, "%1s", str); 62130595Ssam switch (str[0]) { 62230595Ssam case 'p' : 62330595Ssam FlushShow(0);MoveTo();DoMove(); 62430595Ssam fgets(largebuf, sizeof(largebuf), fp); 62530595Ssam last = strlen(largebuf) - 1; 62630595Ssam if (last >= 0 && largebuf[last] == '\n') { 62730595Ssam ungetc('\n', fp); 62830595Ssam largebuf[last] = ' '; 62930595Ssam } 63032179Sedward puts(largebuf); 63130595Ssam break; 63230595Ssam case 'f' : 63330595Ssam FlushShow(0);MoveTo();DoMove(); 63430595Ssam if (fscanf(fp, "%s", largebuf) == 1) { 63530595Ssam char *nl = (char *) index(largebuf, '\n'); 63630595Ssam if (nl) *nl = '\0'; 63730595Ssam includefile(largebuf); 63830595Ssam } else 63930595Ssam fprintf(stderr, "warning - include cmd w/o path.\n"); 64030595Ssam break; 64130595Ssam } 64230595Ssam } 64330595Ssam break; 64430595Ssam #endif 64532179Sedward } 64632179Sedward /* skip rest of input line */ 64732179Sedward while ((c = getc(fp)) != '\n' && c != EOF) 64832179Sedward ; 64930594Ssam } 65030594Ssam 65130595Ssam #ifdef XMOD 65230595Ssam includefile(filenm) 65332179Sedward char *filenm; 65432179Sedward { 65530595Ssam FILE *inf; 65630595Ssam int ch, c1, c2, firstch = 0; 65730595Ssam 65830595Ssam if (!(inf = fopen(filenm, "r"))) { 65930595Ssam fprintf(stderr, "psdit: fopen(%s): ", filenm); 66030595Ssam perror(); 66130595Ssam exit(1); 66230595Ssam } 66330595Ssam c1 = fgetc(inf); c2 = fgetc(inf); 66430595Ssam if (c1 != '%' || c2 != '!') 66530595Ssam fprintf(stderr, "psdit: %s not a postscript file.\n", filenm), 66630595Ssam exit(1); 66730595Ssam 66832179Sedward fputs("%!", stdout); 66930595Ssam while ((ch = fgetc(inf)) != EOF) { 67032179Sedward putchar(ch); 67130595Ssam if (firstch && ch == '%') { 67230595Ssam /* we have to double leading '%'s */ 67332179Sedward putchar('%'); 67430595Ssam } 67530595Ssam firstch = (ch == '\n'); 676*34009Sedward } 67730595Ssam fclose(inf); 67830595Ssam } 67930595Ssam #endif 68032179Sedward 68132179Sedward fileinit() /* read in font and code files, etc. */ 68230594Ssam { 68332179Sedward int i, fin, nw; 68432179Sedward char *filebase, *p; 68532179Sedward char temp[60]; 68632179Sedward unsigned msize; 68730594Ssam 68832179Sedward /* 68932179Sedward * Open table for device, 69032179Sedward * read in resolution, size info, font info, etc., and set params. 69132179Sedward */ 69232179Sedward sprintf(temp, "%s/dev%s/DESC.out", ditdir, devname); 69332179Sedward if ((fin = open(temp, 0)) < 0) { 69432179Sedward fprintf(stderr, "%s: can't open %s - %s\n", 69532179Sedward prog, devname, temp); 69632179Sedward pexit(prog, 2); 69732179Sedward } 69832179Sedward if (read(fin, (char *) &dev, sizeof (struct dev)) != 69932179Sedward sizeof (struct dev)) { 70032179Sedward fprintf(stderr, "%s: can't read %s\n", prog, temp); 70132179Sedward pexit(prog, 2); 70232179Sedward } 70332179Sedward dres = dev.res; 70432179Sedward nfonts = dev.nfonts; 70532179Sedward nsizes = dev.nsizes; 70632179Sedward nchtab = dev.nchtab; 70732179Sedward /* enough room for whole file */ 70832179Sedward filebase = malloc((unsigned) dev.filesize); 70932179Sedward if (read(fin, filebase, dev.filesize) != dev.filesize) { 71032179Sedward fprintf(stderr, "%s: trouble reading %s\n", prog, temp); 71132179Sedward pexit(prog, 2); 71232179Sedward } 71332179Sedward pstab = (short *) filebase; /* point size table */ 71432179Sedward chtab = pstab + nsizes + 1; /* char index table */ 71532179Sedward chname = (char *) (chtab + dev.nchtab); /* char name table */ 71632179Sedward p = chname + dev.lchname; /* end of char name table */ 71732179Sedward /* parse the preloaded font tables */ 71832179Sedward for (i = 1; i <= nfonts; i++) { 71932179Sedward fontdelta[i] = 0; 72032179Sedward fontbase[i] = (struct font *) p; 72132179Sedward nw = *p & BMASK; /* number of width entries */ 72232179Sedward if ((smnt == 0) && (fontbase[i]->specfont == 1)) 72332179Sedward smnt = i; /* first special font */ 72432179Sedward p += sizeof (struct font); /* skip header */ 72532179Sedward widthtab[i] = p; /* width table */ 72632179Sedward /* kern table is next */ 72732179Sedward codetab[i] = p + 2 * nw; /* device codes */ 72832179Sedward fitab[i] = p + 3 * nw; /* font index table */ 72932179Sedward p += 3 * nw + dev.nchtab + (128 - 32); /* next font */ 73032179Sedward t_fp(i, fontbase[i]->namefont, fontbase[i]->intname); 73132179Sedward loadpswidths(i, fontbase[i]->namefont); 73232179Sedward sayload(i, fontbase[i]->namefont, (char *) 0); 73330594Ssam #ifdef DEBUG 73432179Sedward if (fdbg > 1) 73532179Sedward fontprint(i); 73630594Ssam #endif 73732179Sedward } 73832179Sedward fontdelta[0] = 0; 73932179Sedward msize = 3*255 + dev.nchtab + (128 - 32) + sizeof (struct font); 74032179Sedward fontbase[0] = (struct font *) malloc(msize); 74132179Sedward widthtab[0] = (char *) fontbase[0] + sizeof (struct font); 74232179Sedward fontbase[0]->nwfont = 255; 74332179Sedward close(fin); 74430594Ssam } 74530594Ssam 74632179Sedward loadpswidths(i, name) 74732179Sedward int i; 74832179Sedward char *name; 74930594Ssam { 75032179Sedward char temp[60]; 75132179Sedward register FILE *auxin; 75232179Sedward register int j; 75332179Sedward int cc, wid, funny; 75430594Ssam 75532179Sedward sprintf(temp, "%s/dev%s/%s.aux", ditdir, devname, name); 75632179Sedward auxin = fopen(temp, "r"); 75732179Sedward /* allocate table */ 75832179Sedward if (pswidths[i] == NULL) 75932179Sedward pswidths[i] = (int *) malloc(256 * (sizeof (int))); 76032179Sedward /* initialize to not-there */ 76132179Sedward for (j = 0; j <= 255; pswidths[i][j++] = -1) 76232179Sedward ; 76332179Sedward /* read them in */ 76432179Sedward while (fscanf(auxin, "%d %d %d", &cc, &wid, &funny) != EOF) 76532179Sedward pswidths[i][cc] = wid | (funny << 12); 76632179Sedward (void) fclose(auxin); 76730594Ssam } 76830594Ssam 76930594Ssam #ifdef DEBUG 77032179Sedward fontprint(i) /* debugging print of font i (0, ...) */ 77130594Ssam int i; 77230594Ssam { 77332179Sedward int j, n; 77432179Sedward char *p; 77530594Ssam 77632179Sedward printf("font %d:\n", i); 77732179Sedward p = (char *) fontbase[i]; 77832179Sedward n = fontbase[i]->nwfont & BMASK; 77932179Sedward printf("base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n", 78032179Sedward p, n, fontbase[i]->specfont, 78132179Sedward fontbase[i]->namefont, widthtab[i], fitab[i]); 78232179Sedward printf("widths:\n"); 78332179Sedward for (j = 0; j <= n; j++) { 78432179Sedward printf(" %2d", widthtab[i][j] & BMASK); 78532179Sedward if (j % 20 == 19) 78632179Sedward printf("\n"); 78732179Sedward } 78832179Sedward printf("\ncodetab:\n"); 78932179Sedward for (j = 0; j <= n; j++) { 79032179Sedward printf(" %2d", codetab[i][j] & BMASK); 79132179Sedward if (j % 20 == 19) 79232179Sedward printf("\n"); 79332179Sedward } 79432179Sedward printf("\nfitab:\n"); 79532179Sedward for (j = 0; j <= dev.nchtab + 128 - 32; j++) { 79632179Sedward printf(" %2d", fitab[i][j] & BMASK); 79732179Sedward if (j % 20 == 19) 79832179Sedward printf("\n"); 79932179Sedward } 80032179Sedward printf("\n"); 80130594Ssam } 80230594Ssam #endif 80330594Ssam 80432179Sedward loadfont(n, s, s1) /* load font info for font s on position n */ 80532179Sedward int n; 80632179Sedward char *s, *s1; 80730594Ssam { 80832179Sedward char temp[60]; 80932179Sedward int fin, nw, norig; 81032179Sedward int bcount; 81130594Ssam 81232179Sedward if (n < 0 || n > NFONT) { 81332179Sedward fprintf(stderr, "%s: illegal fp command %d %s\n", prog, n, s); 81432179Sedward exit(2); 81532179Sedward } 81632179Sedward if (strcmp(s, fontbase[n]->namefont) == 0) 81732179Sedward return; 81832179Sedward if (fontbase[n]->namefont != 0) 81932179Sedward fontdelta[n] = 1; 82032179Sedward if (s1 == NULL || s1[0] == '\0') 82132179Sedward sprintf(temp, "%s/dev%s/%s.out", ditdir, devname, s); 82232179Sedward else 82332179Sedward sprintf(temp, "%s/%s.out", s1, s); 82432179Sedward if ((fin = open(temp, 0)) < 0) { 82532179Sedward fprintf(stderr, "%s: can't open font table %s\n", prog, temp); 82632179Sedward pexit(prog, 2); 82732179Sedward } 82832179Sedward norig = fontbase[n]->nwfont & BMASK; 82932179Sedward bcount = 3 * norig + nchtab + 128 - 32 + sizeof (struct font); 83032179Sedward (void) read(fin, (char *) fontbase[n], bcount); 83132179Sedward if ((fontbase[n]->nwfont & BMASK) > norig) { 83232179Sedward fprintf(stderr, "%s: Font %s too big for position %d\n", 83332179Sedward prog, s, n); 83432179Sedward exit(2); 83532179Sedward } 83632179Sedward close(fin); 83732179Sedward nw = fontbase[n]->nwfont & BMASK; 83832179Sedward widthtab[n] = (char *) fontbase[n] + sizeof (struct font); 83932179Sedward codetab[n] = (char *) widthtab[n] + 2 * nw; 84032179Sedward fitab[n] = (char *) widthtab[n] + 3 * nw; 84132179Sedward t_fp(n, fontbase[n]->namefont, fontbase[n]->intname); 84232179Sedward loadpswidths(n, fontbase[n]->namefont); 84332179Sedward sayload(n, s, s1); 84432179Sedward fontbase[n]->nwfont = norig; /* so can later use full original size */ 84530594Ssam #ifdef DEBUG 84632179Sedward if (fdbg > 1) 84732179Sedward fontprint(n); 84830594Ssam #endif 84930594Ssam } 85030594Ssam 85132179Sedward sayload(n, s, s1) /* position n contains font s (internal s1) */ 85232179Sedward int n; 85332179Sedward char *s, *s1; 85430594Ssam { 85532179Sedward char pass[60]; 85632179Sedward FILE *ptrfile; 85732179Sedward char Adobefont[60]; 85830594Ssam 85932179Sedward if (s1 == NULL || s1[0] == '\0') 86032179Sedward sprintf(pass, "%s/dev%s/%s.map", ditdir, devname, s); 86132179Sedward else 86232179Sedward sprintf(pass, "%s/%s.map", s1, s); 86332179Sedward if ((ptrfile = fopen(pass, "r")) == NULL) { 86432179Sedward fprintf(stderr, "%s: can't open font map file %s\n", 86532179Sedward prog, pass); 86632179Sedward pexit(prog, 2); 86732179Sedward } 86832179Sedward fscanf(ptrfile, "%s", Adobefont); 86932179Sedward FlushShow(0); 87032179Sedward printf("%d(%s)xf %d f\n", n, Adobefont, n); 87132179Sedward font = n; 87232179Sedward (void) fclose(ptrfile); 87330594Ssam } 87430594Ssam 87532179Sedward done() 87630594Ssam { 87732179Sedward t_reset('s'); 87832179Sedward exit(0); 87930594Ssam } 88030594Ssam 88132179Sedward t_init() /* "x i" - initialize device */ 88230594Ssam { 88332179Sedward movepending = NONE; 88432179Sedward savex = savey = 0; 88530594Ssam 88632179Sedward t_size(10); /* start somewhere */ 88732179Sedward t_slant(0); 88832179Sedward setfont(1); /* set font */ 88932179Sedward printf("xi\n"); 89032179Sedward printf("%%%%EndProlog\n"); 89130594Ssam } 89230594Ssam 89332179Sedward t_push() /* begin a new block */ 89430594Ssam { 89532179Sedward FlushShow(1); 89632179Sedward MoveTo(); 89732179Sedward DoMove(); 89832179Sedward if (dlevel == DSTACK) { 89932179Sedward fprintf(stderr, "%s: ditroff push/pop overflow!\n", prog); 90032179Sedward exit(2); 90132179Sedward } 90232179Sedward ditstack[dlevel].hpos = hpos; 90332179Sedward ditstack[dlevel].vpos = vpos; 90432179Sedward ditstack[dlevel].fontsize = fontsize; 90532179Sedward ditstack[dlevel].fontheight = fontheight; 90632179Sedward ditstack[dlevel].fontslant = fontslant; 90732179Sedward ditstack[dlevel].font = font; 90832179Sedward dlevel++; 90932179Sedward printf("\nditpush\n"); 91030594Ssam } 91130594Ssam 91232179Sedward t_pop() /* pop to previous state */ 91330594Ssam { 91432179Sedward FlushShow(1); 91532179Sedward MoveTo(); 91632179Sedward DoMove(); 91732179Sedward if (dlevel == 0) { 91832179Sedward fprintf(stderr, "%s: ditroff push/pop underflow!\n", prog); 91932179Sedward exit(2); 92032179Sedward } 92132179Sedward dlevel--; 92232179Sedward hpos = ditstack[dlevel].hpos; 92332179Sedward vpos = ditstack[dlevel].vpos; 92432179Sedward fontsize = ditstack[dlevel].fontsize; 92532179Sedward fontheight = ditstack[dlevel].fontheight; 92632179Sedward fontslant = ditstack[dlevel].fontslant; 92732179Sedward font = ditstack[dlevel].font; 92832179Sedward printf("%d s %d xH %d xS %d f\n", 92932179Sedward fontsize, fontheight, fontslant, font); 93032179Sedward startx = savex = hpos; 93132179Sedward savey = vpos; 93232179Sedward PSx = hpos * PSmag; 93332179Sedward PSy = vpos * PSmag; 93432179Sedward printf("%d %d MXY\n", savex, savey); 93532179Sedward movepending = NONE; 93632179Sedward printf("\nditpop\n"); 93730594Ssam } 93830594Ssam 93932179Sedward t_page(n) /* do whatever new page functions */ 94030594Ssam { 94132179Sedward register int i; 94230594Ssam 94332179Sedward if (output && ++scount >= spage) { 94432179Sedward t_reset('p'); 94532179Sedward scount = 0; 94630594Ssam } 94732179Sedward output = 1; 94832179Sedward FlushShow(0); 94932179Sedward if (!firstpage) 95032179Sedward printf("\n%d p", n); 95132179Sedward firstpage = FALSE; 95232179Sedward printf("\n%%%%Page: %d %d\n", n, ++pageno, n); 95332179Sedward for (i = 0; i <= nfonts; i++) 95432179Sedward if (fontdelta[i] != 0) 95532179Sedward sayload(i, fontname[i].name, (char *) 0); 95632179Sedward vpos = 0; 95732179Sedward PSy = 0; 95832179Sedward printf("%d s %d xH %d xS %d f\n", 95932179Sedward fontsize, fontheight, fontslant, font); 96032179Sedward if (nolist == 0) 96132179Sedward return; 96232179Sedward output = 0; 96332179Sedward for (i = 0; i < nolist; i += 2) 96432179Sedward if (n >= olist[i] && n <= olist[i + 1]) { 96532179Sedward output = 1; 96632179Sedward break; 96732179Sedward } 96830594Ssam } 96930594Ssam 97032179Sedward t_size(n) /* convert integer to internal size number*/ 97132179Sedward int n; 97230594Ssam { 97332179Sedward FlushShow(1); 97432179Sedward if (fontsize != n) { 97532179Sedward fontsize = n; 97630595Ssam #ifdef XMOD 97732179Sedward fontheight = n; 97830595Ssam #endif 97932179Sedward printf("%d s\n", fontsize); 98032179Sedward } 98130594Ssam } 98230594Ssam 98332179Sedward t_charht(n) /* set character height to n */ 98432179Sedward int n; 98530594Ssam { 98632179Sedward FlushShow(1); 98732179Sedward if (fontheight != n) { 98832179Sedward fontheight = n; 98932179Sedward printf("%d xH\n", fontheight); 99032179Sedward } 99130594Ssam } 99230594Ssam 99332179Sedward t_slant(n) /* set slant to n */ 99432179Sedward int n; 99530594Ssam { 99632179Sedward FlushShow(1); 99732179Sedward if (fontslant != n) { 99832179Sedward fontslant = n; 99932179Sedward printf("%d xS\n", fontslant); 100032179Sedward } 100130594Ssam } 100230594Ssam 100332179Sedward t_font(s) /* convert string to internal font number */ 100432179Sedward char *s; 100530594Ssam { 100632179Sedward int n; 100730594Ssam 100832179Sedward n = atoi(s); 100932179Sedward return n < 0 || n > nfonts ? 1 : n; 101030594Ssam } 101130594Ssam 101232179Sedward t_text(s) /* print string s as text??? */ 101332179Sedward char *s; 101430594Ssam { 101532179Sedward fprintf(stderr, "%s: ditroff t <%s> unimplemented!\n", prog, s); 101630594Ssam } 101730594Ssam 101832179Sedward t_reset(c) 101930594Ssam { 102032179Sedward output = 1; /* by God */ 102132179Sedward if (c == 'p') 102232179Sedward printf("\nxp\n"); 102332179Sedward else if (!stopped) { 102432179Sedward printf("\nxs\n"); 102532179Sedward stopped = 1; 102632179Sedward } 102732179Sedward fflush(stdout); 102830594Ssam } 102930594Ssam 103032179Sedward t_res(res, minh, minv) 103132179Sedward int res, minh, minv; 103230594Ssam { 103332179Sedward resolution = res; 103432179Sedward minhoriz = minh; 103532179Sedward minvert = minv; 103632179Sedward printf("%d %d %d xr\n", res, minh, minv); 103730594Ssam } 103830594Ssam 103932179Sedward t_trailer() 104030594Ssam { 104132179Sedward FlushShow(0); 104232179Sedward printf("\n%d p", pageno); 104332179Sedward printf("\n%%%%Trailer\n"); 104432179Sedward printf("xt\n"); 104530594Ssam } 104630594Ssam 104732179Sedward put1s(s) /* s is a funny char name */ 104830594Ssam char *s; 104930594Ssam { 105032179Sedward int i; 105130594Ssam 105232179Sedward if (!output) 105332179Sedward return; 105432179Sedward debugp(("%s ", s)); 105530594Ssam 105632179Sedward /* search for s in the funny char name table */ 105732179Sedward for (i = 0; i < nchtab; i++) 105832179Sedward if (strcmp(&chname[chtab[i]], s) == 0) 105932179Sedward break; 106032179Sedward if (i < nchtab) 106132179Sedward put1(i + 128, s); 106232179Sedward else { 106332179Sedward debugp(("not found ")); 106432179Sedward putnf(0, s); 106532179Sedward } 106630594Ssam } 106730594Ssam 106832179Sedward #define needsescape(c) ((c) == '\\' || (c) == '(' || (c) == ')') 106930594Ssam 107032179Sedward put1(c, s) /* output char c */ 107132179Sedward int c; 107232179Sedward char *s; 107330594Ssam { 107432179Sedward char *pw; 107532179Sedward register char *p; 107632179Sedward register int i, k; 107732179Sedward register int cc; 107832179Sedward int ofont, code; 107932179Sedward int psinfo, pswid, tw; 108030594Ssam 108132179Sedward if (!output) 108232179Sedward return; 108332179Sedward if (c == ' ') { 108432179Sedward thisw = 0; 108532179Sedward FlushShow(0); 108632179Sedward return; 108732179Sedward } 108832179Sedward if (c < ' ') { 108932179Sedward debugp(("non-exist 0%o\n", c)); 109032179Sedward return; 109132179Sedward } 109232179Sedward c -= 32; /* offset char code */ 109332179Sedward k = ofont = pfont = font; 109432179Sedward if (onspecial) 109532179Sedward pfont = prevfont; 109632179Sedward if ((i = fitab[pfont][c] & BMASK) != 0) { /* char on this font */ 109732179Sedward p = codetab[pfont]; 109832179Sedward pw = widthtab[pfont]; 109932179Sedward if (onspecial) { 110032179Sedward setfont(prevfont); 110132179Sedward thisw = 0; 110232179Sedward onspecial = 0; 110332179Sedward } 110432179Sedward } else if (smnt > 0) { /* on special (we hope) */ 110532179Sedward for (k = smnt; k <= nfonts; k += 1) 110632179Sedward if ((i = fitab[k][c] & BMASK) != 0) { 110732179Sedward p = codetab[k]; 110832179Sedward pw = widthtab[k]; 110932179Sedward prevfont = pfont; 111032179Sedward if (onspecial && k == specfont) 111132179Sedward break; 111232179Sedward setfont(k); 111332179Sedward thisw = 0; 111432179Sedward onspecial = 1; 111532179Sedward specfont = k; 111632179Sedward break; 111732179Sedward } 111832179Sedward } 111932179Sedward if (i == 0 || k > nfonts || (code = p[i] & BMASK) == 0) { 112032179Sedward debugp(("not found 0%o\n", c + 32)); 112132179Sedward putnf(c + 32, s); 112232179Sedward return; 112332179Sedward } 112432179Sedward /* 112532179Sedward * when we get here, 112632179Sedward * c == biased character code 112732179Sedward * k == font number 112832179Sedward * i == index into codetab and widthtab for this character 112932179Sedward * p == codetab for this font 113032179Sedward * pw == width tab for this font 113132179Sedward * code == character code for this char 113232179Sedward */ 113332179Sedward cc = c + 32; 113432179Sedward debugp(((isascii(cc) && isprint(cc)) ? "%c %d\n":"%03o %d\n", 113532179Sedward cc, code)); 113632179Sedward psinfo = pswidths[font][code]; /* PS specific char info */ 113732179Sedward pswid = psinfo & PSWID; /* PS character width */ 113832179Sedward thisw = pw[i] & BMASK; /* troff char width */ 113932179Sedward tw = thisw = (thisw * fontsize + dev.unitwidth / 2) / dev.unitwidth; 114030594Ssam 114132179Sedward if (psinfo & ISPSPROC && psinfo != -1) { 114232179Sedward /* character is implemented by a PostScript proc */ 114332179Sedward showspecial(s, code, pswid); 114432179Sedward if (pswid > 0) 114532179Sedward PSx += PSscale(pswid * fontsize * dres); 114632179Sedward thisw = 0; 114732179Sedward } else { 114832179Sedward showchar(code); 114932179Sedward if (pswid > 0) 115032179Sedward PSshowlen += PSscale(pswid * fontsize * dres); 115132179Sedward } 115230594Ssam 115332179Sedward /* 115432179Sedward if (font != ofont) { 115532179Sedward setfont(ofont); 115632179Sedward startx = hpos + tw; 115730594Ssam thisw = 0; 115832179Sedward lastcmd = FNT; 115930594Ssam } 116032179Sedward */ 116132179Sedward debugp(("...width (%d)\n", pw[i] & BMASK)); 116232179Sedward } 116330594Ssam 116432179Sedward putnf(c, s) /* note that a character wasnt found */ 116532179Sedward int c; 116632179Sedward char *s; 116732179Sedward { 116832179Sedward FlushShow(0); 116930594Ssam thisw = 0; 117032179Sedward if (s == NULL || *s == '\0') 117132179Sedward printf("(\%3o)cb\n", c); 117232179Sedward else if (strcmp(s, "\\|") == 0 || strcmp(s, "\\^") == 0 || 117332179Sedward strcmp(s, "\\&") == 0) 117432179Sedward return; 117532179Sedward else 117632179Sedward printf("(%s)cb\n", s); 117730594Ssam } 117830594Ssam 117932179Sedward t_fp(n, s, si) /* font position n now contains font s, intname si */ 118032179Sedward int n; /* position */ 118132179Sedward char *s; /* font (ditname) */ 118232179Sedward char *si; /* font (intname = number) */ 118332179Sedward { 118432179Sedward fontname[n].name = s; 118532179Sedward fontname[n].number = atoi(si); 118632179Sedward } 118730594Ssam 118832179Sedward setfont(n) /* set font to n */ 118932179Sedward int n; 119030594Ssam { 119132179Sedward FlushShow(1); 119232179Sedward if (n < 0 || n > NFONT) 119332179Sedward fprintf(stderr, "%s: illegal font %d\n", prog, n); 119432179Sedward if (font != n) { 119532179Sedward font = n; 119632179Sedward printf("%d f\n", font); 119732179Sedward } 119832179Sedward onspecial = 0; 119932179Sedward } 120030594Ssam 120132179Sedward drawline(dx, dy) /* draw line from here to dx, dy */ 120232179Sedward int dx, dy; 120332179Sedward { 120432179Sedward FlushShow(0); 120532179Sedward MoveTo(); 120632179Sedward DoMove(); 120732179Sedward printf("%d %d Dl\n", dx, dy); 120832179Sedward hpos += dx; 120932179Sedward PSx = hpos * PSmag; 121032179Sedward vpos += dy; 121132179Sedward PSy = vpos * PSmag; 121230594Ssam } 121330594Ssam 121432179Sedward drawcurve(line) 121532179Sedward char *line; 121632179Sedward { 121732179Sedward FlushShow(0); 121832179Sedward MoveTo(); 121932179Sedward DoMove(); 1220*34009Sedward getpoints(line + 1); 1221*34009Sedward /* hpos and vpos won't be changed by curve drawing code */ 1222*34009Sedward hpos = x[numpoints]; 1223*34009Sedward vpos = y[numpoints]; 1224*34009Sedward switch (*line) { 1225*34009Sedward case 'g': 1226*34009Sedward IS_Initialize(); 1227*34009Sedward IS_Convert(); 1228*34009Sedward break; 1229*34009Sedward case '~': 1230*34009Sedward BS_Initialize(); 1231*34009Sedward BS_Convert(); 1232*34009Sedward break; 1233*34009Sedward case 'z': 1234*34009Sedward BZ_Offsets(); 1235*34009Sedward BZ_Convert(); 1236*34009Sedward break; 1237*34009Sedward } 1238*34009Sedward printf("Dstroke\n"); 123932179Sedward } 124032179Sedward 1241*34009Sedward drawpoly(line) 124232179Sedward char *line; 124330594Ssam { 124432179Sedward int stipple; 124532179Sedward register i; 1246*34009Sedward register char *p; 124732179Sedward int minx, miny, maxx, maxy; 124832179Sedward 124932179Sedward FlushShow(0); 125032179Sedward MoveTo(); 125132179Sedward DoMove(); 1252*34009Sedward for (p = line + 1; isspace(*p); p++) 125332179Sedward ; 1254*34009Sedward for (stipple = 0; isdigit(*p); 1255*34009Sedward stipple = stipple * 10 + *p++ - '0') 125632179Sedward ; 1257*34009Sedward getpoints(p); 125832179Sedward minx = maxx = hpos; 125932179Sedward miny = maxy = vpos; 1260*34009Sedward for (i = 1; i <= numpoints; i++) { 1261*34009Sedward printf(" %lg %lg lineto\n", x[i], y[i]); 1262*34009Sedward if (x[i] > maxx) 1263*34009Sedward maxx = x[i]; 1264*34009Sedward if (x[i] < minx) 1265*34009Sedward minx = x[i]; 1266*34009Sedward if (y[i] > maxy) 1267*34009Sedward maxy = y[i]; 1268*34009Sedward if (y[i] < miny) 1269*34009Sedward miny = y[i]; 127032179Sedward } 127132179Sedward printf("closepath %d %d %d %d %d D%c\n", 1272*34009Sedward stipple, minx, miny, maxx, maxy, *line); 1273*34009Sedward /* XXX, hpos and vpos not changed? */ 1274*34009Sedward PSx = x[numpoints] * PSmag; 1275*34009Sedward PSy = y[numpoints] * PSmag; 127630594Ssam } 127730594Ssam 1278*34009Sedward getpoints(s) 127932179Sedward register char *s; 128030594Ssam { 128132179Sedward int h = hpos, v = vpos; 128232179Sedward 1283*34009Sedward numpoints = 0; 128432179Sedward for (;;) { 1285*34009Sedward int dh, dv, neg; 1286*34009Sedward 1287*34009Sedward numpoints++; 1288*34009Sedward x[numpoints] = h; 1289*34009Sedward y[numpoints] = v; 1290*34009Sedward if (numpoints >= MAXPOINTS - 2) /* -2 for good measure */ 129132179Sedward break; 129232179Sedward for (; isspace(*s); s++) 129332179Sedward ; 129432179Sedward if (neg = *s == '-') 129532179Sedward s++; 129632179Sedward if (!isdigit(*s)) 129732179Sedward break; 1298*34009Sedward for (dh = 0; isdigit(*s); dh = dh * 10 + *s++ - '0') 129932179Sedward ; 130032179Sedward if (neg) 1301*34009Sedward dh = - dh; 130232179Sedward for (; isspace(*s); s++) 130332179Sedward ; 130432179Sedward if (neg = *s == '-') 130532179Sedward s++; 130632179Sedward if (!isdigit(*s)) 130732179Sedward break; 1308*34009Sedward for (dv = 0; isdigit(*s); dv = dv * 10 + *s++ - '0') 130932179Sedward ; 131032179Sedward if (neg) 1311*34009Sedward dv = - dv; 1312*34009Sedward h += dh; 1313*34009Sedward v += dv; 131432179Sedward } 131530594Ssam } 131630594Ssam 131732179Sedward drawcirc(d) 131832179Sedward int d; 131930594Ssam { 132032179Sedward FlushShow(0); 132132179Sedward MoveTo(); 132232179Sedward DoMove(); 132332179Sedward printf("%d Dc\n", d); 1324*34009Sedward hpos += d; 1325*34009Sedward PSx = hpos * PSmag; 132630594Ssam } 132730594Ssam 132832179Sedward drawarc(dx1, dy1, dx2, dy2) 132932179Sedward int dx1, dy1, dx2, dy2; 133030594Ssam { 133132179Sedward FlushShow(0); 133232179Sedward MoveTo(); 133332179Sedward DoMove(); 133432179Sedward printf("%d %d %d %d Da\n", dx1, dy1, dx2, dy2); 133532179Sedward hpos += dx1 + dx2; 133632179Sedward PSx = hpos * PSmag; 133732179Sedward vpos += dy1 + dy2; 133832179Sedward PSy = vpos * PSmag; 133930594Ssam } 134030594Ssam 134132179Sedward drawellip(a, b) 134232179Sedward int a, b; 134330594Ssam { 134432179Sedward FlushShow(0); 134532179Sedward MoveTo(); 134632179Sedward DoMove(); 134732179Sedward printf("%d %d De\n", a, b); 134830594Ssam } 134930594Ssam 135032179Sedward hmot(a) /* relative horizontal motion */ 135132179Sedward int a; 135230594Ssam { 135332179Sedward register int aa; 135432179Sedward 135532179Sedward aa = abs(a); 135632179Sedward if (aa < 8 || aa > 10 * thisw || a >= 100 || 135732179Sedward thisw != 0 && abs(thisw - a) > 4) 135832179Sedward FlushShow(1); 135932179Sedward hpos += a; 136032179Sedward if (lastcmd != CPUT) 136132179Sedward startx = hpos; 136230594Ssam } 136330594Ssam 136432179Sedward hgoto(a) /* absolute horizontal motion */ 136532179Sedward int a; 136630594Ssam { 136732179Sedward FlushShow(1); 136832179Sedward startx = hpos = a; 136932179Sedward thisw = 0; 137030594Ssam } 137130594Ssam 137232179Sedward vmot(a) /* relative vertical motion */ 137332179Sedward int a; 137430594Ssam { 137532179Sedward FlushShow(1); 137632179Sedward vpos += a; 137732179Sedward thisw = 0; 137830594Ssam } 137930594Ssam 138032179Sedward vgoto(a) /* absolute vertical motion */ 138132179Sedward int a; 138230594Ssam { 138332179Sedward FlushShow(1); 138432179Sedward vpos = a; 138532179Sedward thisw = 0; 138630594Ssam } 138730594Ssam 138832179Sedward showspecial(s, cc, wid) 138932179Sedward char *s; 139032179Sedward int cc; 139132179Sedward int wid; 139230594Ssam { 139332179Sedward char *sp; 139430594Ssam 139532179Sedward FlushShow(0); 139632179Sedward MoveTo(); 139732179Sedward DoMove(); 139832179Sedward putchar('('); 139932179Sedward for (sp = s; *sp != '\0'; sp++) { 140032179Sedward if (needsescape(*sp)) 140132179Sedward putchar('\\'); 140232179Sedward putchar(*sp); 140330594Ssam } 140432179Sedward printf(")%d %d oc\n", cc, wid); 140530594Ssam } 140630594Ssam 140732179Sedward showchar(c) 140832179Sedward int c; 140930594Ssam { 141032179Sedward if (showind == 0) 141132179Sedward MoveTo(); 141232179Sedward else if (vpos * PSmag != PSy) { 141332179Sedward FlushShow(0); 141432179Sedward MoveTo(); 141530594Ssam } 141632179Sedward if (showind >= SHOWSIZE) 141732179Sedward FlushShow(0); 141832179Sedward if (isascii(c) && isprint(c)) 141932179Sedward switch (c) { 142032179Sedward case '\\': 142132179Sedward case '(': 142232179Sedward case ')': 142332179Sedward showbuf[showind++] = '\\'; 142432179Sedward /* fall through */ 142532179Sedward default: 142632179Sedward showbuf[showind++] = c; 142732179Sedward } 142832179Sedward else { 142932179Sedward showbuf[showind++] = '\\'; 143032179Sedward showbuf[showind++] = ((c >> 6) & 03) + '0'; 143132179Sedward showbuf[showind++] = ((c >> 3) & 07) + '0'; 143232179Sedward showbuf[showind++] = (c & 07) + '0'; 143332179Sedward } 143432179Sedward showbuf[showind] = '\0'; 143532179Sedward nshow++; 143630594Ssam } 143730594Ssam 143832179Sedward MoveTo() 143932179Sedward { 144032179Sedward int x, y; 144130594Ssam 144232179Sedward x = hpos * PSmag; 144332179Sedward y = vpos * PSmag; 144432179Sedward if (x != PSx) { 144532179Sedward startx = savex = hpos; 144632179Sedward PSx = x; 144732179Sedward movepending |= XMOVE; 144832179Sedward } 144932179Sedward if (y != PSy) { 145032179Sedward savey = vpos; 145132179Sedward PSy = y; 145232179Sedward movepending |= YMOVE; 145332179Sedward } 145430594Ssam } 145530594Ssam 145632179Sedward FlushMove() 145732179Sedward { 145832179Sedward switch (movepending) { 145930594Ssam case NONE: 146032179Sedward break; 146130594Ssam case XMOVE: 146232179Sedward printf("%d", savex); 146332179Sedward break; 146430594Ssam case YMOVE: 146532179Sedward printf("%d", savey); 146632179Sedward break; 146730594Ssam case XYMOVE: 146832179Sedward printf("%d %d", savex, savey); 146932179Sedward break; 147030594Ssam default: 147132179Sedward fprintf(stderr, "%s: invalid move code %d\n", 147232179Sedward prog, movepending); 147332179Sedward exit(2); 147432179Sedward } 147530594Ssam } 147630594Ssam 147732179Sedward char *movecmds[] = { "MX", "MY", "MXY" }; 147832179Sedward 147932179Sedward DoMove() 148032179Sedward { 148132179Sedward FlushMove(); 148232179Sedward if (movepending != NONE) { 148332179Sedward printf(" %s\n", movecmds[movepending - 1]); 148432179Sedward movepending = NONE; 148532179Sedward } 148630594Ssam } 148730594Ssam 148832179Sedward char showops[] = "SXYN"; 148930594Ssam 149032179Sedward FlushShow(t) 149132179Sedward int t; 149232179Sedward { 149332179Sedward long err, tlen; 149432179Sedward float cerror; 149532179Sedward 149632179Sedward if (showind == 0) { 149732179Sedward thisw = 0; 149832179Sedward return; 149932179Sedward } 150032179Sedward if (movepending != NONE) 150132179Sedward FlushMove(); 150232179Sedward tlen = hpos - startx; 150332179Sedward if (lastcmd == CPUT) 150432179Sedward tlen += thisw; 150532179Sedward err = tlen * PSmag - PSshowlen; 150632179Sedward if (nshow != 1 && abs(err) > ErrorTolerance) { 150732179Sedward cerror = (float) err / ((nshow - 1) * PSmag); 150830594Ssam #ifdef DEBUG 150932179Sedward fprintf(stderr, "F%d lc %d thisw %d ", t, lastcmd, thisw); 151032179Sedward fprintf(stderr, "x %ld h %ld tn %ld %ld ", 151132179Sedward startx, hpos, tlen*PSmag, PSshowlen); 151232179Sedward fprintf(stderr, "error %d %.4f %s\n", nshow, cerror, showbuf); 151332179Sedward fflush(stderr); 151430594Ssam #endif 151532179Sedward printf(" %.4f(%s)A%c\n", cerror, showbuf, showops[movepending]); 151632179Sedward } else 151732179Sedward printf("(%s)%c\n", showbuf, showops[movepending]); 151832179Sedward showind = 0; 151932179Sedward nshow = 0; 152032179Sedward showbuf[showind] = '\0'; 152132179Sedward PSx += PSshowlen; 152232179Sedward PSshowlen = 0; 152332179Sedward startx = hpos; 152432179Sedward if (lastcmd == CPUT) 152532179Sedward startx += thisw; 152632179Sedward thisw = 0; 152732179Sedward movepending = NONE; 152832179Sedward } 152930594Ssam 153032179Sedward /* The following stolen (with modifications) from ... */ 153132179Sedward /* 153232179Sedward * This program is part of gr2ps. It converts Gremlin's curve output to 153332179Sedward * control vertices of Bezier Cubics, as supported by PostScript. 153432179Sedward * Gremlin currently supports three kinds of curves: 153532179Sedward * (1) cubic interpolated spline with 153632179Sedward * i) periodic end condition, if two end points coincide 153732179Sedward * ii) natural end condition, otherwise 153832179Sedward * (2) uniform cubic B-spline with 153932179Sedward * i) closed curve (no vertex interpolated), if end vertices coincide 154032179Sedward * ii) end vertex interpolation, otherwise 154132179Sedward * (3) Bezier cubics 154232179Sedward * 154332179Sedward * The basic idea of the conversion algorithm for the first two is 154432179Sedward * (1) take each curve segment's two end points as Bezier end vertices. 154532179Sedward * (2) find two intermediate points in the orginal curve segment 154632179Sedward * (with u=1/4 and u=1/2, for example). 154732179Sedward * (3) solve for the two intermediate control vertices. 154832179Sedward * The conversion between Bezier Cubics of Gremlin and that of PostScript 154932179Sedward * is straightforward. 155032179Sedward * 155132179Sedward * Author: Peehong Chen (phc@renoir.berkeley.edu) 155232179Sedward * Date: 9/17/1986 155332179Sedward */ 155432179Sedward #include <math.h> 155532179Sedward 155632179Sedward #define BezierMax 5 155732179Sedward #define BC1 1.0/9 /* coefficient of Bezier conversion */ 155832179Sedward #define BC2 4*BC1 155932179Sedward #define BC3 3*BC2 156032179Sedward #define BC4 8*BC2 156132179Sedward 1562*34009Sedward double Qx, Qy, h[MAXPOINTS], dx[MAXPOINTS], 156332179Sedward dy[MAXPOINTS], d2x[MAXPOINTS], d2y[MAXPOINTS], d3x[MAXPOINTS], 156432179Sedward d3y[MAXPOINTS]; 156532179Sedward 156632179Sedward /* 156732179Sedward * This routine converts each segment of a curve, P1, P2, P3, and P4 156832179Sedward * to a set of two intermediate control vertices, V2 and V3, in a Bezier 156932179Sedward * segment, plus a third vertex of the end point P4 (assuming the current 157032179Sedward * position is P1), and then writes a PostScript command "V2 V3 V4 curveto" 157132179Sedward * to the output file. 157232179Sedward * The two intermediate vertices are obtained using 157332179Sedward * Q(u) = V1 * (1-u)^3 + V2 * 3u(1-u)^2 + V3 * 3(1-u)u^2 + V4 * u^3 157432179Sedward * with u=1/4, and u=1/2, 157532179Sedward * Q(1/4) = Q2 = (x2, y2) 157632179Sedward * Q(1/2) = Q3 = (x3, y3) 157732179Sedward * V1 = P1 157832179Sedward * V4 = P4 157932179Sedward * and 158032179Sedward * V2 = (32/9)*Q2 - (4/3)*(Q3 + V1) + (1/9)*V4 158132179Sedward * V3 = -(32/9)*Q2 + 4*Q3 + V1 - (4/9)*V4 158232179Sedward */ 158332179Sedward BezierSegment(x1, y1, x2, y2, x3, y3, x4, y4) 158432179Sedward double x1, y1, x2, y2, x3, y3, x4, y4; 158532179Sedward { 158632179Sedward double V2x, V2y, V3x, V3y; 158732179Sedward 158832179Sedward V2x = BC4 * x2 - BC3 * (x3 + x1) + BC1 * x4; 158932179Sedward V2y = BC4 * y2 - BC3 * (y3 + y1) + BC1 * y4; 159032179Sedward V3x = -BC4 * x2 + 4 * x3 + x1 - BC2 * x4; 159132179Sedward V3y = -BC4 * y2 + 4 * y3 + y1 - BC2 * y4; 159232179Sedward 159332179Sedward printf(" %lg %lg %lg %lg %lg %lg curveto\n", 159432179Sedward V2x, V2y, V3x, V3y, x4, y4); 1595*34009Sedward PSx = x4 * PSmag; 1596*34009Sedward PSy = y4 * PSmag; 159732179Sedward } /* end BezierSegment */ 159832179Sedward 159932179Sedward /* 160032179Sedward * This routine calculates parameteric values for use in calculating 160132179Sedward * curves. The values are an approximation of cumulative arc lengths 160232179Sedward * of the curve (uses cord * length). For additional information, 160332179Sedward * see paper cited below. 160432179Sedward * 160532179Sedward * This is from Gremlin (called Paramaterize in gremlin), 160632179Sedward * with minor modifications (elimination of param list) 160732179Sedward */ 160832179Sedward IS_Parameterize() 160932179Sedward { 161032179Sedward register i, j; 161132179Sedward double t1, t2; 161232179Sedward double u[MAXPOINTS]; 161332179Sedward 161432179Sedward for (i = 1; i <= numpoints; i++) { 161532179Sedward u[i] = 0.0; 161632179Sedward for (j = 1; j < i; j++) { 161732179Sedward t1 = x[j + 1] - x[j]; 161832179Sedward t2 = y[j + 1] - y[j]; 1619*34009Sedward u[i] += sqrt(t1 * t1 + t2 * t2); 162032179Sedward } 162132179Sedward } 162232179Sedward for (i = 1; i < numpoints; i++) 162332179Sedward h[i] = u[i + 1] - u[i]; 162432179Sedward } /* end IS_Parameterize */ 162532179Sedward 162632179Sedward /* 162732179Sedward * This routine solves for the cubic polynomial to fit a spline 162832179Sedward * curve to the the points specified by the list of values. 162932179Sedward * The curve generated is periodic. The alogrithms for this 163032179Sedward * curve are from the "Spline Curve Techniques" paper cited below. 163132179Sedward * 163232179Sedward * This is from Gremlin (called PeriodicSpline in gremlin) 163332179Sedward * 163432179Sedward */ 163532179Sedward IS_PeriodicEnd(h, z, dz, d2z, d3z) 163632179Sedward double h[MAXPOINTS]; /* Parameterizeaterization */ 163732179Sedward double z[MAXPOINTS]; /* point list */ 163832179Sedward double dz[MAXPOINTS]; /* to return the 1st derivative */ 163932179Sedward double d2z[MAXPOINTS]; /* 2nd derivative */ 164032179Sedward double d3z[MAXPOINTS]; /* and 3rd derivative */ 164132179Sedward { 164232179Sedward double a[MAXPOINTS]; 164332179Sedward double b[MAXPOINTS]; 164432179Sedward double c[MAXPOINTS]; 164532179Sedward double d[MAXPOINTS]; 164632179Sedward double deltaz[MAXPOINTS]; 164732179Sedward double r[MAXPOINTS]; 164832179Sedward double s[MAXPOINTS]; 164932179Sedward double ftmp; 165032179Sedward register i; 165132179Sedward 165232179Sedward /* step 1 */ 165332179Sedward for (i = 1; i < numpoints; i++) 165432179Sedward if (h[i] != 0) 165532179Sedward deltaz[i] = (z[i + 1] - z[i]) / h[i]; 165632179Sedward else 165732179Sedward deltaz[i] = 0; 165832179Sedward h[0] = h[numpoints - 1]; 165932179Sedward deltaz[0] = deltaz[numpoints - 1]; 166032179Sedward 166132179Sedward /* step 2 */ 166232179Sedward for (i = 1; i < numpoints - 1; i++) 166332179Sedward d[i] = deltaz[i + 1] - deltaz[i]; 166432179Sedward d[0] = deltaz[1] - deltaz[0]; 166532179Sedward 166632179Sedward /* step 3a */ 166732179Sedward a[1] = 2 * (h[0] + h[1]); 166832179Sedward if (a[1] == 0) 166932179Sedward return (-1); /* 3 consecutive knots at same point */ 167032179Sedward b[1] = d[0]; 167132179Sedward c[1] = h[0]; 167232179Sedward 167332179Sedward for (i = 2; i < numpoints - 1; i++) { 167432179Sedward ftmp = h[i - 1]; 167532179Sedward a[i] = ftmp + ftmp + h[i] + h[i] - ftmp * ftmp / a[i - 1]; 167632179Sedward if (a[i] == 0) 167732179Sedward return (-1); /* 3 consec knots at same point */ 167832179Sedward b[i] = d[i - 1] - ftmp * b[i - 1] / a[i - 1]; 167932179Sedward c[i] = - ftmp * c[i - 1]/a[i - 1]; 168032179Sedward } 168132179Sedward 168232179Sedward /* step 3b */ 168332179Sedward r[numpoints - 1] = 1; 168432179Sedward s[numpoints - 1] = 0; 168532179Sedward for (i = numpoints - 2; i > 0; i--) { 168632179Sedward r[i] = - (h[i] * r[i + 1] + c[i]) / a[i]; 168732179Sedward s[i] = (6 * b[i] - h[i] * s[i + 1]) / a[i]; 168832179Sedward } 168932179Sedward 169032179Sedward /* step 4 */ 169132179Sedward d2z[numpoints - 1] = (6 * d[numpoints - 2] - h[0] * s[1] 169232179Sedward - h[numpoints - 1] * s[numpoints - 2]) 169332179Sedward / (h[0] * r[1] + h[numpoints - 1] * r[numpoints - 2] 169432179Sedward + 2 * (h[numpoints - 2] + h[0])); 169532179Sedward for (i = 1; i < numpoints - 1; i++) 169632179Sedward d2z[i] = r[i] * d2z[numpoints - 1] + s[i]; 169732179Sedward d2z[numpoints] = d2z[1]; 169832179Sedward 169932179Sedward /* step 5 */ 170032179Sedward for (i = 1; i < numpoints; i++) { 170132179Sedward dz[i] = deltaz[i] - h[i] * (2 * d2z[i] + d2z[i + 1]) / 6; 170232179Sedward if (h[i] != 0) 170332179Sedward d3z[i] = (d2z[i + 1] - d2z[i]) / h[i]; 170432179Sedward else 170532179Sedward d3z[i] = 0; 170632179Sedward } 170732179Sedward 170832179Sedward return (0); 170932179Sedward } /* end IS_PeriodicEnd */ 171032179Sedward 171132179Sedward /* 171232179Sedward * This routine solves for the cubic polynomial to fit a spline 171332179Sedward * curve from the points specified by the list of values. The alogrithms for 171432179Sedward * this curve are from the "Spline Curve Techniques" paper cited below. 171532179Sedward * 171632179Sedward * This is from Gremlin (called NaturalEndSpline in gremlin) 171732179Sedward */ 171832179Sedward IS_NaturalEnd(h, z, dz, d2z, d3z) 171932179Sedward double h[MAXPOINTS]; /* parameterization */ 172032179Sedward double z[MAXPOINTS]; /* point list */ 172132179Sedward double dz[MAXPOINTS]; /* to return the 1st derivative */ 172232179Sedward double d2z[MAXPOINTS]; /* 2nd derivative */ 172332179Sedward double d3z[MAXPOINTS]; /* and 3rd derivative */ 172432179Sedward { 172532179Sedward double a[MAXPOINTS]; 172632179Sedward double b[MAXPOINTS]; 172732179Sedward double d[MAXPOINTS]; 172832179Sedward double deltaz[MAXPOINTS]; 172932179Sedward double ftmp; 173032179Sedward register i; 173132179Sedward 173232179Sedward /* step 1 */ 173332179Sedward for (i = 1; i < numpoints; i++) 173432179Sedward if (h[i] != 0) 173532179Sedward deltaz[i] = (z[i + 1] - z[i]) / h[i]; 173632179Sedward else 173732179Sedward deltaz[i] = 0; 173832179Sedward deltaz[0] = deltaz[numpoints - 1]; 173932179Sedward 174032179Sedward /* step 2 */ 174132179Sedward for (i = 1; i < numpoints - 1; i++) 174232179Sedward d[i] = deltaz[i + 1] - deltaz[i]; 174332179Sedward d[0] = deltaz[1] - deltaz[0]; 174432179Sedward 174532179Sedward /* step 3 */ 174632179Sedward a[0] = 2 * (h[2] + h[1]); 174732179Sedward if (a[0] == 0) /* 3 consec knots at same point */ 174832179Sedward return (-1); 174932179Sedward b[0] = d[1]; 175032179Sedward 175132179Sedward for (i = 1; i < numpoints - 2; i++) { 175232179Sedward ftmp = h[i + 1]; 175332179Sedward a[i] = ftmp + ftmp + h[i + 2] + h[i + 2] - 175432179Sedward (ftmp * ftmp) / a[i - 1]; 175532179Sedward if (a[i] == 0) /* 3 consec knots at same point */ 175632179Sedward return (-1); 175732179Sedward b[i] = d[i + 1] - ftmp * b[i - 1] / a[i - 1]; 175832179Sedward } 175932179Sedward 176032179Sedward /* step 4 */ 176132179Sedward d2z[numpoints] = d2z[1] = 0; 176232179Sedward for (i = numpoints - 1; i > 1; i--) 176332179Sedward d2z[i] = (6 * b[i - 2] - h[i] * d2z[i + 1]) / a[i - 2]; 176432179Sedward 176532179Sedward /* step 5 */ 176632179Sedward for (i = 1; i < numpoints; i++) { 176732179Sedward dz[i] = deltaz[i] - h[i] * (2 * d2z[i] + d2z[i + 1]) / 6; 176832179Sedward if (h[i] != 0) 176932179Sedward d3z[i] = (d2z[i + 1] - d2z[i]) / h[i]; 177032179Sedward else 177132179Sedward d3z[i] = 0; 177232179Sedward } 177332179Sedward 177432179Sedward return (0); 177532179Sedward } /* end IS_NaturalEnd */ 177632179Sedward 177732179Sedward /* 177832179Sedward * Use the same algorithm Gremlin uses to interpolate a given 177932179Sedward * set of points, as described in ``Spline Curve Techniques,'' 178032179Sedward * by Pattrick Baudelaire, Robert M. Flegal, and Robert F. Sproull, 178132179Sedward * Xerox PARC Tech Report No. 78CSL-059. 178232179Sedward */ 1783*34009Sedward IS_Initialize() 178432179Sedward { 178532179Sedward IS_Parameterize(); 178632179Sedward 178732179Sedward /* Solve for derivatives of the curve at each point 178832179Sedward separately for x and y (parametric). */ 178932179Sedward 179032179Sedward if (x[1] == x[numpoints] && y[1] == y[numpoints]) { /* closed curve */ 179132179Sedward IS_PeriodicEnd(h, x, dx, d2x, d3x); 179232179Sedward IS_PeriodicEnd(h, y, dy, d2y, d3y); 179332179Sedward } else { 179432179Sedward IS_NaturalEnd(h, x, dx, d2x, d3x); 179532179Sedward IS_NaturalEnd(h, y, dy, d2y, d3y); 179632179Sedward } 179730594Ssam } 179832179Sedward 179932179Sedward /* 180032179Sedward * This routine converts cubic interpolatory spline to Bezier control vertices 180132179Sedward */ 180232179Sedward IS_Convert() 180332179Sedward { 180432179Sedward double t, t2, t3, x2, y2, x3, y3; 180532179Sedward register j, j1; 180632179Sedward 180732179Sedward for (j = 1; j < numpoints; j++) { 180832179Sedward t = .25 * h[j]; 180932179Sedward t2 = t * t; 181032179Sedward t3 = t2 * t; 181132179Sedward x2 = x[j] + t * dx[j] + t2 * d2x[j] / 2.0 + t3 * d3x[j] / 6.0; 181232179Sedward y2 = y[j] + t * dy[j] + t2 * d2y[j] / 2.0 + t3 * d3y[j] / 6.0; 181332179Sedward 181432179Sedward t = 2 * t; 181532179Sedward t2 = t * t; 181632179Sedward t3 = t2 * t; 181732179Sedward x3 = x[j] + t * dx[j] + t2 * d2x[j] / 2.0 + t3 * d3x[j] / 6.0; 181832179Sedward y3 = y[j] + t * dy[j] + t2 * d2y[j] / 2.0 + t3 * d3y[j] / 6.0; 181932179Sedward 182032179Sedward j1 = j + 1; 182132179Sedward BezierSegment(x[j], y[j], x2, y2, x3, y3, x[j1], y[j1]); 182232179Sedward } 182332179Sedward } /* end IS_Convert */ 182432179Sedward 182532179Sedward /* 182632179Sedward * This routine computes a point in B-spline segment, given i, and u. 182732179Sedward * Details of this algorithm can be found in the tech. report cited below. 182832179Sedward */ 1829*34009Sedward BS_ComputePoint(i, u, xp, yp) 183032179Sedward int i; 183132179Sedward float u; 1832*34009Sedward double *xp, *yp; 183332179Sedward { 183432179Sedward float u2, u3, b_2, b_1, b0, b1; 183532179Sedward register i1, i_2, i_1; 183632179Sedward 183732179Sedward i1 = i + 1; 183832179Sedward i_1 = i - 1; 183932179Sedward i_2 = i - 2; 184032179Sedward 184132179Sedward u2 = u * u; 184232179Sedward u3 = u2 * u; 184332179Sedward b_2 = (1 - 3 * u + 3 * u2 - u3) / 6.0; 184432179Sedward b_1 = (4 - 6 * u2 + 3 * u3) / 6.0; 184532179Sedward b0 = (1 + 3 * u + 3 * u2 - 3 * u3) / 6.0; 184632179Sedward b1 = u3 / 6.0; 184732179Sedward 1848*34009Sedward *xp = b_2 * x[i_2] + b_1 * x[i_1] + b0 * x[i] + b1 * x[i1]; 1849*34009Sedward *yp = b_2 * y[i_2] + b_1 * y[i_1] + b0 * y[i] + b1 * y[i1]; 185032179Sedward } /* end BS_ComputePoint */ 185132179Sedward 185232179Sedward /* 185332179Sedward * This routine initializes the array of control vertices 185432179Sedward * We consider two end conditions here: 185532179Sedward * (1) closed curve -- C2 continuation and end vertex not interpolated, i.e. 185632179Sedward * V[0] = V[n-1], and 185732179Sedward * V[n+1] = V[2]. 185832179Sedward * (2) open curve -- end vertex interpolation, i.e. 185932179Sedward * V[0] = 2*V[1] - V[2], and 186032179Sedward * V[n+1] = 2*V[n] - V[n-1]. 186132179Sedward * Details of uniform cubic B-splines, including other end conditions 186232179Sedward * and important properties can be found in Chapters 4-5 of 186332179Sedward * Richard H. Bartels and Brian A. Barsky, 186432179Sedward * "An Introduction to the Use of Splines in Computer Graphics", 186532179Sedward * Tech. Report CS-83-136, Computer Science Division, 186632179Sedward * University of California, Berkeley, 1984. 186732179Sedward */ 1868*34009Sedward BS_Initialize() 186932179Sedward { 187032179Sedward register n_1, n1; 187132179Sedward 187232179Sedward n_1 = numpoints - 1; 187332179Sedward n1 = numpoints + 1; 187432179Sedward if (x[1] == x[numpoints] && y[1] == y[numpoints]) { /* closed curve */ 187532179Sedward x[0] = x[n_1]; /* V[0] */ 187632179Sedward y[0] = y[n_1]; 187732179Sedward x[n1] = x[2]; /* V[n+1] */ 187832179Sedward y[n1] = y[2]; 187932179Sedward } else { /* end vertex interpolation */ 1880*34009Sedward x[0] = 2 * x[1] - x[2]; /* V[0] */ 1881*34009Sedward y[0] = 2 * y[1] - y[2]; 1882*34009Sedward x[n1] = 2 * x[numpoints] - x[n_1]; /* V[n+1] */ 1883*34009Sedward y[n1] = 2 * y[numpoints] - y[n_1]; 188432179Sedward } 188532179Sedward } /* end BS_Initialize */ 188632179Sedward 188732179Sedward /* 188832179Sedward * This routine converts uniform cubic B-spline to Bezier control vertices 188932179Sedward */ 189032179Sedward BS_Convert() 189132179Sedward { 1892*34009Sedward double x1, y1, x2, y2, x3, y3, x4, y4; 189332179Sedward register i; 189432179Sedward 189532179Sedward for (i = 2; i <= numpoints; i++) { 1896*34009Sedward BS_ComputePoint(i, 0.0, &x1, &y1); 1897*34009Sedward BS_ComputePoint(i, 0.25, &x2, &y2); 1898*34009Sedward BS_ComputePoint(i, 0.5, &x3, &y3); 1899*34009Sedward BS_ComputePoint(i, 1.0, &x4, &y4); 1900*34009Sedward if (i == 2) 1901*34009Sedward printf("%lg %lg moveto\n", x1, y1); 1902*34009Sedward BezierSegment(x1, y1, x2, y2, x3, y3, x4, y4); 190332179Sedward } 190432179Sedward } /* end BS_Convert */ 190532179Sedward 190632179Sedward /* 190732179Sedward * This routine copies the offset between two consecutive control points 190832179Sedward * into an array. That is, 190932179Sedward * O[i] = (x[i], y[i]) = V[i+1] - V[i], 191032179Sedward * for i=1 to N-1, where N is the number of points given. 191132179Sedward * The starting end point (V[1]) is saved in (Qx, Qy). 191232179Sedward */ 1913*34009Sedward BZ_Offsets() 191432179Sedward { 191532179Sedward register i; 191632179Sedward 191732179Sedward /* Assign offsets btwn points to array for convenience of processing */ 1918*34009Sedward Qx = x[1]; 1919*34009Sedward Qy = y[1]; 1920*34009Sedward for (i = 1; i < numpoints; i++) { 1921*34009Sedward x[i] = x[i + 1] - x[i]; 1922*34009Sedward y[i] = y[i + 1] - y[i]; 192332179Sedward } 192432179Sedward } 192532179Sedward 192632179Sedward /* 192732179Sedward * This routine contructs paths of piecewise continuous Bezier cubics 192832179Sedward * in PostScript based on the given set of control vertices. 1929*34009Sedward * Given 2 points, a straight line is drawn. 193032179Sedward * Given 3 points V[1], V[2], and V[3], a Bezier cubic segment 193132179Sedward * of (V[1], (V[1]+V[2])/2, (V[2]+V[3])/2, V[3]) is drawn. 193232179Sedward * In the case when N (N >= 4) points are given, N-2 Bezier segments will 193332179Sedward * be drawn, each of which (for i=1 to N-2) is translated to PostScript as 193432179Sedward * Q+O[i]/3 Q+(3*O[i]+O[i+1])/6 K+O[i+1]/2 curveto, 193532179Sedward * where 193632179Sedward * Q is the current point, 193732179Sedward * K is the continuation offset = Qinitial + Sigma(1, i)(O[i]) 193832179Sedward * Note that when i is 1, the initial point 193932179Sedward * Q = V[1]. 194032179Sedward * and when i is N-2, the terminating point 194132179Sedward * K+O[i+1]/2 = V[N]. 194232179Sedward */ 194332179Sedward BZ_Convert() 194432179Sedward { 194532179Sedward register i, i1; 194632179Sedward double x1, y1, x2, y2, x3, y3, Kx, Ky; 194732179Sedward 194832179Sedward if (numpoints == 2) { 194932179Sedward printf(" %lg %lg rlineto\n", x[1], y[1]); 1950*34009Sedward PSx += x[1] * PSmag; 1951*34009Sedward PSy += y[1] * PSmag; 195232179Sedward return; 195332179Sedward } 195432179Sedward if (numpoints == 3) { 195532179Sedward x1 = Qx + x[1]; 195632179Sedward y1 = Qy + y[1]; 195732179Sedward x2 = x1 + x[2]; 195832179Sedward y2 = y1 + y[2]; 195932179Sedward printf(" %lg %lg %lg %lg %lg %lg curveto\n", 196032179Sedward (Qx + x1) / 2.0, (Qy + y1) / 2.0, (x1 + x2) / 2.0, 196132179Sedward (y1 + y2) / 2.0, x2, y2); 1962*34009Sedward PSx = x2 * PSmag; 1963*34009Sedward PSy = y2 * PSmag; 196432179Sedward return; 196532179Sedward } 196632179Sedward /* numpoints >= 4 */ 196732179Sedward Kx = Qx + x[1]; 196832179Sedward Ky = Qy + y[1]; 1969*34009Sedward x[1] *= 2; 1970*34009Sedward y[1] *= 2; 1971*34009Sedward x[numpoints - 1] *= 2; 1972*34009Sedward y[numpoints - 1] *= 2; 1973*34009Sedward for (i = 1; i <= numpoints - 2; i++) { 1974*34009Sedward i1 = i + 1; 1975*34009Sedward x1 = Qx + x[i] / 3; 1976*34009Sedward y1 = Qy + y[i] / 3; 1977*34009Sedward x2 = Qx + (3 * x[i] + x[i1]) / 6; 1978*34009Sedward y2 = Qy + (3 * y[i] + y[i1]) / 6; 1979*34009Sedward x3 = Kx + x[i1] / 2; 1980*34009Sedward y3 = Ky + y[i1] / 2; 198132179Sedward printf(" %lg %lg %lg %lg %lg %lg curveto\n", 198232179Sedward x1, y1, x2, y2, x3, y3); 198332179Sedward Qx = x3; 198432179Sedward Qy = y3; 1985*34009Sedward Kx += x[i1]; 1986*34009Sedward Ky += y[i1]; 198732179Sedward } 1988*34009Sedward PSx = x3 * PSmag; 1989*34009Sedward PSy = y3 * PSmag; 199032179Sedward } /* end BZ_Convert */ 1991