1*37310Sedward /* @(#)psdit.c 1.6 04/03/89 */
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 */
13234804Sedward 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
main(argc,argv)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 */
outlist(s)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
conv(fp)35932179Sedward conv(fp) /* convert a file */
36032179Sedward register FILE *fp;
36130594Ssam {
36232179Sedward register int c, k;
36332179Sedward int m, n, n1, m1;
364*37310Sedward char str[100], buf[1024];
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':
44034804Sedward fscanf(fp, "%d", &stipplefont);
44134804Sedward 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 */
preface()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
devcntrl(fp)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
includefile(filenm)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
fileinit()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
loadpswidths(i,name)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
fontprint(i)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
loadfont(n,s,s1)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
sayload(n,s,s1)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
done()87632179Sedward done()
87730594Ssam {
87832179Sedward t_reset('s');
87932179Sedward exit(0);
88030594Ssam }
88130594Ssam
t_init()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 */
89034804Sedward stipplefont = 1;
89132179Sedward printf("xi\n");
89232179Sedward printf("%%%%EndProlog\n");
89330594Ssam }
89430594Ssam
t_push()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
t_pop()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
t_page(n)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;
96034804Sedward printf("%d s %d xH %d xS %d f %d i\n",
96134804Sedward 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
t_size(n)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
t_charht(n)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
t_slant(n)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
t_font(s)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
t_text(s)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
t_reset(c)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
t_res(res,minh,minv)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
t_trailer()104132179Sedward t_trailer()
104230594Ssam {
104332179Sedward FlushShow(0);
104432179Sedward printf("\n%d p", pageno);
104532179Sedward printf("\n%%%%Trailer\n");
104632179Sedward printf("xt\n");
104730594Ssam }
104830594Ssam
put1s(s)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
put1(c,s)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
putnf(c,s)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')
1173*37310Sedward 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
t_fp(n,s,si)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
setfont(n)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
drawline(dx,dy)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
drawcurve(line)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
drawpoly(line)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
getpoints(s)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
drawcirc(d)131932179Sedward drawcirc(d)
132032179Sedward int d;
132130594Ssam {
132232179Sedward FlushShow(0);
132332179Sedward MoveTo();
132432179Sedward DoMove();
132532179Sedward printf("%d Dc\n", d);
132630594Ssam }
132730594Ssam
drawarc(dx1,dy1,dx2,dy2)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
drawellip(a,b)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
hmot(a)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
hgoto(a)136432179Sedward hgoto(a) /* absolute horizontal motion */
136532179Sedward int a;
136630594Ssam {
136732179Sedward FlushShow(1);
136832179Sedward startx = hpos = a;
136932179Sedward thisw = 0;
137030594Ssam }
137130594Ssam
vmot(a)137232179Sedward vmot(a) /* relative vertical motion */
137332179Sedward int a;
137430594Ssam {
137532179Sedward FlushShow(1);
137632179Sedward vpos += a;
137732179Sedward thisw = 0;
137830594Ssam }
137930594Ssam
vgoto(a)138032179Sedward vgoto(a) /* absolute vertical motion */
138132179Sedward int a;
138230594Ssam {
138332179Sedward FlushShow(1);
138432179Sedward vpos = a;
138532179Sedward thisw = 0;
138630594Ssam }
138730594Ssam
showspecial(s,cc,wid)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
showchar(c)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
MoveTo()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
FlushMove()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
DoMove()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
FlushShow(t)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
156234009Sedward 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 */
BezierSegment(x1,y1,x2,y2,x3,y3,x4,y4)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);
159534009Sedward PSx = x4 * PSmag;
159634009Sedward 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 */
IS_Parameterize()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];
161934009Sedward 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 */
IS_PeriodicEnd(h,z,dz,d2z,d3z)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 */
IS_NaturalEnd(h,z,dz,d2z,d3z)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 */
IS_Initialize()178334009Sedward 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 */
IS_Convert()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 */
BS_ComputePoint(i,u,xp,yp)182934009Sedward BS_ComputePoint(i, u, xp, yp)
183032179Sedward int i;
183132179Sedward float u;
183234009Sedward 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
184834009Sedward *xp = b_2 * x[i_2] + b_1 * x[i_1] + b0 * x[i] + b1 * x[i1];
184934009Sedward *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 */
BS_Initialize()186834009Sedward 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 */
188034009Sedward x[0] = 2 * x[1] - x[2]; /* V[0] */
188134009Sedward y[0] = 2 * y[1] - y[2];
188234009Sedward x[n1] = 2 * x[numpoints] - x[n_1]; /* V[n+1] */
188334009Sedward 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 */
BS_Convert()189032179Sedward BS_Convert()
189132179Sedward {
189234009Sedward double x1, y1, x2, y2, x3, y3, x4, y4;
189332179Sedward register i;
189432179Sedward
189532179Sedward for (i = 2; i <= numpoints; i++) {
189634009Sedward BS_ComputePoint(i, 0.0, &x1, &y1);
189734009Sedward BS_ComputePoint(i, 0.25, &x2, &y2);
189834009Sedward BS_ComputePoint(i, 0.5, &x3, &y3);
189934009Sedward BS_ComputePoint(i, 1.0, &x4, &y4);
190034009Sedward if (i == 2)
190134009Sedward printf("%lg %lg moveto\n", x1, y1);
190234009Sedward 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 */
BZ_Offsets()191334009Sedward BZ_Offsets()
191432179Sedward {
191532179Sedward register i;
191632179Sedward
191732179Sedward /* Assign offsets btwn points to array for convenience of processing */
191834009Sedward Qx = x[1];
191934009Sedward Qy = y[1];
192034009Sedward for (i = 1; i < numpoints; i++) {
192134009Sedward x[i] = x[i + 1] - x[i];
192234009Sedward 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.
192934009Sedward * 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 */
BZ_Convert()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]);
195034009Sedward PSx += x[1] * PSmag;
195134009Sedward 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);
196234009Sedward PSx = x2 * PSmag;
196334009Sedward PSy = y2 * PSmag;
196432179Sedward return;
196532179Sedward }
196632179Sedward /* numpoints >= 4 */
196732179Sedward Kx = Qx + x[1];
196832179Sedward Ky = Qy + y[1];
196934009Sedward x[1] *= 2;
197034009Sedward y[1] *= 2;
197134009Sedward x[numpoints - 1] *= 2;
197234009Sedward y[numpoints - 1] *= 2;
197334009Sedward for (i = 1; i <= numpoints - 2; i++) {
197434009Sedward i1 = i + 1;
197534009Sedward x1 = Qx + x[i] / 3;
197634009Sedward y1 = Qy + y[i] / 3;
197734009Sedward x2 = Qx + (3 * x[i] + x[i1]) / 6;
197834009Sedward y2 = Qy + (3 * y[i] + y[i1]) / 6;
197934009Sedward x3 = Kx + x[i1] / 2;
198034009Sedward 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;
198534009Sedward Kx += x[i1];
198634009Sedward Ky += y[i1];
198732179Sedward }
198834009Sedward PSx = x3 * PSmag;
198934009Sedward PSy = y3 * PSmag;
199032179Sedward } /* end BZ_Convert */
1991