[net.sources] Super Plot ImPress filter

majka@ubc-vision.UUCP (Marc Majka) (05/02/86)

Here is a "Super Plot" filter for ImPress.  I hope it works.  It used to 
work here, but our Imagen is now too brain damaged to plot anything :-[.

It is set up to default nicely for a 240 bpi printer. See the README file
for details.

Cut, feed to sh, make, and give it a whirl!  I leave it as an exercise for
the reader to figure out how to get the output ImPress to the printer.  Here
at UBC, "% plimp foo | lpr -Pimagen -Limpress" fails, but 
"% plimp foo | ipr" works. 

---
Marc Majka


- - - CUT - - - CUT - - - CUT - - - CUT - - - CUT - - - CUT - - - CUT - - -
#!/bin/sh
#
# shell archive - extract with /bin/sh
#
echo extracting file README
sed 's/^X//' > README <<'!FUNKY!STUFF!'
XThis package contains a "Super Plot" filter for ImPress.  The code was
Xwritten for a 240bpi Imagen 10.  The default output plotting area is set up
Xfor this machine.  If you are using a 300bpi printer, you should change the
Xdefaults in the main procedure in plimp.c, and in the plotopen routine in
Xplimpfns.c  (plimp == PLot to IMPress)
X
XThis code is inefficient about drawing lines.  Every straight line segment
Xgenerates a PATH-DRAWPATH sequence in the output ImPress.  It would be more
Xefficient, in terms of the amount of output, to save up "paths" until you
Xare forced to print the path.  This savings are greatest for plots with lots
Xof text.  However, the hacks to do this are horribly ugly. Resist the
Xtemptation. 
X
XI hope this thing works.  Our Imagen printer is so brain-damaged as of late,
Xthat I can't even plot 10 lines on it.  This means that I have been unable
Xto test a few changes I made in the code for distribution.  I can't see how
XI could have broken anything, but be distrustful of the code if strange
Xthing happen.  Please feel free to send me bug reports: I can make
Xsuggestions, but I can't really debug the code here.
X
XIncluded here are 4 files: 
X
X* plimp.c     - source for top level
X* plimpfns.c  - source for filter routines
X* plimp.man   - meager documentation
X* Makefile    - to compile it 
X
XNOTE: make needs the files labels.o and driver.o from the "Super Plot"
Xdistribution.
X
X---
XMarc Majka
X
X
!FUNKY!STUFF!
echo extracting file Makefile
sed 's/^X//' > Makefile <<'!FUNKY!STUFF!'
X# Makefile for plimp
X
Xplimp: plimp.o plimpfns.o labels.o driver.o
X	cc -o plimp plimp.o plimpfns.o labels.o driver.o -lm
!FUNKY!STUFF!
echo extracting file plimp.man
sed 's/^X//' > plimp.man <<'!FUNKY!STUFF!'
XPLIMP(1)     UNIX Programmer's Manual      PLIMP(1)
X
XNAME
X     plimp - plot file to ImPress filter
X
XSYNOPSIS
X     plimp file [-i imp] [-m n] [-p n] [-w r1 c1 r2 c2]
X
XDESCRIPTION
X     plimp converts a plot file into ImPress language. It permits
X     the specification of an output window for the plot, pensize,
X     and the magnification (see below) of the plot. Default values
X     are supplied for all options which will result in the plot
X     using the full page, with a small (approx 1 cm) margin.
X
X     The following options are recognized:
X
X     -i imp
X          The named file is used for ImPress output. The default
X          is standard output.
X
X     -m n The plot will be magnified by a power of n. The mag-
X          nification must be 0, 1, or 2.  The default value is 0.
X          A magnification of 1 will double the size of the output
X          image, and 2 will quadruple the output size.
X
X     -p n Sets the starting pensize to n.  This is the equivalent
X          of an initial "pensize n" command in the plot file.
X
X     -w r1 c1 r2 c1
X          The output plot will be mapped into a window starting 
X          at row r1 and column c1, defining the upper left cor-
X          ner, ending at row r2 and column c2, defining the 
X          lower right corner.  The page coordinate system used
X          by plimp is row-column, with the origin at the upper
X          left corner of the page in portrait mode.  With a 240
X          bpi printer, the page will have 2460 rows and 1860 
X          columns.  At 300 bpi, the page is 3300 rows and 2550
X          columns.
X
XAUTHOR
X     Marc Majka
!FUNKY!STUFF!
echo extracting file plimp.c
sed 's/^X//' > plimp.c <<'!FUNKY!STUFF!'
X/*************************************************************/
X/*                                                           */
X/*  Copyright (c) 1985                                       */
X/*  Marc S. Majka - UBC Laboratory for Computational Vision  */
X/*                                                           */
X/*  Permission is hereby granted to copy all or any part of  */
X/*  this program for free distribution.   The author's name  */
X/*  and this copyright notice must be included in any copy.  */
X/*                                                           */
X/*************************************************************/
X
X#include <stdio.h>
X
Xmain (argc, argv)
Xint argc;
Xchar *argv[];
X{
X    FILE *pfp, *fopen();
X    int argn, nrows, ncols, mgn, pen, win, plt, imp, r1, r2, c1, c2;
X
X    r1 = 64; r2 = r1 + 2460;
X    c1 = 64; c2 = c1 + 1860;
X
X    mgn = 1;
X    pen = 1;
X    plt = 0;
X    win = 0;
X    imp = 0;
X
X    for (argn = 1; argn < argc; argn++) {
X        if (argv[argn][0] == '-') {
X            switch (argv[argn][1]) {
X                case 'p': pen = atoi(argv[++argn]); break;
X                case 'm': mgn = atoi(argv[++argn]); break;
X                case 'i': imp = ++argn; break;
X                case 'w':
X                    win = 1;
X                    r1 = atoi(argv[++argn]);
X                    c1 = atoi(argv[++argn]);
X                    r2 = atoi(argv[++argn]);
X                    c2 = atoi(argv[++argn]);
X                    break;
X                default:
X                    fprintf(stderr,
X                    "plimp [file] [-i imp] [-m n] [-p n] [-w r1 c1 r2 c2]\n");
X                    fprintf(stderr,"  file input plot file [stdin]\n");
X                    fprintf(stderr,"  -i   output Impress file [stdout]\n");
X                    fprintf(stderr,"  -m   magnification\n");
X                    fprintf(stderr,"  -p   pen size\n");
X                    fprintf(stderr,"  -w   output window\n");
X                    exit(0);
X            }
X        }
X        else {
X             if (plt) {
X                    fprintf(stderr,
X                        "plimp [file][-i imp][-m n][-p n][-w r1 c1 r2 c2]\n");
X                    exit(0);
X            }
X            plt = 1;
X            pfp = fopen(argv[argn],"r");
X            if (pfp == NULL) {
X                fprintf(stderr,"plimp: can't open plot file %s\n",argv[argn]);
X                exit(1);
X            }
X        }
X    }
X    if (!plt) pfp = stdin;
X
X    if (imp) plotopen(argv[imp]);
X    else plotopen("");
X
X    impsetup(r1,c1,mgn);
X    pensize(pen);
X    if (win) frame(0,0,nrows,ncols,1);
X
X    plotdriver(pfp);
X    plotclose();
X    exit(0);
X}
!FUNKY!STUFF!
echo extracting file plimpfns.c
sed 's/^X//' > plimpfns.c <<'!FUNKY!STUFF!'
X/*************************************************************/
X/*                                                           */
X/*  Copyright (c) 1985                                       */
X/*  Marc S. Majka - UBC Laboratory for Computational Vision  */
X/*                                                           */
X/*  Permission is hereby granted to copy all or any part of  */
X/*  this program for free distribution.   The author's name  */
X/*  and this copyright notice must be included in any copy.  */
X/*                                                           */
X/*************************************************************/
X
X#define ENDPAGE 219
X#define IMP_EOF 255
X#define NO_OP 254
X#define SET_HV_SYSTEM 205
X#define SET_ABS_H 135
X#define SET_ABS_V 137
X#define SET_REL_H 136
X#define SET_REL_V 138
X#define PAGE 213
X#define SET_ADV_DIRS 206
X#define MMOVE 133
X#define SMOVE 134
X#define SET_SP 210
X#define SP 128
X#define SP1 129
X#define MPLUS 131
X#define MMINUS 132
X#define CRLF 197
X#define SET_BOL 209
X#define SET_IL 208
X#define BGLY 199
X#define SGLY 198
X#define CREATE_MAP 222
X#define CREATE_FAMILY_TABLE 221
X#define SET_FAMILY 207
X#define BRULE 193
X#define CREATE_PATH 230
X#define CIRC_ARC 150
X#define CIRC_SEGM 160
X#define ELLIPSE_ARC 151
X#define SET_PUM 225
X#define SET_TEXTURE 231
X#define SET_PEN 232
X#define DRAW_PATH 234
X#define FILL_PATH 233
X#define BITMAP 235
X#define SET_MAGNIFICATION 236
X#define SET_PUSH_MASK 214
X#define PUSH 211
X#define POP 212
X#define DEFINE_MACRO 242
X#define EXECUTE_MACRO 243
X
X#define CORC 116
X#define GLYPHID 2176
X#define TFAMILY 17
X
X#include <stdio.h>
X
X#define MAXPATS 128
X#define FPMAX 32
X
Xstruct implstruct {
X    double x1, y1, x2, y2;      /* min and max points       */
X    double xr, yr;              /* x and y range            */
X    double xc, yc;              /* current point            */
X    int uhv;                    /* user space is hv         */
X    int ubpp;                   /* user bits per pixel      */
X    double ubppr;               /* user bpp range           */
X    int bx1, by1, bx2, by2;     /* polygon bounding box     */
X    int gray;                   /* current gray level       */
X    int optype;                 /* ImPress "gray" level     */
X    char linemask[100];         /* line generator mask      */
X    int lmp;                    /* mask pointer             */
X    FILE *ifp;                  /* impress file pointer     */
X    int r1, c1, r2, c2;         /* max and min row and col  */
X    int rr, cr;                 /* row and col range        */
X    int rc, cc;                 /* current row and col      */
X    int dhv;                    /* device hv                */
X    int dbpp;                   /* image bits per pixel     */
X    double dbppr;               /* image bpp range          */
X    int nrows, ncols;           /* output size              */
X    int fill, fstat;            /* fill mode flags          */
X} impl;
X
Xstruct fpstruct {
X    char grid[FPMAX][FPMAX];
X    int nr, nc;
X} fpat[MAXPATS];
X
X#define FILLMAX 2048
X
Xshort fstack[2][FILLMAX], knotn, knotk;
Xint ftop;
X
Ximpsetup(v,h,m)
Xint v,h,m;
X{
X    impwrite(SET_ABS_H,1);
X    impwrite(h,2);
X    impwrite(SET_ABS_V,1);
X    impwrite(v,2);
X    impwrite(SET_MAGNIFICATION,1);
X    impwrite(m,1);
X    impwrite(SET_HV_SYSTEM,1);
X    impwrite(CORC,1);
X}
X
Xplotopen(fname)
Xchar *fname;
X{
X    FILE *fopen();
X
X    if (fname == NULL || fname[0] == '\0') impl.ifp = stdout;
X    else impl.ifp = fopen(fname,"w");
X
X    if (impl.ifp == NULL) {
X        fprintf(stderr,"plotopen: can't open Impress file %s\n",fname);
X        exit(1);
X    }
X
X    impwrite(CREATE_FAMILY_TABLE,1);
X    impwrite(TFAMILY,1);
X    impwrite(1,1);
X    impwrite(0,1);
X    fwrite("Textures\0",9,1,impl.ifp);
X    impwrite(SET_FAMILY,1);
X    impwrite(TFAMILY,1);
X
X    /* defaults */
X    frame(0,0,2459,1859,0);
X    space(0,0,2459,1859,0);
X    bppout(1);
X    bppin(255);
X    move(0,0);
X    gray(1);
X    pensize(1);
X    linemod("1");
X    fillpat(0,1,1,"1");
X    font("sr");
X    fspec(1.0,1.0,0.0);
X
X    impl.fill = 0;
X    impl.fstat = 0;
X}
X
Xframe(x1,y1,x2,y2,hv)
Xint x1,y1,x2,y2,hv;
X{
X    impl.r1 = x1; impl.c1 = y1;
X    impl.r2 = x2; impl.c2 = y2;
X    impl.rr = x2 - x1; impl.cr = y2 - y1;
X    impl.nrows = 1 + abs((int)impl.rr);
X    impl.ncols = 1 + abs((int)impl.cr);
X    impl.bx2 = impl.r1; impl.by2 = impl.c1;
X}
X
Xbppout(b)
Xint b;
X{
X    /* DOES NOTHING */
X    impl.dbpp = 1;
X    impl.dbppr = 1.0;
X}
X
Xbppin(b)
Xint b;
X{
X    impl.ubpp = b;
X    impl.ubppr = (1 << b) - 1;
X}
X
Xplotclose()
X{   
X    impwrite(ENDPAGE,1);
X    impwrite(IMP_EOF,1);
X    fclose(impl.ifp);
X}
X
Xspace(x1,y1,x2,y2,hv)
Xint x1, y1, x2, y2, hv;
X{
X    impl.x1 = x1; impl.y1 = y1;
X    impl.x2 = x2; impl.y2 = y2;
X    impl.xr = x2 - x1; 
X    impl.yr = y2 - y1; 
X    impl.uhv = hv;
X    impl.bx1 = impl.x1; impl.by1 = impl.y1;
X    impl.bx2 = impl.x2; impl.by2 = impl.y2;
X    move(x1,y1);
X}
X
Xhvmatch()
X{
X    if (impl.uhv == impl.dhv) return(1);
X    return(0);
X}
X
Xerase()
X{
X    impwrite(ENDPAGE,1);
X}
X
Ximdscale(x,y)
Xdouble x,y;
X{
X    impl.xc = x; impl.yc = y;
X
X    if (impl.uhv != impl.dhv) {
X        impl.cc = (int)(impl.c1 +
X            (impl.xc - impl.x1) * ((double)impl.cr / impl.xr));
X        impl.rc = (int)(impl.r1 +
X            (impl.yc - impl.y1) * ((double)impl.rr / impl.yr));
X    }
X    else {
X        impl.rc = (int)(impl.r1 + 
X            (impl.xc - impl.x1) * ((double)impl.rr / impl.xr));
X        impl.cc = (int)(impl.c1 +
X            (impl.yc - impl.y1) * ((double)impl.cr / impl.yr));
X    }
X}
X
Xmove(x,y)
Xint x, y;
X{
X    impl.xc = x; impl.yc = y;
X    imdscale(impl.xc, impl.yc);
X
X    impl.lmp = 0;
X    if (x < impl.bx1) impl.bx1 = x; if (y < impl.by1) impl.by1 = y;
X    if (x > impl.bx2) impl.bx2 = x; if (y > impl.by2) impl.by2 = y;
X
X    if ((impl.fill) && (impl.fstat)) {
X        fstack[0][ftop] = (short)impl.rc;
X        fstack[1][ftop] = (short)impl.cc;
X        ftop++;
X        impl.fstat = 0;
X    }
X}
X
Xpoint(x,y)
Xint x, y;
X{
X    move(x,y);
X    setpoint(impl.rc,impl.cc);
X}
X
Xsetpoint(r,c)
Xint r,c;
X{
X    impwrite(CREATE_PATH,1);
X    impwrite(1,2);
X    impwrite(c,2);
X    impwrite(r,2);
X    impwrite(DRAW_PATH,1);
X    impwrite(impl.optype,1);
X}
X
Xcont(x,y)
Xint x, y;
X{
X    double r1, c1, r2, c2, rinc, cinc, length, tlen, r, c, fabs();
X    int i, state;
X
X    r1 = impl.rc; c1 = impl.cc; 
X    move(x,y);
X    r2 = impl.rc; c2 = impl.cc; 
X    imdraw(r1,c1,r2,c2);
X}
X
Ximdraw(r1,c1,r2,c2)
Xdouble r1, c1, r2, c2;
X{
X    double rinc, cinc, length, tlen, r, c, fabs();
X    int i, state;
X
X    /* if the this line is part of a polygon, stack it for later fill */    
X    if (impl.fill) {
X        fstack[0][ftop] = (short)r2;
X        fstack[1][ftop] = (short)c2;
X        ftop++;
X        if (ftop >= FILLMAX) {
X            fprintf(stderr,"plimp: fill stack overflow\n");
X            exit(1);
X        }
X    }
X
X    if (0 == strcmp(impl.linemask,"1")) {
X        impwrite(CREATE_PATH,1);
X        impwrite(2,2);
X        impwrite((int)c1,2);
X        impwrite((int)r1,2);
X        impwrite((int)c2,2);
X        impwrite((int)r2,2);
X        impwrite(DRAW_PATH,1);
X        impwrite(impl.optype,1);
X    }
X    else {
X        /* Based on the simple DDA from Newmann and Sproull */
X
X        state = 1;
X        length = fabs(r2-r1);
X        tlen = fabs(c2-c1);
X        if (tlen > length) length = tlen;
X            if (length != 0.0) {
X                rinc = (r2 - r1)/length;
X                cinc = (c2 - c1)/length;
X                r = r1;
X                c = c1;
X
X                for (i = 0; i < length; i++) {
X                    if (impl.linemask[impl.lmp] == '\0') impl.lmp = 0;
X                    if (impl.linemask[impl.lmp++] == '1') 
X                        if (!state) {
X                            state = 1;
X                            r1 = r; c1 = c;
X                        } else ;
X                    else
X                        if (state) {
X                            state = 0;
X                            impwrite(CREATE_PATH,1);
X                            impwrite(2,2);
X                            impwrite((int)c1,2);
X                            impwrite((int)r1,2);
X                            impwrite((int)c,2);
X                            impwrite((int)r,2);
X                            impwrite(DRAW_PATH,1);
X                            impwrite(impl.optype,1);
X                        }
X                        else ;
X
X                    r += rinc;
X                    c += cinc;
X                }
X
X                if ((r != r2) || (c != c2)) {
X                    if (impl.linemask[impl.lmp] == '\0') impl.lmp = 0;
X                        if (impl.linemask[impl.lmp++] == '1') {
X                            setpoint((int)r2,(int)c2);
X                        }
X                }
X            }
X    }
X}
X
Xline(x1,y1,x2,y2)
Xint x1, y1, x2, y2;
X{
X    move(x1,y1);
X    cont(x2,y2);
X}
X
Xchain(n,v)
Xshort n, *v;
X{
X    short vn, indx, x, y;
X
X    indx = 0;
X    impwrite(CREATE_PATH,1);
X    impwrite(n,2);
X    for (vn = 0; vn < n; vn++) {
X        x = v[indx++]; y = v[indx++];
X        move(x,y);
X        impwrite(impl.cc,2);
X        impwrite(impl.rc,2);
X    }
X    impwrite(DRAW_PATH,1);
X    impwrite(impl.optype,1);
X}
X
Xbspline(k,n,v)
Xshort k,n,*v;
X{
X    double u, du, ufin, x, y, or, oc;
X    short nn;
X
X    nn = n - 1;
X    ufin = (double)(nn - k + 2);
X    du = ufin / (500.0 + (double)nn);
X
X    u = 0.0;
X    Bpoint(&x,&y,0.0,nn,k,v);
X    imdscale(x,y);
X    or = impl.rc; oc = impl.cc;
X
X    while (u <= ufin) {
X        u = u + du;
X        Bpoint(&x,&y,u,n,k,v);
X        imdscale(x,y);
X        imdraw(or,oc,(double)impl.rc,(double)impl.cc);
X        or = impl.rc; oc = impl.cc;
X    }
X    x = v[nn*2];
X    y = v[nn*2 + 1];
X    cont((short)x,(short)y);
X}
X
XBpoint(x,y,u,n,k,v)
Xdouble *x, *y;
Xdouble u;
Xint n,k;
Xshort *v;
X{
X    int i, m;
X    double b, Bnblend();
X
X    *x = 0.0; *y = 0.0;
X    m = 0;
X    knotk = k;
X    knotn = n;
X
X    for (i = 0; i <= n; i++) {
X        b = Bnblend(i,k,u);
X        *x = *x + (double)(v[m]) * b;
X        *y = *y + (double)(v[m+1]) * b;
X        m += 2;
X    }
X}
X
XBknot(i)
Xint i;
X{
X    if (i < knotk) return(0);
X    else if (i > knotn) return(knotn - knotk + 2);
X    else return(i - knotk + 1);
X}
X
Xdouble Bnblend(i,k,u)
Xint i,k;
Xdouble u;
X{
X    double v, v1, v2, t1, t2;
X
X    v1 = 0.0; v2 = 0.0; t1 = 0.0; t2 = 0.0;
X
X    if (k == 1) {
X        if ((Bknot(i) <= u) && (u < Bknot(i+1))) v = 1.0;
X        else v = 0.0;
X    }
X    else {
X        t1 = Bknot(i+k-1) - Bknot(i);
X        if (t1 != 0) v1 = (u - Bknot(i)) * Bnblend(i,k-1,u) / t1;
X
X        t2 = Bknot(i+k) - Bknot(i+1);
X        if (t2 != 0) v2 = (Bknot(i+k) - u) * Bnblend(i+1,k-1,u) / t2;
X
X        v = v1 + v2;
X    }
X    return(v);
X}
X
Xpolygon(n,v)
Xshort n, *v;
X{
X    short vn, indx, x, y;
X
X    indx = 0;
X    impwrite(CREATE_PATH,1);
X    impwrite(n,2);
X    for (vn = 0; vn < n; vn++) {
X        x = v[indx++]; y = v[indx++];
X        move(x,y);
X        impwrite(impl.cc,2);
X        impwrite(impl.rc,2);
X    }
X    impwrite(FILL_PATH,1);
X    impwrite(7,1);
X}
X
Xmoverel(x,y)
Xint x, y;
X{
X    dblmoverel((double)x,(double)y);
X}
X
Xdblmoverel(x,y)
Xdouble x, y;
X{
X    impl.xc += x; impl.yc += y;
X    imdscale(impl.xc,impl.yc);
X
X    impl.lmp = 0;
X    if (x < impl.bx1) impl.bx1 = x; if (y < impl.by1) impl.by1 = y;
X    if (x > impl.bx2) impl.bx2 = x; if (y > impl.by2) impl.by2 = y;
X
X    if ((impl.fill) && (impl.fstat)) {
X        fstack[0][ftop] = (short)impl.rc;
X        fstack[1][ftop] = (short)impl.cc;
X        ftop++;
X        impl.fstat = 0;
X    }
X}
X
Xcontrel(x,y)
Xint x, y;
X{
X    impl.xc += (double)x; impl.yc += (double)y;
X    cont((int)impl.xc,(int)impl.yc);
X}
X
Xdblcontrel(x,y)
Xdouble x, y;
X{
X    double r1, c1, r2, c2;
X
X    r1 = impl.rc; c1 = impl.cc;
X
X    impl.xc += x; impl.yc += y;
X    imdscale(impl.xc,impl.yc);
X    r2 = impl.rc; c2 = impl.cc;
X    imdraw(r1,c1,r2,c2);
X}
X
Xgray(g)
Xint g;
X{
X    if (g == 0) {
X        impl.gray = 0;
X        impl.optype = 0;
X    }
X    else {
X        impl.gray = 1;
X        impl.optype = 15;
X    }
X}
X
Xcolour(r,g,b)
Xint r,g,b;
X{
X    if ((r+g+b) == 0) impl.gray = 0;
X    else impl.gray = 1;
X}
X
Xpensize(p)
Xint p;
X{
X    impwrite(SET_PEN,1);
X    impwrite(p,1);
X}
X
Xlinemod(str)
Xchar *str;
X{
X    strcpy(impl.linemask,str);
X    impl.lmp = 0;
X}
X
Xstartp()
X{
X    impl.fill = 1;
X    impl.fstat = 1;
X    ftop = 0;
X}
X
Xendp()
X{
X    impl.fill = 0;
X    impl.fstat = 0;
X    impwrite(CREATE_PATH,1);
X    impwrite(ftop,2);
X    while (ftop > 0) {
X        ftop--;
X        impwrite(fstack[1][ftop],2);
X        impwrite(fstack[0][ftop],2);
X    }
X    impwrite(FILL_PATH,1);
X    impwrite(7,1);
X    ftop = 0;
X}
X
Xarc(xc,yc,x1,y1,x2,y2)
Xint xc,yc,x1,y1,x2,y2;
X{
X    double fabs(), hypot(),acos(), cos(), sin();
X    double dt, a1, a2, theta, rad, pi, pi2, up, dn, bup, bdn;
X    double cx, cy;
X    int catch, lastr, lastc;
X
X    pi = acos(-1.0);
X    pi2 = 2.0 * pi;
X
X    /* Algorithm: move to x1 y1. The angle between x1 y1 and the x axis is a1.
X        The angle to x2 y2 is a2. Set theta = a1, and move to x1 y1.
X        Sweep anti-clockwise to a2, incrementing theta by dt. At each step,
X        find the point on the arc at angle theta. Use cont to draw a line
X        to that point.
X    */
X
X    rad = hypot((double)(x1-xc),(double)(y1-yc));
X
X    /* find the angles a1 and a2 */
X
X    if (y1 >= yc) a1 = acos((x1-xc)/rad);
X    else a1 = pi + acos((xc-x1)/rad);
X
X    if (y2 >= yc) a2 = acos((x2-xc)/rad);
X    else a2 = pi + acos((xc-x2)/rad);
X
X    move(x1,y1);
X    lastr = impl.rc; lastc = impl.cc;
X    dt = 2.0 / rad;
X    theta = a1;
X    up = a2+dt;
X    dn = a2-dt;
X    bup = up + pi2;
X    bdn = dn + pi2;
X    catch = 0; /* safety chain */
X
X    /* step around the arc until within range of a2 */
X    while (!((catch > 1) && (((theta < up) && (theta > dn)) ||
X        ((theta < bup) && (theta > bdn))))) {
X
X        impl.xc = xc + rad * cos(theta);
X        impl.yc = yc + rad * sin(theta);
X
X        if (impl.uhv != impl.dhv) {
X            impl.cc = impl.c1 + (impl.xc - impl.x1) * (impl.cr / impl.xr);
X            impl.rc = impl.r1 + (impl.yc - impl.y1) * (impl.rr / impl.yr);
X        }
X        else {
X            impl.rc = impl.r1 + (impl.xc - impl.x1) * (impl.rr / impl.xr);
X            impl.cc = impl.c1 + (impl.yc - impl.y1) * (impl.cr / impl.yr);
X        }
X
X        if (impl.xc < impl.bx1) impl.bx1 = impl.xc;
X        if (impl.yc < impl.by1) impl.by1 = impl.yc;
X        if (impl.xc > impl.bx2) impl.bx2 = impl.xc;
X        if (impl.yc > impl.by2) impl.by2 = impl.yc;
X
X        if (impl.linemask[impl.lmp] == '\0') impl.lmp = 0;
X        if (impl.linemask[impl.lmp++] == '1') {
X            impwrite(CREATE_PATH,1);
X            impwrite(2,2);
X            impwrite(lastc,2);
X            impwrite(lastr,2);
X            impwrite(impl.cc,2);
X            impwrite(impl.rc,2);
X            impwrite(DRAW_PATH,1);
X            impwrite(impl.optype,1);
X        }
X
X        lastr = impl.rc; lastc = impl.cc;
X        theta+=dt;
X
X        /* safety check to catch runaway loops */
X        if (catch++ > 1000000) {
X            fprintf(stderr,"arc: runaway loop caught: inform a wizard!\n");
X            fprintf(stderr,"  xc=%lf yc=%lf x1=%lf y1=%lf x1=%lf y1=%lf\n",
X                xc,yc,x1,y1,x2,y2);
X            fprintf(stderr,"  angle1=%lf angle2=%lf dtheta=%lf\n",a1,a2,dt);
X            exit(1);
X        }
X    }
X
X    /* finish up */
X    cont(x2,y2);
X    point(x2,y2);
X}
X
Xcircle(x1,y1,r)
Xint x1,y1,r;
X{
X    arc(x1,y1,x1-r,y1,x1-r,y1);
X}
X
Xfillpat(n,r,c,str)
Xint n, r, c;
Xchar *str;
X{
X    int gr, gc, pr, pc, wl, word, p, pat[32][32], glyph;
X
X    glyph = GLYPHID + n;
X
X    fpat[n].nr = r;
X    fpat[n].nc = c;
X    p = 0;
X
X    for (pr = 0; pr < r; pr++)
X        for (pc = 0; pc < c; pc++) {
X            if (str[p++] == '1') pat[pr][pc] = 1;
X            else pat[pr][pc] = 0;
X            if (str[p] == '\0') p = 0;
X        }
X
X    impwrite(SGLY,1);
X    impwrite(glyph,2);
X    impwrite(32,1);
X    impwrite(32,1);
X    impwrite(0,1);
X    impwrite(32,1);
X    impwrite(0,1);
X
X    pr = 0; wl = 7; word = 0;
X
X    for (gr = 0; gr < 32; gr++) {
X        pc = 0;
X        for (gc = 0; gc < 32; gc++) {
X
X            fpat[n].grid[gr][gc] = pat[pr][pc++];
X            word |= fpat[n].grid[gr][gc] << wl;
X
X            if (wl == 0) {
X                wl = 7;
X                impwrite(word,1);
X                word = 0;
X            }
X            else wl--;
X            if (pc == c) pc = 0;
X        }
X        pr++;
X        if (pr == r) pr = 0;
X    }
X    setpat(n);
X}
X
Xsetpat(p)
Xint p;
X{   
X    int glyph;
X
X    glyph = GLYPHID + p;
X
X    impwrite(SET_TEXTURE,1);
X    impwrite(glyph,2);
X}
X
Xarea(x,y)
Xint x, y;
X{
X/* AREA NOT IMPLEMENTED */
X}
X
Ximpwrite(v,b)
Xint v, b;
X{
X    int t;
X
X    if (b == 1) fwrite(&v,1,1,impl.ifp);
X    else {
X        t = v >> 8;
X        fwrite(&t,1,1,impl.ifp);
X        fwrite(&v,1,1,impl.ifp);
X    }
X
X}
X
Xcomment(str)
Xchar *str;
X{
X}
X
Xdonelabel()
X{
X}
!FUNKY!STUFF!
echo Done\!
exit 0