Annotation of researchv10no/cmd/dimpress/impdraw.c, revision 1.1.1.1

1.1       root        1: 
                      2: /*
                      3:  *
                      4:  * Drawing routines used dimpress. Most, if not all the complicated code
                      5:  * has been eliminated for systems running version 1.9 or later systems.
                      6:  *
                      7:  * If your printer doesn't support the Impress graphics primitives used
                      8:  * in this file make sure you use an old version of draw.c.
                      9:  *
                     10:  * Apparently there's a bug in the Impress version 2.0 ellipse code. If
                     11:  * you're drawing part of an ellipse and radiusa < radiusb things get
                     12:  * messed up. That won't happen often - in fact only when the apsect
                     13:  * ratio is less than 1. All other cases seem to work properly. I expect
                     14:  * the problem to be fixed soon so I haven't bothered trying to get
                     15:  * around it.
                     16:  *
                     17:  */
                     18: 
                     19: 
                     20: #include <stdio.h>
                     21: #include <math.h>
                     22: 
                     23: #include "gen.h"                       /* general purpose definitions */
                     24: #include "impcodes.h"                  /* version 2.0 Impress codes */
                     25: 
                     26: 
                     27: #define XSCALE(A)      ((int) ((A) * xfac + .5 + xoffset))
                     28: #define YSCALE(A)      ((int) ((A) * yfac + .5 + yoffset))
                     29: 
                     30: 
                     31: int                    maxdots = 32000;
                     32: 
                     33: /*
                     34:  *
                     35:  * All these guys should be defined in file dimpress.c.
                     36:  *
                     37:  */
                     38: 
                     39: 
                     40: extern int             hpos;
                     41: extern int             vpos;
                     42: extern int             xoffset;
                     43: extern int             yoffset;
                     44: extern float           xfac;
                     45: extern float           yfac;
                     46: extern int             lastx;
                     47: extern int             lasty;
                     48: extern int             DX;
                     49: extern int             DY;
                     50: extern FILE            *tf;
                     51: 
                     52: 
                     53: /*****************************************************************************/
                     54: 
                     55: 
                     56: dist(x1, y1, x2, y2)
                     57: 
                     58: 
                     59:        int     x1, y1, x2, y2;
                     60: 
                     61: 
                     62: {
                     63: 
                     64: 
                     65:        float   dx, dy;
                     66: 
                     67: 
                     68: /*
                     69:  *
                     70:  * Returns the integer distance between points (x1, y1) and (x2, y2).
                     71:  *
                     72:  */
                     73: 
                     74: 
                     75:        dx = x2 - x1;
                     76:        dy = y2 - y1;
                     77: 
                     78:        return(sqrt(dx*dx + dy*dy) + 0.5);
                     79: 
                     80: }    /* End of dist */
                     81: 
                     82: 
                     83: /*****************************************************************************/
                     84: 
                     85: 
                     86: char *getstr(p, temp)
                     87: 
                     88: 
                     89:        char    *p;                     /* next string copied from here */
                     90:        char    *temp;                  /* and saved here */
                     91: 
                     92: 
                     93: {
                     94: 
                     95: 
                     96: /*
                     97:  *
                     98:  * Copies the next non-blank string from p to temp. p is updated and the final
                     99:  * final value of the pointer is returned to the caller. Probably could do all
                    100:  * this stuff just as easily using strtok().
                    101:  *
                    102:  */
                    103: 
                    104: 
                    105:        while (*p == ' ' || *p == '\t' || *p == '\n')
                    106:                p++;
                    107: 
                    108:        if (*p == '\0') {
                    109:                temp[0] = 0;
                    110:                return(NULL);
                    111:        }
                    112: 
                    113:        while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
                    114:                *temp++ = *p++;
                    115:        *temp = '\0';
                    116: 
                    117:        return(p);
                    118: 
                    119: }    /* End of getstr */
                    120: 
                    121: 
                    122: /*****************************************************************************/
                    123: 
                    124: 
                    125: xymove(x, y)
                    126: 
                    127: 
                    128:        int     x, y;                   /* move printer to this point */
                    129: 
                    130: 
                    131: {
                    132: 
                    133: 
                    134: /*
                    135:  *
                    136:  * Moves the printer's current position to the pixel corresponding to the
                    137:  * troff position (x, y).
                    138:  *
                    139:  */
                    140: 
                    141: 
                    142:        putc(ASETAH, tf);
                    143:        putint(lastx = XSCALE(x), tf);
                    144:        putc(ASETAV, tf);
                    145:        putint(lasty = YSCALE(y), tf);
                    146: 
                    147: }   /* End of xymove */
                    148: 
                    149: 
                    150: /*****************************************************************************/
                    151: 
                    152: 
                    153: drawline(dx, dy)
                    154: 
                    155: 
                    156:        int     dx, dy;                 /* endpoint is (hpos+dx, vpos+dy) */
                    157: 
                    158: 
                    159: {
                    160: 
                    161: 
                    162: /*
                    163:  *
                    164:  * Draws a line form the current position (hpos, vpos) to the point
                    165:  * (hpos+dx, vpos+dy), and leaves the current position at the endpoint.
                    166:  * We're assuming here that after the path is drawn Impress sets its current
                    167:  * position to the endpoint of the path. If that's not the case call xymove()
                    168:  * before returning.
                    169:  *
                    170:  */
                    171: 
                    172: 
                    173:        putc(ASETP, tf);                /* define the path */
                    174:        putint(2, tf);
                    175: 
                    176:        putint(XSCALE(hpos), tf);
                    177:        putint(YSCALE(vpos), tf);
                    178:        putint(XSCALE(hpos + dx), tf);
                    179:        putint(YSCALE(vpos + dy), tf);
                    180: 
                    181:        putc(ADRAWP, tf);               /* then draw it */
                    182:        putc(OR_OP, tf);
                    183: 
                    184:        hgoto(hpos + dx);               /* adjust troff's position */
                    185:        vgoto(vpos + dy);
                    186: 
                    187:        xymove(hpos, vpos);             /* think we need it */
                    188: 
                    189: }    /* End of drawline */
                    190: 
                    191: 
                    192: /*****************************************************************************/
                    193: 
                    194: 
                    195: drawcirc(d)
                    196: 
                    197: 
                    198:        int     d;                      /* diameter of the circle */
                    199: 
                    200: 
                    201: {
                    202: 
                    203: 
                    204: /*
                    205:  *
                    206:  * Draws a circle of diameter d with the left 'side' of the circle at the
                    207:  * current point. After we're finished drawing we move the current position
                    208:  * to the right side.
                    209:  *
                    210:  */
                    211: 
                    212:        drawellip(d, d);
                    213: 
                    214: }    /* End of drawcirc */
                    215: 
                    216: 
                    217: /*****************************************************************************/
                    218: 
                    219: 
                    220: drawellip(a, b)
                    221: 
                    222: 
                    223:        int     a, b;                   /* axes lengths for the ellipse */
                    224: 
                    225: 
                    226: {
                    227: 
                    228: 
                    229: /*
                    230:  *
                    231:  * Draws an ellipse having axes lengths horizontally and vertically of a and
                    232:  * b. The left side of the ellipse is at the current point. After we're done
                    233:  * drawing the path we move the current position to the right side.
                    234:  *
                    235:  */
                    236: 
                    237: 
                    238:        xymove(hpos + a/2, vpos);
                    239: 
                    240:        putc(AELLIPSEARC, tf);          /* define the ellipse */
                    241:        putint((int) ((a * xfac) / 2 + .5), tf);
                    242:        putint((int) ((b * yfac) / 2 + .5), tf);
                    243:        putint(0, tf);
                    244:        putint(0, tf);
                    245:        putint(16383, tf);
                    246: 
                    247:        putc(ADRAWP, tf);
                    248:        putc(OR_OP, tf);
                    249: 
                    250:        hgoto(hpos + a);                /* where troff wants to be */
                    251:        vgoto(vpos);
                    252: 
                    253:        xymove(hpos, vpos);             /* move the printer there too */
                    254: 
                    255: }    /* End of drawellip */
                    256: 
                    257: 
                    258: /*****************************************************************************/
                    259: 
                    260: 
                    261: drawarc(dx1, dy1, dx2, dy2)
                    262: 
                    263: 
                    264:        int     dx1, dy1;               /* vector from current pos to center */
                    265:        int     dx2, dy2;               /* from center to end of the arc */
                    266: 
                    267: 
                    268: {
                    269: 
                    270: 
                    271:        int     angle0;                 /* to get to first point */
                    272:        int     angle1;                 /* for second point - always negative */
                    273:        int     radius;
                    274: 
                    275: 
                    276: /*
                    277:  *
                    278:  * Draws a circular arc from the current position (hpos, vpos) to the point
                    279:  * (hpos + dx1 + dx2, vpos + dy1 + dy2). The center of the circle is the
                    280:  * point (hpos + dx1, vpos + dy1). Arcs always go in the counter-clockwise
                    281:  * direction from the starting point to the endpoint.
                    282:  *
                    283:  * After we're finished troff expects its current position to be the end
                    284:  * point of the arc. I've also made sure that Impress has its current
                    285:  * position set there too, although it's probably not necessary.
                    286:  *
                    287:  * Used elliptical arcs in case the aspect ratio is different than 1.0.
                    288:  * Things seem to work OK for aspect ratios greater than or equal to
                    289:  * 1.0, but there appears to be a bug in the Impress ellipse drawing
                    290:  * code that causes problems if radiusa < radiusb. I haven't bothered
                    291:  * to try and fix the code since I expect the Impress problem to
                    292:  * disappear, and besides apsect ratios different from 1.0 are rarely
                    293:  * used.
                    294:  *
                    295:  */
                    296: 
                    297: 
                    298:        if ( dx1 == 0  &&  dy1 == 0 )   /* nothing to do */
                    299:                return;
                    300: 
                    301:        xymove(hpos + dx1, vpos + dy1); /* center of the circle */
                    302: 
                    303:        radius = sqrt((float) dx1 * dx1 + (float) dy1 * dy1) + .5;
                    304:        angle0 = (atan2((double) -dy1, (double) -dx1) * (1 << 14)) / (2 * PI);
                    305:        angle1 = (atan2((double) dy2, (double) dx2) * (1 << 14)) / (2 * PI);
                    306: 
                    307:        if ( angle0 < angle1 )
                    308:                if ( angle0 < 0 ) angle0 += (1 << 14);
                    309:                else angle1 -= (1 << 14);
                    310: 
                    311:        putc(AELLIPSEARC, tf);          /* define the arc */
                    312:        putint((int) (radius * xfac + .5), tf);
                    313:        putint((int) (radius * yfac + .5), tf);
                    314:        putint(0, tf);
                    315:        putint(angle0, tf);
                    316:        putint(angle1, tf);
                    317: 
                    318:        putc(ADRAWP, tf);               /* draw the arc */
                    319:        putc(OR_OP, tf);
                    320: 
                    321:        hgoto(hpos + dx1 + dx2);        /* all done so get to the end point */
                    322:        vgoto(vpos + dy1 + dy2);
                    323: 
                    324:        xymove(hpos, vpos);             /* make sure the printer's there too */
                    325: 
                    326: }   /* End of drawarc */
                    327: 
                    328: 
                    329: /*****************************************************************************/
                    330: 
                    331: 
                    332: drawspline(fp, flag)
                    333:        FILE    *fp;                    /* input for point list */
                    334:        int     flag;                   /* flag!=1 connect end points */
                    335: {
                    336:        int x[50], y[50], xp, yp, pxp, pyp;
                    337:        float t1, t2, t3, w;
                    338:        int i, j, numdots, N;
                    339:        char temp[50], *p, *getstr();
                    340: /*
                    341:  *
                    342:  * I haven't made any real changes to this routine. Efficiency depends
                    343:  * on the size of DX and DY.
                    344:  *
                    345:  */
                    346:        for (N = 2;  N < sizeof(x)/sizeof(x[0]); N++)
                    347:                if (fscanf(fp, "%d %d", &x[N], &y[N]) != 2)
                    348:                        break;
                    349:        x[0] = x[1] = hpos;
                    350:        y[0] = y[1] = vpos;
                    351:        for (i = 1; i < N; i++) {
                    352:                x[i+1] += x[i];
                    353:                y[i+1] += y[i];
                    354:        }
                    355:        x[N] = x[N-1];
                    356:        y[N] = y[N-1];
                    357:        pxp = pyp = -9999;
                    358:        for (i = 0; i < N-1; i++) {     /* interval */
                    359:                numdots = (dist(x[i],y[i], x[i+1],y[i+1]) + dist(x[i+1],y[i+1], x[i+2],y[i+2])) / 2;
                    360:                numdots /= DX;
                    361:                numdots = MIN(numdots, maxdots);
                    362:                for (j = 0; j < numdots; j++) { /* points within */
                    363:                        w = (float) j / numdots;
                    364:                        t1 = 0.5 * w * w;
                    365:                        w = w - 0.5;
                    366:                        t2 = 0.75 - w * w;
                    367:                        w = w - 0.5;
                    368:                        t3 = 0.5 * w * w;
                    369:                        xp = t1 * x[i+2] + t2 * x[i+1] + t3 * x[i] + 0.5;
                    370:                        yp = t1 * y[i+2] + t2 * y[i+1] + t3 * y[i] + 0.5;
                    371:                        if (xp != pxp || yp != pyp) {
                    372:                                if (flag!=1 || (i!=0 && i!=N-2))   /* pg 3/21/87 */
                    373:                                        drawline(xp-hpos,yp-vpos); /* jsp 6/15/83 */
                    374:                                hgoto(xp);
                    375:                                vgoto(yp);
                    376:                                pxp = xp;
                    377:                                pyp = yp;
                    378:                        }
                    379:                }
                    380:        }
                    381: 
                    382: }   /* End of drawspline */
                    383: 
                    384: 
                    385: /*****************************************************************************/
                    386: 
                    387: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.