1*34804Sedward /* @(#)psdit.c 1.5 06/22/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 */ 132*34804Sedward int stipplefont; /* current stipple font */ 13330594Ssam 13432179Sedward int onspecial; 13532179Sedward int specfont; 13632179Sedward int prevfont; 13732179Sedward int pfont; 13830594Ssam 13930594Ssam /* {} push/pop stack */ 14030594Ssam #define DSTACK 10 14132179Sedward struct ditstack { 14232179Sedward int hpos, vpos, fontsize, fontheight, fontslant, font; 14330594Ssam } ditstack[DSTACK]; 14432179Sedward int dlevel = 0; 14530594Ssam 14630594Ssam #define ErrorTolerance 48 14730594Ssam #define PSWID 0x00000FFF 14830594Ssam #define ISPSPROC 0x000FF000 14930594Ssam 15030594Ssam /* PSscale is equivalent to (x * PSmag / 72000) + 0.5 */ 15130594Ssam #define PSmag 16 15232179Sedward #define PSscale(x) (((x) + 2250) / 4500) 15330594Ssam 15430594Ssam /* we maintain PS coords with PSmag times the precision */ 15530594Ssam /* current PS state is: */ 15630594Ssam 15732179Sedward int PSx; /* current horizontal position */ 15832179Sedward int PSy; /* current vertical position */ 15932179Sedward int savex, savey; /* position of start of current show string */ 16030594Ssam 16130594Ssam /* ps move types -- note that XMOVE|YMOVE == XYMOVE ! */ 16232179Sedward #define NONE 0 16332179Sedward #define XMOVE 1 16432179Sedward #define YMOVE 2 16532179Sedward #define XYMOVE 3 16630594Ssam 16732179Sedward int movepending = NONE; 16830594Ssam 16930594Ssam /* buffer string for show -- save up adjacent chars */ 17030594Ssam #define SHOWSIZE 400 17132179Sedward char showbuf[SHOWSIZE + 3]; /* extras are for quoting */ 17232179Sedward int showind = 0; /* index into string of next available byte */ 17332179Sedward int PSshowlen = 0; /* size in big units of buffered string */ 17432179Sedward int nshow = 0; /* actual number of show chars in showbuf */ 17532179Sedward int startx; /* troff starting pos of current string */ 17632179Sedward int thisw; 17730594Ssam 17830594Ssam /* #define NONE 0 */ 17932179Sedward #define HMOT 1 18032179Sedward #define VMOT 2 18132179Sedward #define CPUT 4 18232179Sedward #define BRK 8 18332179Sedward #define FNT 16 18432179Sedward int lastcmd; 18530594Ssam 18632179Sedward int output = 0; /* do we do output at all? */ 18732179Sedward int nolist = 0; /* output page list if > 0 */ 18832179Sedward int olist[20]; /* pairs of page numbers */ 18932179Sedward int spage = 9999; /* stop every spage pages */ 19032179Sedward int scount = 0; 19132179Sedward int stopped = 0; 19232179Sedward int pageno = 0; 19332179Sedward int firstpage = TRUE; 19430594Ssam 19532179Sedward struct dev dev; 19632179Sedward struct font *fontbase[NFONT+1]; 19732179Sedward short *pstab; 19832179Sedward int dres; /* resolution from DESC */ 19932179Sedward int nsizes; /* number of point sizes from DESC */ 20032179Sedward int nfonts; /* number of fonts from DESC */ 20132179Sedward int smnt; /* index of first special font */ 20232179Sedward int nchtab; 20332179Sedward char *chname; 20432179Sedward short *chtab; 20532179Sedward char *fitab[NFONT+1]; 20632179Sedward char *widthtab[NFONT+1]; /* widtab would be a better name */ 20732179Sedward char *codetab[NFONT+1]; /* device codes */ 20830594Ssam 20932179Sedward int *pswidths[NFONT+1]; /* ps width tables */ 21032179Sedward int fontdelta[NFONT+1]; /* nonzero if xf overwrites font i */ 21130594Ssam 21230594Ssam /* font position info: */ 21332179Sedward struct { 21430594Ssam char *name; 21530594Ssam int number; 21630594Ssam } fontname[NFONT+1]; 21730594Ssam 21830594Ssam #define FATAL 1 21930594Ssam #define BMASK 0377 22030594Ssam 22130594Ssam #ifdef DEBUG 22232179Sedward int dbg = 0; 22330594Ssam int fdbg = 0; 22432179Sedward #define debugp(xxx) (dbg != 0 ? (dbg--, printf xxx, fflush(stdout)) : 0) 22530594Ssam #else 22630594Ssam #define debugp(x) 22730594Ssam #endif 22830594Ssam 22932179Sedward char devname[20] = "psc"; 23030594Ssam 23132179Sedward char *infilename = "stdin"; /* input file name */ 23232179Sedward char *prologfile = PSDITPRO; 23332179Sedward char *ditdir = DitDir; 23430594Ssam 23532179Sedward char *prog; /* argv[0] - program name */ 23630594Ssam 23734009Sedward /* for curve and polygon drawing */ 23832179Sedward #define MAXPOINTS 200 23934009Sedward double x[MAXPOINTS], y[MAXPOINTS]; 24034009Sedward int numpoints; 24132179Sedward 24230594Ssam main(argc, argv) 24332179Sedward int argc; 24432179Sedward char *argv[]; 24530594Ssam { 24632179Sedward FILE *fp; 24732179Sedward int done(); 24830594Ssam 24932179Sedward prog = argv[0]; 25032179Sedward while (argc > 1 && argv[1][0] == '-') { 25132179Sedward switch (argv[1][1]) { 25232179Sedward case 'f': 25332179Sedward case 'F': 25432179Sedward if (argv[1][2]) 25532179Sedward ditdir = &argv[1][2]; 25632179Sedward else { 25732179Sedward ditdir = argv[2]; 25832179Sedward argv++; 25932179Sedward argc--; 26032179Sedward } 26132179Sedward break; 26232179Sedward case 'p': 26332179Sedward if (argv[1][2]) 26432179Sedward prologfile = &argv[1][2]; 26532179Sedward break; 26632179Sedward case 'o': 26732179Sedward outlist(&argv[1][2]); 26832179Sedward break; 26932179Sedward case 'd': 27032179Sedward #ifdef DEBUG 27132179Sedward dbg = atoi(&argv[1][2]); 27232179Sedward if (dbg == 0) 27332179Sedward dbg = 1; 27432179Sedward #endif DEBUG 27532179Sedward break; 27632179Sedward case 'b': /* ignore busy */ 27732179Sedward break; 27832179Sedward case 'w': /* ignore wait */ 27932179Sedward break; 28032179Sedward case 's': 28132179Sedward spage = atoi(&argv[1][2]); 28232179Sedward if (spage <= 0) 28332179Sedward spage = 9999; 28432179Sedward break; 28530594Ssam } 28632179Sedward argc--; 28732179Sedward argv++; 28830594Ssam } 28930594Ssam 29032179Sedward if (signal(SIGINT, done) == SIG_IGN) { 29132179Sedward signal(SIGINT, SIG_IGN); 29232179Sedward signal(SIGQUIT, SIG_IGN); 29332179Sedward signal(SIGHUP, SIG_IGN); 29432179Sedward } else { 29532179Sedward signal(SIGQUIT, done); 29632179Sedward signal(SIGHUP, done); 29732179Sedward } 29832179Sedward signal(SIGTERM, done); 29930594Ssam 30032179Sedward preface(); 30130594Ssam 30232179Sedward if (argc <= 1) 30332179Sedward conv(stdin); 30432179Sedward else 30532179Sedward while (--argc > 0) { 30632179Sedward if (strcmp(*++argv, "-") == 0) 30732179Sedward fp = stdin; 30832179Sedward else if ((fp = fopen(*argv, "r")) == NULL) { 30932179Sedward fprintf(stderr, "%s: can't open %s\n", 31032179Sedward prog, *argv); 31132179Sedward pexit(prog, 2); 31232179Sedward } 31332179Sedward infilename = *argv; 31432179Sedward conv(fp); 31532179Sedward (void) fclose(fp); 31632179Sedward } 31732179Sedward done(); 31830594Ssam } 31930594Ssam 32032179Sedward /* process list of page numbers to be printed */ 32132179Sedward outlist(s) 32232179Sedward register char *s; 32330594Ssam { 32432179Sedward int n1, n2, i; 32530594Ssam 32632179Sedward nolist = 0; 32732179Sedward while (*s) { 32832179Sedward n1 = 0; 32932179Sedward if (isdigit (*s)) 33032179Sedward do 33132179Sedward n1 = 10 * n1 + *s++ - '0'; 33232179Sedward while (isdigit(*s)); 33332179Sedward else 33432179Sedward n1 = -9999; 33532179Sedward n2 = n1; 33632179Sedward if (*s == '-') { 33732179Sedward s++; 33832179Sedward n2 = 0; 33932179Sedward if (isdigit(*s)) 34032179Sedward do 34132179Sedward n2 = 10 * n2 + *s++ - '0'; 34232179Sedward while (isdigit(*s)); 34332179Sedward else 34432179Sedward n2 = 9999; 34530594Ssam } 34632179Sedward olist[nolist++] = n1; 34732179Sedward olist[nolist++] = n2; 34832179Sedward if (*s != '\0') 34932179Sedward s++; 35030594Ssam } 35132179Sedward olist[nolist] = 0; 35230594Ssam #ifdef DEBUG 35332179Sedward if (dbg) 35432179Sedward for (i = 0; i < nolist; i += 2) 35532179Sedward printf("%3d %3d\n", olist[i], olist[i + 1]); 35632179Sedward #endif 35730594Ssam } 35830594Ssam 35932179Sedward conv(fp) /* convert a file */ 36032179Sedward register FILE *fp; 36130594Ssam { 36232179Sedward register int c, k; 36332179Sedward int m, n, n1, m1; 36432179Sedward char str[100], buf[300]; 36530594Ssam 36632179Sedward while ((c = getc(fp)) != EOF) 36732179Sedward switch (c) { 36832179Sedward case '\n': case ' ': case '\0': 36930594Ssam break; 37032179Sedward case '{': /* push down current environment */ 37132179Sedward t_push(); 37230594Ssam break; 37332179Sedward case '}': 37432179Sedward t_pop(); 37530594Ssam break; 37632179Sedward case '0': case '1': case '2': case '3': case '4': 37732179Sedward case '5': case '6': case '7': case '8': case '9': 37832179Sedward /* two motion digits plus a character */ 37932179Sedward hmot((c - '0') * 10 + getc(fp) - '0'); 38032179Sedward lastcmd = HMOT; 38132179Sedward put1(getc(fp), (char *) 0); 38232179Sedward lastcmd = CPUT; 38330594Ssam break; 38432179Sedward case 'c': /* single ascii character */ 38532179Sedward put1(getc(fp), (char *) 0); 38632179Sedward lastcmd = CPUT; 38730594Ssam break; 38832179Sedward case 'C': 38932179Sedward fscanf(fp, "%s", str); 39032179Sedward put1s(str); 39132179Sedward lastcmd = CPUT; 39232179Sedward break; 39332179Sedward case 't': /* straight text */ 39432179Sedward fgets(buf, sizeof buf, fp); 39532179Sedward t_text(buf); 39632179Sedward lastcmd = CPUT; 39732179Sedward break; 39832179Sedward case 'D': /* draw function */ 39932179Sedward fgets(buf, sizeof buf, fp); 40032179Sedward switch (buf[0]) { 40132179Sedward case 'l': /* draw a line */ 40232179Sedward sscanf(buf + 1, "%d %d", &n, &m); 40332179Sedward drawline(n, m); 40432179Sedward break; 40532179Sedward case 'c': /* circle */ 40632179Sedward sscanf(buf + 1, "%d", &n); 40732179Sedward drawcirc(n); 40832179Sedward break; 40932179Sedward case 'e': /* ellipse */ 41032179Sedward sscanf(buf + 1, "%d %d", &m, &n); 41132179Sedward drawellip(m, n); 41232179Sedward break; 41332179Sedward case 'a': /* arc */ 41432179Sedward sscanf(buf + 1, "%d %d %d %d", 41532179Sedward &n, &m, &n1, &m1); 41632179Sedward drawarc(n, m, n1, m1); 41732179Sedward break; 41832179Sedward case '~': /* b-spline */ 41932179Sedward case 'g': /* gremlin curve */ 42032179Sedward case 'z': /* bezier cubic */ 42134009Sedward drawcurve(buf); 42232179Sedward break; 42332179Sedward case 'p': /* filled polygon */ 42432179Sedward case 'P': /* bordered filled polygon */ 42534009Sedward drawpoly(buf); 42632179Sedward break; 42732179Sedward case 't': /* line thickness */ 42832179Sedward case 's': /* line style */ 42932179Sedward sscanf(buf + 1, "%d", &n); 43032179Sedward printf("%d D%c\n", n, buf[0]); 43132179Sedward break; 43232179Sedward default: 43332179Sedward fprintf(stderr, 43432179Sedward "%s: unknown drawing function %s\n", 43532179Sedward prog, buf); 43632179Sedward exit(2); 43732179Sedward } 43832179Sedward break; 43932179Sedward case 'i': 440*34804Sedward fscanf(fp, "%d", &stipplefont); 441*34804Sedward printf("%d i\n", stipplefont); 44232179Sedward break; 44332179Sedward case 's': 44432179Sedward fscanf(fp, "%d", &n); 44532179Sedward t_size(n); 44632179Sedward lastcmd = FNT; 44732179Sedward break; 44832179Sedward case 'f': 44932179Sedward fscanf(fp, "%s", str); 45032179Sedward setfont(t_font(str)); 45132179Sedward lastcmd = FNT; 45232179Sedward break; 45332179Sedward case 'H': /* absolute horizontal motion */ 45432179Sedward while ((c = getc(fp)) == ' ') 45532179Sedward ; 45632179Sedward k = 0; 45732179Sedward do 45832179Sedward k = 10 * k + c - '0'; 45932179Sedward while (isdigit(c = getc(fp))); 46032179Sedward ungetc(c, fp); 46132179Sedward hgoto(k); 46232179Sedward lastcmd = HMOT; 46332179Sedward break; 46432179Sedward case 'h': /* relative horizontal motion */ 46532179Sedward while ((c = getc(fp)) == ' ') 46632179Sedward ; 46732179Sedward k = 0; 46832179Sedward do 46932179Sedward k = 10 * k + c - '0'; 47032179Sedward while (isdigit(c = getc(fp))); 47132179Sedward ungetc(c, fp); 47232179Sedward hmot(k); 47332179Sedward lastcmd = HMOT; 47432179Sedward break; 47532179Sedward case 'w': 47632179Sedward FlushShow(1); 47732179Sedward lastcmd = BRK; 47832179Sedward break; 47932179Sedward case 'V': 48032179Sedward fscanf(fp, "%d", &n); 48132179Sedward vgoto(n); 48232179Sedward lastcmd = VMOT; 48332179Sedward break; 48432179Sedward case 'v': 48532179Sedward fscanf(fp, "%d", &n); 48632179Sedward vmot(n); 48732179Sedward lastcmd = VMOT; 48832179Sedward break; 48932179Sedward case 'p': /* new page */ 49032179Sedward fscanf(fp, "%d", &n); 49132179Sedward t_page(n); 49232179Sedward lastcmd = NONE; 49332179Sedward break; 49432179Sedward case 'n': /* end of line -- ignore */ 49532179Sedward while (getc(fp) != '\n') 49632179Sedward ; 49732179Sedward FlushShow(1); 49832179Sedward lastcmd = BRK; 49932179Sedward break; 50032179Sedward case '#': /* comment */ 50132179Sedward /* maybe should pass through as a PS comment */ 50232179Sedward while (getc(fp) != '\n') 50332179Sedward ; 50432179Sedward break; 50532179Sedward case 'x': /* device control */ 50632179Sedward devcntrl(fp); 50732179Sedward break; 50832179Sedward case '%': /* imbedded PostScript */ 50932179Sedward /* copy everything up to but NOT including a line */ 51032179Sedward /* with at single "." */ 51132179Sedward FlushShow(0); 51232179Sedward MoveTo(); 51332179Sedward DoMove(); 51432179Sedward printf("\n%% included PostScript\n"); 51532179Sedward while (fgets(buf, sizeof buf, fp) != NULL) { 51632179Sedward if (strcmp(".\n", buf) == 0) 51732179Sedward break; 51832179Sedward fputs(buf, stdout); 51932179Sedward } 52032179Sedward break; 52132179Sedward default: 52232179Sedward fprintf(stderr, "%s: bad input char \\%03o (%c)\n", 52332179Sedward prog, c, c); 52430594Ssam exit(2); 52530594Ssam } 52630594Ssam } 52730594Ssam 52830594Ssam /* put in PostScript prolog */ 52932179Sedward preface() 53030594Ssam { 53132179Sedward register FILE *prolog; 53232179Sedward char hostname[256]; 53332179Sedward char tempfile[512]; 53432179Sedward struct passwd *pswd; 53532179Sedward long clock; 53632179Sedward char *libdir; 53730594Ssam 53832179Sedward printf("%%!%s\n", COMMENTVERSION); 53932179Sedward pswd = getpwuid(getuid()); 54032179Sedward (void) gethostname(hostname, sizeof hostname); 54132179Sedward printf("%%%%Creator: %s:%s (%s)\n", hostname, 54232179Sedward pswd->pw_name, pswd->pw_gecos); 54332179Sedward printf("%%%%Title: %s (ditroff)\n", infilename); 54432179Sedward printf("%%%%CreationDate: %s", (time(&clock), ctime(&clock))); 54532179Sedward printf("%%%%EndComments\n"); 54632179Sedward if ((libdir = envget("PSLIBDIR")) == NULL) 54732179Sedward libdir = LibDir; 54832179Sedward mstrcat(tempfile, libdir, prologfile, sizeof tempfile); 54932179Sedward if (copyfile(tempfile, stdout) != 0) { 55032179Sedward fprintf(stderr, "%s: can't copy prolog file %s\n", 55132179Sedward prog, tempfile); 55232179Sedward exit(2); 55332179Sedward } 55432179Sedward printf("ditstart\n"); 55530594Ssam } 55630594Ssam 55732179Sedward devcntrl(fp) /* interpret device control functions */ 55832179Sedward FILE *fp; 55930594Ssam { 56032179Sedward char str[20], str1[50], buf[50]; 56132179Sedward int c, n, res, minh, minv; 56230594Ssam 56332179Sedward fscanf(fp, "%s", str); 56432179Sedward switch (str[0]) { /* crude for now */ 56530594Ssam case 'i': /* initialize */ 56632179Sedward fileinit(); 56732179Sedward t_init(); 56832179Sedward lastcmd = NONE; 56932179Sedward break; 57030594Ssam case 'T': /* device name */ 57132179Sedward /* 57232179Sedward fscanf(fp, "%s", devname); 57332179Sedward if (strcmp(devname, "psc")) { 57432179Sedward fprintf(stderr, "%s: device not psc\n", prog); 57532179Sedward exit(2); 57632179Sedward } 57732179Sedward */ 57832179Sedward printf("(%s)xT\n", devname); 57932179Sedward lastcmd = NONE; 58032179Sedward break; 58130594Ssam case 't': /* trailer */ 58232179Sedward t_trailer(); 58332179Sedward lastcmd = NONE; 58432179Sedward break; 58530594Ssam case 'p': /* pause -- can restart */ 58632179Sedward t_reset('p'); 58732179Sedward lastcmd = NONE; 58832179Sedward break; 58930594Ssam case 's': /* stop */ 59032179Sedward t_reset('s'); 59132179Sedward lastcmd = NONE; 59232179Sedward break; 59330594Ssam case 'r': /* resolution assumed when prepared */ 59432179Sedward fscanf(fp, "%d %d %d", &res, &minh, &minv); 59532179Sedward t_res(res, minh, minv); 59632179Sedward lastcmd = NONE; 59732179Sedward break; 59830594Ssam case 'f': /* font used */ 59932179Sedward fscanf(fp, "%d %s", &n, str); 60032179Sedward fgets(buf, sizeof buf, fp); /* in case theres a filename */ 60132179Sedward ungetc('\n', fp); /* fgets goes too far */ 60232179Sedward str1[0] = 0; /* in case there is nothing to come in */ 60332179Sedward sscanf(buf, "%s", str1); 60432179Sedward loadfont(n, str, str1); 60532179Sedward lastcmd = FNT; 60632179Sedward break; 60730594Ssam case 'H': /* char height */ 60832179Sedward fscanf(fp, "%d", &n); 60932179Sedward t_charht(n); 61032179Sedward lastcmd = FNT; 61132179Sedward break; 61230594Ssam case 'S': /* slant */ 61332179Sedward fscanf(fp, "%d", &n); 61432179Sedward t_slant(n); 61532179Sedward lastcmd = FNT; 61632179Sedward break; 61730595Ssam #ifdef XMOD 61830595Ssam case 'X': { /* \X command from ditroff */ 61930595Ssam int last; 62030595Ssam char largebuf[128]; 62130595Ssam fscanf (fp, "%1s", str); 62230595Ssam switch (str[0]) { 62330595Ssam case 'p' : 62430595Ssam FlushShow(0);MoveTo();DoMove(); 62530595Ssam fgets(largebuf, sizeof(largebuf), fp); 62630595Ssam last = strlen(largebuf) - 1; 62730595Ssam if (last >= 0 && largebuf[last] == '\n') { 62830595Ssam ungetc('\n', fp); 62930595Ssam largebuf[last] = ' '; 63030595Ssam } 63132179Sedward puts(largebuf); 63230595Ssam break; 63330595Ssam case 'f' : 63430595Ssam FlushShow(0);MoveTo();DoMove(); 63530595Ssam if (fscanf(fp, "%s", largebuf) == 1) { 63630595Ssam char *nl = (char *) index(largebuf, '\n'); 63730595Ssam if (nl) *nl = '\0'; 63830595Ssam includefile(largebuf); 63930595Ssam } else 64030595Ssam fprintf(stderr, "warning - include cmd w/o path.\n"); 64130595Ssam break; 64230595Ssam } 64330595Ssam } 64430595Ssam break; 64530595Ssam #endif 64632179Sedward } 64732179Sedward /* skip rest of input line */ 64832179Sedward while ((c = getc(fp)) != '\n' && c != EOF) 64932179Sedward ; 65030594Ssam } 65130594Ssam 65230595Ssam #ifdef XMOD 65330595Ssam includefile(filenm) 65432179Sedward char *filenm; 65532179Sedward { 65630595Ssam FILE *inf; 65730595Ssam int ch, c1, c2, firstch = 0; 65830595Ssam 65930595Ssam if (!(inf = fopen(filenm, "r"))) { 66030595Ssam fprintf(stderr, "psdit: fopen(%s): ", filenm); 66130595Ssam perror(); 66230595Ssam exit(1); 66330595Ssam } 66430595Ssam c1 = fgetc(inf); c2 = fgetc(inf); 66530595Ssam if (c1 != '%' || c2 != '!') 66630595Ssam fprintf(stderr, "psdit: %s not a postscript file.\n", filenm), 66730595Ssam exit(1); 66830595Ssam 66932179Sedward fputs("%!", stdout); 67030595Ssam while ((ch = fgetc(inf)) != EOF) { 67132179Sedward putchar(ch); 67230595Ssam if (firstch && ch == '%') { 67330595Ssam /* we have to double leading '%'s */ 67432179Sedward putchar('%'); 67530595Ssam } 67630595Ssam firstch = (ch == '\n'); 67734009Sedward } 67830595Ssam fclose(inf); 67930595Ssam } 68030595Ssam #endif 68132179Sedward 68232179Sedward fileinit() /* read in font and code files, etc. */ 68330594Ssam { 68432179Sedward int i, fin, nw; 68532179Sedward char *filebase, *p; 68632179Sedward char temp[60]; 68732179Sedward unsigned msize; 68830594Ssam 68932179Sedward /* 69032179Sedward * Open table for device, 69132179Sedward * read in resolution, size info, font info, etc., and set params. 69232179Sedward */ 69332179Sedward sprintf(temp, "%s/dev%s/DESC.out", ditdir, devname); 69432179Sedward if ((fin = open(temp, 0)) < 0) { 69532179Sedward fprintf(stderr, "%s: can't open %s - %s\n", 69632179Sedward prog, devname, temp); 69732179Sedward pexit(prog, 2); 69832179Sedward } 69932179Sedward if (read(fin, (char *) &dev, sizeof (struct dev)) != 70032179Sedward sizeof (struct dev)) { 70132179Sedward fprintf(stderr, "%s: can't read %s\n", prog, temp); 70232179Sedward pexit(prog, 2); 70332179Sedward } 70432179Sedward dres = dev.res; 70532179Sedward nfonts = dev.nfonts; 70632179Sedward nsizes = dev.nsizes; 70732179Sedward nchtab = dev.nchtab; 70832179Sedward /* enough room for whole file */ 70932179Sedward filebase = malloc((unsigned) dev.filesize); 71032179Sedward if (read(fin, filebase, dev.filesize) != dev.filesize) { 71132179Sedward fprintf(stderr, "%s: trouble reading %s\n", prog, temp); 71232179Sedward pexit(prog, 2); 71332179Sedward } 71432179Sedward pstab = (short *) filebase; /* point size table */ 71532179Sedward chtab = pstab + nsizes + 1; /* char index table */ 71632179Sedward chname = (char *) (chtab + dev.nchtab); /* char name table */ 71732179Sedward p = chname + dev.lchname; /* end of char name table */ 71832179Sedward /* parse the preloaded font tables */ 71932179Sedward for (i = 1; i <= nfonts; i++) { 72032179Sedward fontdelta[i] = 0; 72132179Sedward fontbase[i] = (struct font *) p; 72232179Sedward nw = *p & BMASK; /* number of width entries */ 72332179Sedward if ((smnt == 0) && (fontbase[i]->specfont == 1)) 72432179Sedward smnt = i; /* first special font */ 72532179Sedward p += sizeof (struct font); /* skip header */ 72632179Sedward widthtab[i] = p; /* width table */ 72732179Sedward /* kern table is next */ 72832179Sedward codetab[i] = p + 2 * nw; /* device codes */ 72932179Sedward fitab[i] = p + 3 * nw; /* font index table */ 73032179Sedward p += 3 * nw + dev.nchtab + (128 - 32); /* next font */ 73132179Sedward t_fp(i, fontbase[i]->namefont, fontbase[i]->intname); 73232179Sedward loadpswidths(i, fontbase[i]->namefont); 73332179Sedward sayload(i, fontbase[i]->namefont, (char *) 0); 73430594Ssam #ifdef DEBUG 73532179Sedward if (fdbg > 1) 73632179Sedward fontprint(i); 73730594Ssam #endif 73832179Sedward } 73932179Sedward fontdelta[0] = 0; 74032179Sedward msize = 3*255 + dev.nchtab + (128 - 32) + sizeof (struct font); 74132179Sedward fontbase[0] = (struct font *) malloc(msize); 74232179Sedward widthtab[0] = (char *) fontbase[0] + sizeof (struct font); 74332179Sedward fontbase[0]->nwfont = 255; 74432179Sedward close(fin); 74530594Ssam } 74630594Ssam 74732179Sedward loadpswidths(i, name) 74832179Sedward int i; 74932179Sedward char *name; 75030594Ssam { 75132179Sedward char temp[60]; 75232179Sedward register FILE *auxin; 75332179Sedward register int j; 75432179Sedward int cc, wid, funny; 75530594Ssam 75632179Sedward sprintf(temp, "%s/dev%s/%s.aux", ditdir, devname, name); 75732179Sedward auxin = fopen(temp, "r"); 75832179Sedward /* allocate table */ 75932179Sedward if (pswidths[i] == NULL) 76032179Sedward pswidths[i] = (int *) malloc(256 * (sizeof (int))); 76132179Sedward /* initialize to not-there */ 76232179Sedward for (j = 0; j <= 255; pswidths[i][j++] = -1) 76332179Sedward ; 76432179Sedward /* read them in */ 76532179Sedward while (fscanf(auxin, "%d %d %d", &cc, &wid, &funny) != EOF) 76632179Sedward pswidths[i][cc] = wid | (funny << 12); 76732179Sedward (void) fclose(auxin); 76830594Ssam } 76930594Ssam 77030594Ssam #ifdef DEBUG 77132179Sedward fontprint(i) /* debugging print of font i (0, ...) */ 77230594Ssam int i; 77330594Ssam { 77432179Sedward int j, n; 77532179Sedward char *p; 77630594Ssam 77732179Sedward printf("font %d:\n", i); 77832179Sedward p = (char *) fontbase[i]; 77932179Sedward n = fontbase[i]->nwfont & BMASK; 78032179Sedward printf("base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n", 78132179Sedward p, n, fontbase[i]->specfont, 78232179Sedward fontbase[i]->namefont, widthtab[i], fitab[i]); 78332179Sedward printf("widths:\n"); 78432179Sedward for (j = 0; j <= n; j++) { 78532179Sedward printf(" %2d", widthtab[i][j] & BMASK); 78632179Sedward if (j % 20 == 19) 78732179Sedward printf("\n"); 78832179Sedward } 78932179Sedward printf("\ncodetab:\n"); 79032179Sedward for (j = 0; j <= n; j++) { 79132179Sedward printf(" %2d", codetab[i][j] & BMASK); 79232179Sedward if (j % 20 == 19) 79332179Sedward printf("\n"); 79432179Sedward } 79532179Sedward printf("\nfitab:\n"); 79632179Sedward for (j = 0; j <= dev.nchtab + 128 - 32; j++) { 79732179Sedward printf(" %2d", fitab[i][j] & BMASK); 79832179Sedward if (j % 20 == 19) 79932179Sedward printf("\n"); 80032179Sedward } 80132179Sedward printf("\n"); 80230594Ssam } 80330594Ssam #endif 80430594Ssam 80532179Sedward loadfont(n, s, s1) /* load font info for font s on position n */ 80632179Sedward int n; 80732179Sedward char *s, *s1; 80830594Ssam { 80932179Sedward char temp[60]; 81032179Sedward int fin, nw, norig; 81132179Sedward int bcount; 81230594Ssam 81332179Sedward if (n < 0 || n > NFONT) { 81432179Sedward fprintf(stderr, "%s: illegal fp command %d %s\n", prog, n, s); 81532179Sedward exit(2); 81632179Sedward } 81732179Sedward if (strcmp(s, fontbase[n]->namefont) == 0) 81832179Sedward return; 81932179Sedward if (fontbase[n]->namefont != 0) 82032179Sedward fontdelta[n] = 1; 82132179Sedward if (s1 == NULL || s1[0] == '\0') 82232179Sedward sprintf(temp, "%s/dev%s/%s.out", ditdir, devname, s); 82332179Sedward else 82432179Sedward sprintf(temp, "%s/%s.out", s1, s); 82532179Sedward if ((fin = open(temp, 0)) < 0) { 82632179Sedward fprintf(stderr, "%s: can't open font table %s\n", prog, temp); 82732179Sedward pexit(prog, 2); 82832179Sedward } 82932179Sedward norig = fontbase[n]->nwfont & BMASK; 83032179Sedward bcount = 3 * norig + nchtab + 128 - 32 + sizeof (struct font); 83132179Sedward (void) read(fin, (char *) fontbase[n], bcount); 83232179Sedward if ((fontbase[n]->nwfont & BMASK) > norig) { 83332179Sedward fprintf(stderr, "%s: Font %s too big for position %d\n", 83432179Sedward prog, s, n); 83532179Sedward exit(2); 83632179Sedward } 83732179Sedward close(fin); 83832179Sedward nw = fontbase[n]->nwfont & BMASK; 83932179Sedward widthtab[n] = (char *) fontbase[n] + sizeof (struct font); 84032179Sedward codetab[n] = (char *) widthtab[n] + 2 * nw; 84132179Sedward fitab[n] = (char *) widthtab[n] + 3 * nw; 84232179Sedward t_fp(n, fontbase[n]->namefont, fontbase[n]->intname); 84332179Sedward loadpswidths(n, fontbase[n]->namefont); 84432179Sedward sayload(n, s, s1); 84532179Sedward fontbase[n]->nwfont = norig; /* so can later use full original size */ 84630594Ssam #ifdef DEBUG 84732179Sedward if (fdbg > 1) 84832179Sedward fontprint(n); 84930594Ssam #endif 85030594Ssam } 85130594Ssam 85232179Sedward sayload(n, s, s1) /* position n contains font s (internal s1) */ 85332179Sedward int n; 85432179Sedward char *s, *s1; 85530594Ssam { 85632179Sedward char pass[60]; 85732179Sedward FILE *ptrfile; 85832179Sedward char Adobefont[60]; 85930594Ssam 86032179Sedward if (s1 == NULL || s1[0] == '\0') 86132179Sedward sprintf(pass, "%s/dev%s/%s.map", ditdir, devname, s); 86232179Sedward else 86332179Sedward sprintf(pass, "%s/%s.map", s1, s); 86432179Sedward if ((ptrfile = fopen(pass, "r")) == NULL) { 86532179Sedward fprintf(stderr, "%s: can't open font map file %s\n", 86632179Sedward prog, pass); 86732179Sedward pexit(prog, 2); 86832179Sedward } 86932179Sedward fscanf(ptrfile, "%s", Adobefont); 87032179Sedward FlushShow(0); 87132179Sedward printf("%d(%s)xf %d f\n", n, Adobefont, n); 87232179Sedward font = n; 87332179Sedward (void) fclose(ptrfile); 87430594Ssam } 87530594Ssam 87632179Sedward done() 87730594Ssam { 87832179Sedward t_reset('s'); 87932179Sedward exit(0); 88030594Ssam } 88130594Ssam 88232179Sedward t_init() /* "x i" - initialize device */ 88330594Ssam { 88432179Sedward movepending = NONE; 88532179Sedward savex = savey = 0; 88630594Ssam 88732179Sedward t_size(10); /* start somewhere */ 88832179Sedward t_slant(0); 88932179Sedward setfont(1); /* set font */ 890*34804Sedward stipplefont = 1; 89132179Sedward printf("xi\n"); 89232179Sedward printf("%%%%EndProlog\n"); 89330594Ssam } 89430594Ssam 89532179Sedward t_push() /* begin a new block */ 89630594Ssam { 89732179Sedward FlushShow(1); 89832179Sedward MoveTo(); 89932179Sedward DoMove(); 90032179Sedward if (dlevel == DSTACK) { 90132179Sedward fprintf(stderr, "%s: ditroff push/pop overflow!\n", prog); 90232179Sedward exit(2); 90332179Sedward } 90432179Sedward ditstack[dlevel].hpos = hpos; 90532179Sedward ditstack[dlevel].vpos = vpos; 90632179Sedward ditstack[dlevel].fontsize = fontsize; 90732179Sedward ditstack[dlevel].fontheight = fontheight; 90832179Sedward ditstack[dlevel].fontslant = fontslant; 90932179Sedward ditstack[dlevel].font = font; 91032179Sedward dlevel++; 91132179Sedward printf("\nditpush\n"); 91230594Ssam } 91330594Ssam 91432179Sedward t_pop() /* pop to previous state */ 91530594Ssam { 91632179Sedward FlushShow(1); 91732179Sedward MoveTo(); 91832179Sedward DoMove(); 91932179Sedward if (dlevel == 0) { 92032179Sedward fprintf(stderr, "%s: ditroff push/pop underflow!\n", prog); 92132179Sedward exit(2); 92232179Sedward } 92332179Sedward dlevel--; 92432179Sedward hpos = ditstack[dlevel].hpos; 92532179Sedward vpos = ditstack[dlevel].vpos; 92632179Sedward fontsize = ditstack[dlevel].fontsize; 92732179Sedward fontheight = ditstack[dlevel].fontheight; 92832179Sedward fontslant = ditstack[dlevel].fontslant; 92932179Sedward font = ditstack[dlevel].font; 93032179Sedward printf("%d s %d xH %d xS %d f\n", 93132179Sedward fontsize, fontheight, fontslant, font); 93232179Sedward startx = savex = hpos; 93332179Sedward savey = vpos; 93432179Sedward PSx = hpos * PSmag; 93532179Sedward PSy = vpos * PSmag; 93632179Sedward printf("%d %d MXY\n", savex, savey); 93732179Sedward movepending = NONE; 93832179Sedward printf("\nditpop\n"); 93930594Ssam } 94030594Ssam 94132179Sedward t_page(n) /* do whatever new page functions */ 94230594Ssam { 94332179Sedward register int i; 94430594Ssam 94532179Sedward if (output && ++scount >= spage) { 94632179Sedward t_reset('p'); 94732179Sedward scount = 0; 94830594Ssam } 94932179Sedward output = 1; 95032179Sedward FlushShow(0); 95132179Sedward if (!firstpage) 95232179Sedward printf("\n%d p", n); 95332179Sedward firstpage = FALSE; 95432179Sedward printf("\n%%%%Page: %d %d\n", n, ++pageno, n); 95532179Sedward for (i = 0; i <= nfonts; i++) 95632179Sedward if (fontdelta[i] != 0) 95732179Sedward sayload(i, fontname[i].name, (char *) 0); 95832179Sedward vpos = 0; 95932179Sedward PSy = 0; 960*34804Sedward printf("%d s %d xH %d xS %d f %d i\n", 961*34804Sedward fontsize, fontheight, fontslant, font, stipplefont); 96232179Sedward if (nolist == 0) 96332179Sedward return; 96432179Sedward output = 0; 96532179Sedward for (i = 0; i < nolist; i += 2) 96632179Sedward if (n >= olist[i] && n <= olist[i + 1]) { 96732179Sedward output = 1; 96832179Sedward break; 96932179Sedward } 97030594Ssam } 97130594Ssam 97232179Sedward t_size(n) /* convert integer to internal size number*/ 97332179Sedward int n; 97430594Ssam { 97532179Sedward FlushShow(1); 97632179Sedward if (fontsize != n) { 97732179Sedward fontsize = n; 97830595Ssam #ifdef XMOD 97932179Sedward fontheight = n; 98030595Ssam #endif 98132179Sedward printf("%d s\n", fontsize); 98232179Sedward } 98330594Ssam } 98430594Ssam 98532179Sedward t_charht(n) /* set character height to n */ 98632179Sedward int n; 98730594Ssam { 98832179Sedward FlushShow(1); 98932179Sedward if (fontheight != n) { 99032179Sedward fontheight = n; 99132179Sedward printf("%d xH\n", fontheight); 99232179Sedward } 99330594Ssam } 99430594Ssam 99532179Sedward t_slant(n) /* set slant to n */ 99632179Sedward int n; 99730594Ssam { 99832179Sedward FlushShow(1); 99932179Sedward if (fontslant != n) { 100032179Sedward fontslant = n; 100132179Sedward printf("%d xS\n", fontslant); 100232179Sedward } 100330594Ssam } 100430594Ssam 100532179Sedward t_font(s) /* convert string to internal font number */ 100632179Sedward char *s; 100730594Ssam { 100832179Sedward int n; 100930594Ssam 101032179Sedward n = atoi(s); 101132179Sedward return n < 0 || n > nfonts ? 1 : n; 101230594Ssam } 101330594Ssam 101432179Sedward t_text(s) /* print string s as text??? */ 101532179Sedward char *s; 101630594Ssam { 101732179Sedward fprintf(stderr, "%s: ditroff t <%s> unimplemented!\n", prog, s); 101830594Ssam } 101930594Ssam 102032179Sedward t_reset(c) 102130594Ssam { 102232179Sedward output = 1; /* by God */ 102332179Sedward if (c == 'p') 102432179Sedward printf("\nxp\n"); 102532179Sedward else if (!stopped) { 102632179Sedward printf("\nxs\n"); 102732179Sedward stopped = 1; 102832179Sedward } 102932179Sedward fflush(stdout); 103030594Ssam } 103130594Ssam 103232179Sedward t_res(res, minh, minv) 103332179Sedward int res, minh, minv; 103430594Ssam { 103532179Sedward resolution = res; 103632179Sedward minhoriz = minh; 103732179Sedward minvert = minv; 103832179Sedward printf("%d %d %d xr\n", res, minh, minv); 103930594Ssam } 104030594Ssam 104132179Sedward t_trailer() 104230594Ssam { 104332179Sedward FlushShow(0); 104432179Sedward printf("\n%d p", pageno); 104532179Sedward printf("\n%%%%Trailer\n"); 104632179Sedward printf("xt\n"); 104730594Ssam } 104830594Ssam 104932179Sedward put1s(s) /* s is a funny char name */ 105030594Ssam char *s; 105130594Ssam { 105232179Sedward int i; 105330594Ssam 105432179Sedward if (!output) 105532179Sedward return; 105632179Sedward debugp(("%s ", s)); 105730594Ssam 105832179Sedward /* search for s in the funny char name table */ 105932179Sedward for (i = 0; i < nchtab; i++) 106032179Sedward if (strcmp(&chname[chtab[i]], s) == 0) 106132179Sedward break; 106232179Sedward if (i < nchtab) 106332179Sedward put1(i + 128, s); 106432179Sedward else { 106532179Sedward debugp(("not found ")); 106632179Sedward putnf(0, s); 106732179Sedward } 106830594Ssam } 106930594Ssam 107032179Sedward #define needsescape(c) ((c) == '\\' || (c) == '(' || (c) == ')') 107130594Ssam 107232179Sedward put1(c, s) /* output char c */ 107332179Sedward int c; 107432179Sedward char *s; 107530594Ssam { 107632179Sedward char *pw; 107732179Sedward register char *p; 107832179Sedward register int i, k; 107932179Sedward register int cc; 108032179Sedward int ofont, code; 108132179Sedward int psinfo, pswid, tw; 108230594Ssam 108332179Sedward if (!output) 108432179Sedward return; 108532179Sedward if (c == ' ') { 108632179Sedward thisw = 0; 108732179Sedward FlushShow(0); 108832179Sedward return; 108932179Sedward } 109032179Sedward if (c < ' ') { 109132179Sedward debugp(("non-exist 0%o\n", c)); 109232179Sedward return; 109332179Sedward } 109432179Sedward c -= 32; /* offset char code */ 109532179Sedward k = ofont = pfont = font; 109632179Sedward if (onspecial) 109732179Sedward pfont = prevfont; 109832179Sedward if ((i = fitab[pfont][c] & BMASK) != 0) { /* char on this font */ 109932179Sedward p = codetab[pfont]; 110032179Sedward pw = widthtab[pfont]; 110132179Sedward if (onspecial) { 110232179Sedward setfont(prevfont); 110332179Sedward thisw = 0; 110432179Sedward onspecial = 0; 110532179Sedward } 110632179Sedward } else if (smnt > 0) { /* on special (we hope) */ 110732179Sedward for (k = smnt; k <= nfonts; k += 1) 110832179Sedward if ((i = fitab[k][c] & BMASK) != 0) { 110932179Sedward p = codetab[k]; 111032179Sedward pw = widthtab[k]; 111132179Sedward prevfont = pfont; 111232179Sedward if (onspecial && k == specfont) 111332179Sedward break; 111432179Sedward setfont(k); 111532179Sedward thisw = 0; 111632179Sedward onspecial = 1; 111732179Sedward specfont = k; 111832179Sedward break; 111932179Sedward } 112032179Sedward } 112132179Sedward if (i == 0 || k > nfonts || (code = p[i] & BMASK) == 0) { 112232179Sedward debugp(("not found 0%o\n", c + 32)); 112332179Sedward putnf(c + 32, s); 112432179Sedward return; 112532179Sedward } 112632179Sedward /* 112732179Sedward * when we get here, 112832179Sedward * c == biased character code 112932179Sedward * k == font number 113032179Sedward * i == index into codetab and widthtab for this character 113132179Sedward * p == codetab for this font 113232179Sedward * pw == width tab for this font 113332179Sedward * code == character code for this char 113432179Sedward */ 113532179Sedward cc = c + 32; 113632179Sedward debugp(((isascii(cc) && isprint(cc)) ? "%c %d\n":"%03o %d\n", 113732179Sedward cc, code)); 113832179Sedward psinfo = pswidths[font][code]; /* PS specific char info */ 113932179Sedward pswid = psinfo & PSWID; /* PS character width */ 114032179Sedward thisw = pw[i] & BMASK; /* troff char width */ 114132179Sedward tw = thisw = (thisw * fontsize + dev.unitwidth / 2) / dev.unitwidth; 114230594Ssam 114332179Sedward if (psinfo & ISPSPROC && psinfo != -1) { 114432179Sedward /* character is implemented by a PostScript proc */ 114532179Sedward showspecial(s, code, pswid); 114632179Sedward if (pswid > 0) 114732179Sedward PSx += PSscale(pswid * fontsize * dres); 114832179Sedward thisw = 0; 114932179Sedward } else { 115032179Sedward showchar(code); 115132179Sedward if (pswid > 0) 115232179Sedward PSshowlen += PSscale(pswid * fontsize * dres); 115332179Sedward } 115430594Ssam 115532179Sedward /* 115632179Sedward if (font != ofont) { 115732179Sedward setfont(ofont); 115832179Sedward startx = hpos + tw; 115930594Ssam thisw = 0; 116032179Sedward lastcmd = FNT; 116130594Ssam } 116232179Sedward */ 116332179Sedward debugp(("...width (%d)\n", pw[i] & BMASK)); 116432179Sedward } 116530594Ssam 116632179Sedward putnf(c, s) /* note that a character wasnt found */ 116732179Sedward int c; 116832179Sedward char *s; 116932179Sedward { 117032179Sedward FlushShow(0); 117130594Ssam thisw = 0; 117232179Sedward if (s == NULL || *s == '\0') 117332179Sedward printf("(\%3o)cb\n", c); 117432179Sedward else if (strcmp(s, "\\|") == 0 || strcmp(s, "\\^") == 0 || 117532179Sedward strcmp(s, "\\&") == 0) 117632179Sedward return; 117732179Sedward else 117832179Sedward printf("(%s)cb\n", s); 117930594Ssam } 118030594Ssam 118132179Sedward t_fp(n, s, si) /* font position n now contains font s, intname si */ 118232179Sedward int n; /* position */ 118332179Sedward char *s; /* font (ditname) */ 118432179Sedward char *si; /* font (intname = number) */ 118532179Sedward { 118632179Sedward fontname[n].name = s; 118732179Sedward fontname[n].number = atoi(si); 118832179Sedward } 118930594Ssam 119032179Sedward setfont(n) /* set font to n */ 119132179Sedward int n; 119230594Ssam { 119332179Sedward FlushShow(1); 119432179Sedward if (n < 0 || n > NFONT) 119532179Sedward fprintf(stderr, "%s: illegal font %d\n", prog, n); 119632179Sedward if (font != n) { 119732179Sedward font = n; 119832179Sedward printf("%d f\n", font); 119932179Sedward } 120032179Sedward onspecial = 0; 120132179Sedward } 120230594Ssam 120332179Sedward drawline(dx, dy) /* draw line from here to dx, dy */ 120432179Sedward int dx, dy; 120532179Sedward { 120632179Sedward FlushShow(0); 120732179Sedward MoveTo(); 120832179Sedward DoMove(); 120932179Sedward printf("%d %d Dl\n", dx, dy); 121032179Sedward hpos += dx; 121132179Sedward PSx = hpos * PSmag; 121232179Sedward vpos += dy; 121332179Sedward PSy = vpos * PSmag; 121430594Ssam } 121530594Ssam 121632179Sedward drawcurve(line) 121732179Sedward char *line; 121832179Sedward { 121932179Sedward FlushShow(0); 122032179Sedward MoveTo(); 122132179Sedward DoMove(); 122234009Sedward getpoints(line + 1); 122334009Sedward /* hpos and vpos won't be changed by curve drawing code */ 122434009Sedward hpos = x[numpoints]; 122534009Sedward vpos = y[numpoints]; 122634009Sedward switch (*line) { 122734009Sedward case 'g': 122834009Sedward IS_Initialize(); 122934009Sedward IS_Convert(); 123034009Sedward break; 123134009Sedward case '~': 123234009Sedward BS_Initialize(); 123334009Sedward BS_Convert(); 123434009Sedward break; 123534009Sedward case 'z': 123634009Sedward BZ_Offsets(); 123734009Sedward BZ_Convert(); 123834009Sedward break; 123934009Sedward } 124034009Sedward printf("Dstroke\n"); 124132179Sedward } 124232179Sedward 124334009Sedward drawpoly(line) 124432179Sedward char *line; 124530594Ssam { 124632179Sedward int stipple; 124732179Sedward register i; 124834009Sedward register char *p; 124932179Sedward int minx, miny, maxx, maxy; 125032179Sedward 125132179Sedward FlushShow(0); 125232179Sedward MoveTo(); 125332179Sedward DoMove(); 125434009Sedward for (p = line + 1; isspace(*p); p++) 125532179Sedward ; 125634009Sedward for (stipple = 0; isdigit(*p); 125734009Sedward stipple = stipple * 10 + *p++ - '0') 125832179Sedward ; 125934009Sedward getpoints(p); 126032179Sedward minx = maxx = hpos; 126132179Sedward miny = maxy = vpos; 126234009Sedward for (i = 1; i <= numpoints; i++) { 126334009Sedward printf(" %lg %lg lineto\n", x[i], y[i]); 126434009Sedward if (x[i] > maxx) 126534009Sedward maxx = x[i]; 126634009Sedward if (x[i] < minx) 126734009Sedward minx = x[i]; 126834009Sedward if (y[i] > maxy) 126934009Sedward maxy = y[i]; 127034009Sedward if (y[i] < miny) 127134009Sedward miny = y[i]; 127232179Sedward } 127332179Sedward printf("closepath %d %d %d %d %d D%c\n", 127434009Sedward stipple, minx, miny, maxx, maxy, *line); 127534009Sedward /* XXX, hpos and vpos not changed? */ 127634009Sedward PSx = x[numpoints] * PSmag; 127734009Sedward PSy = y[numpoints] * PSmag; 127830594Ssam } 127930594Ssam 128034009Sedward getpoints(s) 128132179Sedward register char *s; 128230594Ssam { 128332179Sedward int h = hpos, v = vpos; 128432179Sedward 128534009Sedward numpoints = 0; 128632179Sedward for (;;) { 128734009Sedward int dh, dv, neg; 128834009Sedward 128934009Sedward numpoints++; 129034009Sedward x[numpoints] = h; 129134009Sedward y[numpoints] = v; 129234009Sedward if (numpoints >= MAXPOINTS - 2) /* -2 for good measure */ 129332179Sedward break; 129432179Sedward for (; isspace(*s); s++) 129532179Sedward ; 129632179Sedward if (neg = *s == '-') 129732179Sedward s++; 129832179Sedward if (!isdigit(*s)) 129932179Sedward break; 130034009Sedward for (dh = 0; isdigit(*s); dh = dh * 10 + *s++ - '0') 130132179Sedward ; 130232179Sedward if (neg) 130334009Sedward dh = - dh; 130432179Sedward for (; isspace(*s); s++) 130532179Sedward ; 130632179Sedward if (neg = *s == '-') 130732179Sedward s++; 130832179Sedward if (!isdigit(*s)) 130932179Sedward break; 131034009Sedward for (dv = 0; isdigit(*s); dv = dv * 10 + *s++ - '0') 131132179Sedward ; 131232179Sedward if (neg) 131334009Sedward dv = - dv; 131434009Sedward h += dh; 131534009Sedward v += dv; 131632179Sedward } 131730594Ssam } 131830594Ssam 131932179Sedward drawcirc(d) 132032179Sedward int d; 132130594Ssam { 132232179Sedward FlushShow(0); 132332179Sedward MoveTo(); 132432179Sedward DoMove(); 132532179Sedward printf("%d Dc\n", d); 132634009Sedward hpos += d; 132734009Sedward PSx = hpos * PSmag; 132830594Ssam } 132930594Ssam 133032179Sedward drawarc(dx1, dy1, dx2, dy2) 133132179Sedward int dx1, dy1, dx2, dy2; 133230594Ssam { 133332179Sedward FlushShow(0); 133432179Sedward MoveTo(); 133532179Sedward DoMove(); 133632179Sedward printf("%d %d %d %d Da\n", dx1, dy1, dx2, dy2); 133732179Sedward hpos += dx1 + dx2; 133832179Sedward PSx = hpos * PSmag; 133932179Sedward vpos += dy1 + dy2; 134032179Sedward PSy = vpos * PSmag; 134130594Ssam } 134230594Ssam 134332179Sedward drawellip(a, b) 134432179Sedward int a, b; 134530594Ssam { 134632179Sedward FlushShow(0); 134732179Sedward MoveTo(); 134832179Sedward DoMove(); 134932179Sedward printf("%d %d De\n", a, b); 135030594Ssam } 135130594Ssam 135232179Sedward hmot(a) /* relative horizontal motion */ 135332179Sedward int a; 135430594Ssam { 135532179Sedward register int aa; 135632179Sedward 135732179Sedward aa = abs(a); 135832179Sedward if (aa < 8 || aa > 10 * thisw || a >= 100 || 135932179Sedward thisw != 0 && abs(thisw - a) > 4) 136032179Sedward FlushShow(1); 136132179Sedward hpos += a; 136232179Sedward if (lastcmd != CPUT) 136332179Sedward startx = hpos; 136430594Ssam } 136530594Ssam 136632179Sedward hgoto(a) /* absolute horizontal motion */ 136732179Sedward int a; 136830594Ssam { 136932179Sedward FlushShow(1); 137032179Sedward startx = hpos = a; 137132179Sedward thisw = 0; 137230594Ssam } 137330594Ssam 137432179Sedward vmot(a) /* relative vertical motion */ 137532179Sedward int a; 137630594Ssam { 137732179Sedward FlushShow(1); 137832179Sedward vpos += a; 137932179Sedward thisw = 0; 138030594Ssam } 138130594Ssam 138232179Sedward vgoto(a) /* absolute vertical motion */ 138332179Sedward int a; 138430594Ssam { 138532179Sedward FlushShow(1); 138632179Sedward vpos = a; 138732179Sedward thisw = 0; 138830594Ssam } 138930594Ssam 139032179Sedward showspecial(s, cc, wid) 139132179Sedward char *s; 139232179Sedward int cc; 139332179Sedward int wid; 139430594Ssam { 139532179Sedward char *sp; 139630594Ssam 139732179Sedward FlushShow(0); 139832179Sedward MoveTo(); 139932179Sedward DoMove(); 140032179Sedward putchar('('); 140132179Sedward for (sp = s; *sp != '\0'; sp++) { 140232179Sedward if (needsescape(*sp)) 140332179Sedward putchar('\\'); 140432179Sedward putchar(*sp); 140530594Ssam } 140632179Sedward printf(")%d %d oc\n", cc, wid); 140730594Ssam } 140830594Ssam 140932179Sedward showchar(c) 141032179Sedward int c; 141130594Ssam { 141232179Sedward if (showind == 0) 141332179Sedward MoveTo(); 141432179Sedward else if (vpos * PSmag != PSy) { 141532179Sedward FlushShow(0); 141632179Sedward MoveTo(); 141730594Ssam } 141832179Sedward if (showind >= SHOWSIZE) 141932179Sedward FlushShow(0); 142032179Sedward if (isascii(c) && isprint(c)) 142132179Sedward switch (c) { 142232179Sedward case '\\': 142332179Sedward case '(': 142432179Sedward case ')': 142532179Sedward showbuf[showind++] = '\\'; 142632179Sedward /* fall through */ 142732179Sedward default: 142832179Sedward showbuf[showind++] = c; 142932179Sedward } 143032179Sedward else { 143132179Sedward showbuf[showind++] = '\\'; 143232179Sedward showbuf[showind++] = ((c >> 6) & 03) + '0'; 143332179Sedward showbuf[showind++] = ((c >> 3) & 07) + '0'; 143432179Sedward showbuf[showind++] = (c & 07) + '0'; 143532179Sedward } 143632179Sedward showbuf[showind] = '\0'; 143732179Sedward nshow++; 143830594Ssam } 143930594Ssam 144032179Sedward MoveTo() 144132179Sedward { 144232179Sedward int x, y; 144330594Ssam 144432179Sedward x = hpos * PSmag; 144532179Sedward y = vpos * PSmag; 144632179Sedward if (x != PSx) { 144732179Sedward startx = savex = hpos; 144832179Sedward PSx = x; 144932179Sedward movepending |= XMOVE; 145032179Sedward } 145132179Sedward if (y != PSy) { 145232179Sedward savey = vpos; 145332179Sedward PSy = y; 145432179Sedward movepending |= YMOVE; 145532179Sedward } 145630594Ssam } 145730594Ssam 145832179Sedward FlushMove() 145932179Sedward { 146032179Sedward switch (movepending) { 146130594Ssam case NONE: 146232179Sedward break; 146330594Ssam case XMOVE: 146432179Sedward printf("%d", savex); 146532179Sedward break; 146630594Ssam case YMOVE: 146732179Sedward printf("%d", savey); 146832179Sedward break; 146930594Ssam case XYMOVE: 147032179Sedward printf("%d %d", savex, savey); 147132179Sedward break; 147230594Ssam default: 147332179Sedward fprintf(stderr, "%s: invalid move code %d\n", 147432179Sedward prog, movepending); 147532179Sedward exit(2); 147632179Sedward } 147730594Ssam } 147830594Ssam 147932179Sedward char *movecmds[] = { "MX", "MY", "MXY" }; 148032179Sedward 148132179Sedward DoMove() 148232179Sedward { 148332179Sedward FlushMove(); 148432179Sedward if (movepending != NONE) { 148532179Sedward printf(" %s\n", movecmds[movepending - 1]); 148632179Sedward movepending = NONE; 148732179Sedward } 148830594Ssam } 148930594Ssam 149032179Sedward char showops[] = "SXYN"; 149130594Ssam 149232179Sedward FlushShow(t) 149332179Sedward int t; 149432179Sedward { 149532179Sedward long err, tlen; 149632179Sedward float cerror; 149732179Sedward 149832179Sedward if (showind == 0) { 149932179Sedward thisw = 0; 150032179Sedward return; 150132179Sedward } 150232179Sedward if (movepending != NONE) 150332179Sedward FlushMove(); 150432179Sedward tlen = hpos - startx; 150532179Sedward if (lastcmd == CPUT) 150632179Sedward tlen += thisw; 150732179Sedward err = tlen * PSmag - PSshowlen; 150832179Sedward if (nshow != 1 && abs(err) > ErrorTolerance) { 150932179Sedward cerror = (float) err / ((nshow - 1) * PSmag); 151030594Ssam #ifdef DEBUG 151132179Sedward fprintf(stderr, "F%d lc %d thisw %d ", t, lastcmd, thisw); 151232179Sedward fprintf(stderr, "x %ld h %ld tn %ld %ld ", 151332179Sedward startx, hpos, tlen*PSmag, PSshowlen); 151432179Sedward fprintf(stderr, "error %d %.4f %s\n", nshow, cerror, showbuf); 151532179Sedward fflush(stderr); 151630594Ssam #endif 151732179Sedward printf(" %.4f(%s)A%c\n", cerror, showbuf, showops[movepending]); 151832179Sedward } else 151932179Sedward printf("(%s)%c\n", showbuf, showops[movepending]); 152032179Sedward showind = 0; 152132179Sedward nshow = 0; 152232179Sedward showbuf[showind] = '\0'; 152332179Sedward PSx += PSshowlen; 152432179Sedward PSshowlen = 0; 152532179Sedward startx = hpos; 152632179Sedward if (lastcmd == CPUT) 152732179Sedward startx += thisw; 152832179Sedward thisw = 0; 152932179Sedward movepending = NONE; 153032179Sedward } 153130594Ssam 153232179Sedward /* The following stolen (with modifications) from ... */ 153332179Sedward /* 153432179Sedward * This program is part of gr2ps. It converts Gremlin's curve output to 153532179Sedward * control vertices of Bezier Cubics, as supported by PostScript. 153632179Sedward * Gremlin currently supports three kinds of curves: 153732179Sedward * (1) cubic interpolated spline with 153832179Sedward * i) periodic end condition, if two end points coincide 153932179Sedward * ii) natural end condition, otherwise 154032179Sedward * (2) uniform cubic B-spline with 154132179Sedward * i) closed curve (no vertex interpolated), if end vertices coincide 154232179Sedward * ii) end vertex interpolation, otherwise 154332179Sedward * (3) Bezier cubics 154432179Sedward * 154532179Sedward * The basic idea of the conversion algorithm for the first two is 154632179Sedward * (1) take each curve segment's two end points as Bezier end vertices. 154732179Sedward * (2) find two intermediate points in the orginal curve segment 154832179Sedward * (with u=1/4 and u=1/2, for example). 154932179Sedward * (3) solve for the two intermediate control vertices. 155032179Sedward * The conversion between Bezier Cubics of Gremlin and that of PostScript 155132179Sedward * is straightforward. 155232179Sedward * 155332179Sedward * Author: Peehong Chen (phc@renoir.berkeley.edu) 155432179Sedward * Date: 9/17/1986 155532179Sedward */ 155632179Sedward #include <math.h> 155732179Sedward 155832179Sedward #define BezierMax 5 155932179Sedward #define BC1 1.0/9 /* coefficient of Bezier conversion */ 156032179Sedward #define BC2 4*BC1 156132179Sedward #define BC3 3*BC2 156232179Sedward #define BC4 8*BC2 156332179Sedward 156434009Sedward double Qx, Qy, h[MAXPOINTS], dx[MAXPOINTS], 156532179Sedward dy[MAXPOINTS], d2x[MAXPOINTS], d2y[MAXPOINTS], d3x[MAXPOINTS], 156632179Sedward d3y[MAXPOINTS]; 156732179Sedward 156832179Sedward /* 156932179Sedward * This routine converts each segment of a curve, P1, P2, P3, and P4 157032179Sedward * to a set of two intermediate control vertices, V2 and V3, in a Bezier 157132179Sedward * segment, plus a third vertex of the end point P4 (assuming the current 157232179Sedward * position is P1), and then writes a PostScript command "V2 V3 V4 curveto" 157332179Sedward * to the output file. 157432179Sedward * The two intermediate vertices are obtained using 157532179Sedward * Q(u) = V1 * (1-u)^3 + V2 * 3u(1-u)^2 + V3 * 3(1-u)u^2 + V4 * u^3 157632179Sedward * with u=1/4, and u=1/2, 157732179Sedward * Q(1/4) = Q2 = (x2, y2) 157832179Sedward * Q(1/2) = Q3 = (x3, y3) 157932179Sedward * V1 = P1 158032179Sedward * V4 = P4 158132179Sedward * and 158232179Sedward * V2 = (32/9)*Q2 - (4/3)*(Q3 + V1) + (1/9)*V4 158332179Sedward * V3 = -(32/9)*Q2 + 4*Q3 + V1 - (4/9)*V4 158432179Sedward */ 158532179Sedward BezierSegment(x1, y1, x2, y2, x3, y3, x4, y4) 158632179Sedward double x1, y1, x2, y2, x3, y3, x4, y4; 158732179Sedward { 158832179Sedward double V2x, V2y, V3x, V3y; 158932179Sedward 159032179Sedward V2x = BC4 * x2 - BC3 * (x3 + x1) + BC1 * x4; 159132179Sedward V2y = BC4 * y2 - BC3 * (y3 + y1) + BC1 * y4; 159232179Sedward V3x = -BC4 * x2 + 4 * x3 + x1 - BC2 * x4; 159332179Sedward V3y = -BC4 * y2 + 4 * y3 + y1 - BC2 * y4; 159432179Sedward 159532179Sedward printf(" %lg %lg %lg %lg %lg %lg curveto\n", 159632179Sedward V2x, V2y, V3x, V3y, x4, y4); 159734009Sedward PSx = x4 * PSmag; 159834009Sedward PSy = y4 * PSmag; 159932179Sedward } /* end BezierSegment */ 160032179Sedward 160132179Sedward /* 160232179Sedward * This routine calculates parameteric values for use in calculating 160332179Sedward * curves. The values are an approximation of cumulative arc lengths 160432179Sedward * of the curve (uses cord * length). For additional information, 160532179Sedward * see paper cited below. 160632179Sedward * 160732179Sedward * This is from Gremlin (called Paramaterize in gremlin), 160832179Sedward * with minor modifications (elimination of param list) 160932179Sedward */ 161032179Sedward IS_Parameterize() 161132179Sedward { 161232179Sedward register i, j; 161332179Sedward double t1, t2; 161432179Sedward double u[MAXPOINTS]; 161532179Sedward 161632179Sedward for (i = 1; i <= numpoints; i++) { 161732179Sedward u[i] = 0.0; 161832179Sedward for (j = 1; j < i; j++) { 161932179Sedward t1 = x[j + 1] - x[j]; 162032179Sedward t2 = y[j + 1] - y[j]; 162134009Sedward u[i] += sqrt(t1 * t1 + t2 * t2); 162232179Sedward } 162332179Sedward } 162432179Sedward for (i = 1; i < numpoints; i++) 162532179Sedward h[i] = u[i + 1] - u[i]; 162632179Sedward } /* end IS_Parameterize */ 162732179Sedward 162832179Sedward /* 162932179Sedward * This routine solves for the cubic polynomial to fit a spline 163032179Sedward * curve to the the points specified by the list of values. 163132179Sedward * The curve generated is periodic. The alogrithms for this 163232179Sedward * curve are from the "Spline Curve Techniques" paper cited below. 163332179Sedward * 163432179Sedward * This is from Gremlin (called PeriodicSpline in gremlin) 163532179Sedward * 163632179Sedward */ 163732179Sedward IS_PeriodicEnd(h, z, dz, d2z, d3z) 163832179Sedward double h[MAXPOINTS]; /* Parameterizeaterization */ 163932179Sedward double z[MAXPOINTS]; /* point list */ 164032179Sedward double dz[MAXPOINTS]; /* to return the 1st derivative */ 164132179Sedward double d2z[MAXPOINTS]; /* 2nd derivative */ 164232179Sedward double d3z[MAXPOINTS]; /* and 3rd derivative */ 164332179Sedward { 164432179Sedward double a[MAXPOINTS]; 164532179Sedward double b[MAXPOINTS]; 164632179Sedward double c[MAXPOINTS]; 164732179Sedward double d[MAXPOINTS]; 164832179Sedward double deltaz[MAXPOINTS]; 164932179Sedward double r[MAXPOINTS]; 165032179Sedward double s[MAXPOINTS]; 165132179Sedward double ftmp; 165232179Sedward register i; 165332179Sedward 165432179Sedward /* step 1 */ 165532179Sedward for (i = 1; i < numpoints; i++) 165632179Sedward if (h[i] != 0) 165732179Sedward deltaz[i] = (z[i + 1] - z[i]) / h[i]; 165832179Sedward else 165932179Sedward deltaz[i] = 0; 166032179Sedward h[0] = h[numpoints - 1]; 166132179Sedward deltaz[0] = deltaz[numpoints - 1]; 166232179Sedward 166332179Sedward /* step 2 */ 166432179Sedward for (i = 1; i < numpoints - 1; i++) 166532179Sedward d[i] = deltaz[i + 1] - deltaz[i]; 166632179Sedward d[0] = deltaz[1] - deltaz[0]; 166732179Sedward 166832179Sedward /* step 3a */ 166932179Sedward a[1] = 2 * (h[0] + h[1]); 167032179Sedward if (a[1] == 0) 167132179Sedward return (-1); /* 3 consecutive knots at same point */ 167232179Sedward b[1] = d[0]; 167332179Sedward c[1] = h[0]; 167432179Sedward 167532179Sedward for (i = 2; i < numpoints - 1; i++) { 167632179Sedward ftmp = h[i - 1]; 167732179Sedward a[i] = ftmp + ftmp + h[i] + h[i] - ftmp * ftmp / a[i - 1]; 167832179Sedward if (a[i] == 0) 167932179Sedward return (-1); /* 3 consec knots at same point */ 168032179Sedward b[i] = d[i - 1] - ftmp * b[i - 1] / a[i - 1]; 168132179Sedward c[i] = - ftmp * c[i - 1]/a[i - 1]; 168232179Sedward } 168332179Sedward 168432179Sedward /* step 3b */ 168532179Sedward r[numpoints - 1] = 1; 168632179Sedward s[numpoints - 1] = 0; 168732179Sedward for (i = numpoints - 2; i > 0; i--) { 168832179Sedward r[i] = - (h[i] * r[i + 1] + c[i]) / a[i]; 168932179Sedward s[i] = (6 * b[i] - h[i] * s[i + 1]) / a[i]; 169032179Sedward } 169132179Sedward 169232179Sedward /* step 4 */ 169332179Sedward d2z[numpoints - 1] = (6 * d[numpoints - 2] - h[0] * s[1] 169432179Sedward - h[numpoints - 1] * s[numpoints - 2]) 169532179Sedward / (h[0] * r[1] + h[numpoints - 1] * r[numpoints - 2] 169632179Sedward + 2 * (h[numpoints - 2] + h[0])); 169732179Sedward for (i = 1; i < numpoints - 1; i++) 169832179Sedward d2z[i] = r[i] * d2z[numpoints - 1] + s[i]; 169932179Sedward d2z[numpoints] = d2z[1]; 170032179Sedward 170132179Sedward /* step 5 */ 170232179Sedward for (i = 1; i < numpoints; i++) { 170332179Sedward dz[i] = deltaz[i] - h[i] * (2 * d2z[i] + d2z[i + 1]) / 6; 170432179Sedward if (h[i] != 0) 170532179Sedward d3z[i] = (d2z[i + 1] - d2z[i]) / h[i]; 170632179Sedward else 170732179Sedward d3z[i] = 0; 170832179Sedward } 170932179Sedward 171032179Sedward return (0); 171132179Sedward } /* end IS_PeriodicEnd */ 171232179Sedward 171332179Sedward /* 171432179Sedward * This routine solves for the cubic polynomial to fit a spline 171532179Sedward * curve from the points specified by the list of values. The alogrithms for 171632179Sedward * this curve are from the "Spline Curve Techniques" paper cited below. 171732179Sedward * 171832179Sedward * This is from Gremlin (called NaturalEndSpline in gremlin) 171932179Sedward */ 172032179Sedward IS_NaturalEnd(h, z, dz, d2z, d3z) 172132179Sedward double h[MAXPOINTS]; /* parameterization */ 172232179Sedward double z[MAXPOINTS]; /* point list */ 172332179Sedward double dz[MAXPOINTS]; /* to return the 1st derivative */ 172432179Sedward double d2z[MAXPOINTS]; /* 2nd derivative */ 172532179Sedward double d3z[MAXPOINTS]; /* and 3rd derivative */ 172632179Sedward { 172732179Sedward double a[MAXPOINTS]; 172832179Sedward double b[MAXPOINTS]; 172932179Sedward double d[MAXPOINTS]; 173032179Sedward double deltaz[MAXPOINTS]; 173132179Sedward double ftmp; 173232179Sedward register i; 173332179Sedward 173432179Sedward /* step 1 */ 173532179Sedward for (i = 1; i < numpoints; i++) 173632179Sedward if (h[i] != 0) 173732179Sedward deltaz[i] = (z[i + 1] - z[i]) / h[i]; 173832179Sedward else 173932179Sedward deltaz[i] = 0; 174032179Sedward deltaz[0] = deltaz[numpoints - 1]; 174132179Sedward 174232179Sedward /* step 2 */ 174332179Sedward for (i = 1; i < numpoints - 1; i++) 174432179Sedward d[i] = deltaz[i + 1] - deltaz[i]; 174532179Sedward d[0] = deltaz[1] - deltaz[0]; 174632179Sedward 174732179Sedward /* step 3 */ 174832179Sedward a[0] = 2 * (h[2] + h[1]); 174932179Sedward if (a[0] == 0) /* 3 consec knots at same point */ 175032179Sedward return (-1); 175132179Sedward b[0] = d[1]; 175232179Sedward 175332179Sedward for (i = 1; i < numpoints - 2; i++) { 175432179Sedward ftmp = h[i + 1]; 175532179Sedward a[i] = ftmp + ftmp + h[i + 2] + h[i + 2] - 175632179Sedward (ftmp * ftmp) / a[i - 1]; 175732179Sedward if (a[i] == 0) /* 3 consec knots at same point */ 175832179Sedward return (-1); 175932179Sedward b[i] = d[i + 1] - ftmp * b[i - 1] / a[i - 1]; 176032179Sedward } 176132179Sedward 176232179Sedward /* step 4 */ 176332179Sedward d2z[numpoints] = d2z[1] = 0; 176432179Sedward for (i = numpoints - 1; i > 1; i--) 176532179Sedward d2z[i] = (6 * b[i - 2] - h[i] * d2z[i + 1]) / a[i - 2]; 176632179Sedward 176732179Sedward /* step 5 */ 176832179Sedward for (i = 1; i < numpoints; i++) { 176932179Sedward dz[i] = deltaz[i] - h[i] * (2 * d2z[i] + d2z[i + 1]) / 6; 177032179Sedward if (h[i] != 0) 177132179Sedward d3z[i] = (d2z[i + 1] - d2z[i]) / h[i]; 177232179Sedward else 177332179Sedward d3z[i] = 0; 177432179Sedward } 177532179Sedward 177632179Sedward return (0); 177732179Sedward } /* end IS_NaturalEnd */ 177832179Sedward 177932179Sedward /* 178032179Sedward * Use the same algorithm Gremlin uses to interpolate a given 178132179Sedward * set of points, as described in ``Spline Curve Techniques,'' 178232179Sedward * by Pattrick Baudelaire, Robert M. Flegal, and Robert F. Sproull, 178332179Sedward * Xerox PARC Tech Report No. 78CSL-059. 178432179Sedward */ 178534009Sedward IS_Initialize() 178632179Sedward { 178732179Sedward IS_Parameterize(); 178832179Sedward 178932179Sedward /* Solve for derivatives of the curve at each point 179032179Sedward separately for x and y (parametric). */ 179132179Sedward 179232179Sedward if (x[1] == x[numpoints] && y[1] == y[numpoints]) { /* closed curve */ 179332179Sedward IS_PeriodicEnd(h, x, dx, d2x, d3x); 179432179Sedward IS_PeriodicEnd(h, y, dy, d2y, d3y); 179532179Sedward } else { 179632179Sedward IS_NaturalEnd(h, x, dx, d2x, d3x); 179732179Sedward IS_NaturalEnd(h, y, dy, d2y, d3y); 179832179Sedward } 179930594Ssam } 180032179Sedward 180132179Sedward /* 180232179Sedward * This routine converts cubic interpolatory spline to Bezier control vertices 180332179Sedward */ 180432179Sedward IS_Convert() 180532179Sedward { 180632179Sedward double t, t2, t3, x2, y2, x3, y3; 180732179Sedward register j, j1; 180832179Sedward 180932179Sedward for (j = 1; j < numpoints; j++) { 181032179Sedward t = .25 * h[j]; 181132179Sedward t2 = t * t; 181232179Sedward t3 = t2 * t; 181332179Sedward x2 = x[j] + t * dx[j] + t2 * d2x[j] / 2.0 + t3 * d3x[j] / 6.0; 181432179Sedward y2 = y[j] + t * dy[j] + t2 * d2y[j] / 2.0 + t3 * d3y[j] / 6.0; 181532179Sedward 181632179Sedward t = 2 * t; 181732179Sedward t2 = t * t; 181832179Sedward t3 = t2 * t; 181932179Sedward x3 = x[j] + t * dx[j] + t2 * d2x[j] / 2.0 + t3 * d3x[j] / 6.0; 182032179Sedward y3 = y[j] + t * dy[j] + t2 * d2y[j] / 2.0 + t3 * d3y[j] / 6.0; 182132179Sedward 182232179Sedward j1 = j + 1; 182332179Sedward BezierSegment(x[j], y[j], x2, y2, x3, y3, x[j1], y[j1]); 182432179Sedward } 182532179Sedward } /* end IS_Convert */ 182632179Sedward 182732179Sedward /* 182832179Sedward * This routine computes a point in B-spline segment, given i, and u. 182932179Sedward * Details of this algorithm can be found in the tech. report cited below. 183032179Sedward */ 183134009Sedward BS_ComputePoint(i, u, xp, yp) 183232179Sedward int i; 183332179Sedward float u; 183434009Sedward double *xp, *yp; 183532179Sedward { 183632179Sedward float u2, u3, b_2, b_1, b0, b1; 183732179Sedward register i1, i_2, i_1; 183832179Sedward 183932179Sedward i1 = i + 1; 184032179Sedward i_1 = i - 1; 184132179Sedward i_2 = i - 2; 184232179Sedward 184332179Sedward u2 = u * u; 184432179Sedward u3 = u2 * u; 184532179Sedward b_2 = (1 - 3 * u + 3 * u2 - u3) / 6.0; 184632179Sedward b_1 = (4 - 6 * u2 + 3 * u3) / 6.0; 184732179Sedward b0 = (1 + 3 * u + 3 * u2 - 3 * u3) / 6.0; 184832179Sedward b1 = u3 / 6.0; 184932179Sedward 185034009Sedward *xp = b_2 * x[i_2] + b_1 * x[i_1] + b0 * x[i] + b1 * x[i1]; 185134009Sedward *yp = b_2 * y[i_2] + b_1 * y[i_1] + b0 * y[i] + b1 * y[i1]; 185232179Sedward } /* end BS_ComputePoint */ 185332179Sedward 185432179Sedward /* 185532179Sedward * This routine initializes the array of control vertices 185632179Sedward * We consider two end conditions here: 185732179Sedward * (1) closed curve -- C2 continuation and end vertex not interpolated, i.e. 185832179Sedward * V[0] = V[n-1], and 185932179Sedward * V[n+1] = V[2]. 186032179Sedward * (2) open curve -- end vertex interpolation, i.e. 186132179Sedward * V[0] = 2*V[1] - V[2], and 186232179Sedward * V[n+1] = 2*V[n] - V[n-1]. 186332179Sedward * Details of uniform cubic B-splines, including other end conditions 186432179Sedward * and important properties can be found in Chapters 4-5 of 186532179Sedward * Richard H. Bartels and Brian A. Barsky, 186632179Sedward * "An Introduction to the Use of Splines in Computer Graphics", 186732179Sedward * Tech. Report CS-83-136, Computer Science Division, 186832179Sedward * University of California, Berkeley, 1984. 186932179Sedward */ 187034009Sedward BS_Initialize() 187132179Sedward { 187232179Sedward register n_1, n1; 187332179Sedward 187432179Sedward n_1 = numpoints - 1; 187532179Sedward n1 = numpoints + 1; 187632179Sedward if (x[1] == x[numpoints] && y[1] == y[numpoints]) { /* closed curve */ 187732179Sedward x[0] = x[n_1]; /* V[0] */ 187832179Sedward y[0] = y[n_1]; 187932179Sedward x[n1] = x[2]; /* V[n+1] */ 188032179Sedward y[n1] = y[2]; 188132179Sedward } else { /* end vertex interpolation */ 188234009Sedward x[0] = 2 * x[1] - x[2]; /* V[0] */ 188334009Sedward y[0] = 2 * y[1] - y[2]; 188434009Sedward x[n1] = 2 * x[numpoints] - x[n_1]; /* V[n+1] */ 188534009Sedward y[n1] = 2 * y[numpoints] - y[n_1]; 188632179Sedward } 188732179Sedward } /* end BS_Initialize */ 188832179Sedward 188932179Sedward /* 189032179Sedward * This routine converts uniform cubic B-spline to Bezier control vertices 189132179Sedward */ 189232179Sedward BS_Convert() 189332179Sedward { 189434009Sedward double x1, y1, x2, y2, x3, y3, x4, y4; 189532179Sedward register i; 189632179Sedward 189732179Sedward for (i = 2; i <= numpoints; i++) { 189834009Sedward BS_ComputePoint(i, 0.0, &x1, &y1); 189934009Sedward BS_ComputePoint(i, 0.25, &x2, &y2); 190034009Sedward BS_ComputePoint(i, 0.5, &x3, &y3); 190134009Sedward BS_ComputePoint(i, 1.0, &x4, &y4); 190234009Sedward if (i == 2) 190334009Sedward printf("%lg %lg moveto\n", x1, y1); 190434009Sedward BezierSegment(x1, y1, x2, y2, x3, y3, x4, y4); 190532179Sedward } 190632179Sedward } /* end BS_Convert */ 190732179Sedward 190832179Sedward /* 190932179Sedward * This routine copies the offset between two consecutive control points 191032179Sedward * into an array. That is, 191132179Sedward * O[i] = (x[i], y[i]) = V[i+1] - V[i], 191232179Sedward * for i=1 to N-1, where N is the number of points given. 191332179Sedward * The starting end point (V[1]) is saved in (Qx, Qy). 191432179Sedward */ 191534009Sedward BZ_Offsets() 191632179Sedward { 191732179Sedward register i; 191832179Sedward 191932179Sedward /* Assign offsets btwn points to array for convenience of processing */ 192034009Sedward Qx = x[1]; 192134009Sedward Qy = y[1]; 192234009Sedward for (i = 1; i < numpoints; i++) { 192334009Sedward x[i] = x[i + 1] - x[i]; 192434009Sedward y[i] = y[i + 1] - y[i]; 192532179Sedward } 192632179Sedward } 192732179Sedward 192832179Sedward /* 192932179Sedward * This routine contructs paths of piecewise continuous Bezier cubics 193032179Sedward * in PostScript based on the given set of control vertices. 193134009Sedward * Given 2 points, a straight line is drawn. 193232179Sedward * Given 3 points V[1], V[2], and V[3], a Bezier cubic segment 193332179Sedward * of (V[1], (V[1]+V[2])/2, (V[2]+V[3])/2, V[3]) is drawn. 193432179Sedward * In the case when N (N >= 4) points are given, N-2 Bezier segments will 193532179Sedward * be drawn, each of which (for i=1 to N-2) is translated to PostScript as 193632179Sedward * Q+O[i]/3 Q+(3*O[i]+O[i+1])/6 K+O[i+1]/2 curveto, 193732179Sedward * where 193832179Sedward * Q is the current point, 193932179Sedward * K is the continuation offset = Qinitial + Sigma(1, i)(O[i]) 194032179Sedward * Note that when i is 1, the initial point 194132179Sedward * Q = V[1]. 194232179Sedward * and when i is N-2, the terminating point 194332179Sedward * K+O[i+1]/2 = V[N]. 194432179Sedward */ 194532179Sedward BZ_Convert() 194632179Sedward { 194732179Sedward register i, i1; 194832179Sedward double x1, y1, x2, y2, x3, y3, Kx, Ky; 194932179Sedward 195032179Sedward if (numpoints == 2) { 195132179Sedward printf(" %lg %lg rlineto\n", x[1], y[1]); 195234009Sedward PSx += x[1] * PSmag; 195334009Sedward PSy += y[1] * PSmag; 195432179Sedward return; 195532179Sedward } 195632179Sedward if (numpoints == 3) { 195732179Sedward x1 = Qx + x[1]; 195832179Sedward y1 = Qy + y[1]; 195932179Sedward x2 = x1 + x[2]; 196032179Sedward y2 = y1 + y[2]; 196132179Sedward printf(" %lg %lg %lg %lg %lg %lg curveto\n", 196232179Sedward (Qx + x1) / 2.0, (Qy + y1) / 2.0, (x1 + x2) / 2.0, 196332179Sedward (y1 + y2) / 2.0, x2, y2); 196434009Sedward PSx = x2 * PSmag; 196534009Sedward PSy = y2 * PSmag; 196632179Sedward return; 196732179Sedward } 196832179Sedward /* numpoints >= 4 */ 196932179Sedward Kx = Qx + x[1]; 197032179Sedward Ky = Qy + y[1]; 197134009Sedward x[1] *= 2; 197234009Sedward y[1] *= 2; 197334009Sedward x[numpoints - 1] *= 2; 197434009Sedward y[numpoints - 1] *= 2; 197534009Sedward for (i = 1; i <= numpoints - 2; i++) { 197634009Sedward i1 = i + 1; 197734009Sedward x1 = Qx + x[i] / 3; 197834009Sedward y1 = Qy + y[i] / 3; 197934009Sedward x2 = Qx + (3 * x[i] + x[i1]) / 6; 198034009Sedward y2 = Qy + (3 * y[i] + y[i1]) / 6; 198134009Sedward x3 = Kx + x[i1] / 2; 198234009Sedward y3 = Ky + y[i1] / 2; 198332179Sedward printf(" %lg %lg %lg %lg %lg %lg curveto\n", 198432179Sedward x1, y1, x2, y2, x3, y3); 198532179Sedward Qx = x3; 198632179Sedward Qy = y3; 198734009Sedward Kx += x[i1]; 198834009Sedward Ky += y[i1]; 198932179Sedward } 199034009Sedward PSx = x3 * PSmag; 199134009Sedward PSy = y3 * PSmag; 199232179Sedward } /* end BZ_Convert */ 1993