Annotation of researchv10no/cmd/dimpress/impdraw.c, revision 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.