Annotation of researchv10dc/cmd/picasso/xform.c, revision 1.1

1.1     ! root        1: /*     Copyright (c) 1988 AT&T */
        !             2: /*       All Rights Reserved   */
        !             3: 
        !             4: /*     THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T     */
        !             5: /*     The copyright notice above does not evidence any        */
        !             6: /*     actual or intended publication of such source code.     */
        !             7: 
        !             8: /*     @(#)picasso:xform.c     1.0     */
        !             9: 
        !            10: #include       "picasso.h"
        !            11: #include       "y.tab.h"
        !            12: #include    <math.h>
        !            13: 
        !            14: /* shorthand for a 3x3 affine matrix applied as follows:
        !            15:  *
        !            16:  *     C(x, y) = |x y 1| | C[0]  C[1]  0 | 
        !            17:  *                       | C[2]  C[3]  0 |
        !            18:  *                       | C[4]  C[5]  1 |
        !            19:  *
        !            20:  *             = (C[0]x+C[2]y+C[4], C[1]x+C[3]y+C[5])
        !            21:  */
        !            22: 
        !            23: matmult (A, B)                 /* A <- A * B; A is an object transformation */
        !            24:        valtype A[6];           /* or cur_xform updated by a new transform.  */
        !            25:        double  B[6];
        !            26: {
        !            27:        register double p;
        !            28: 
        !            29:        p = A[0].f * B[0] + A[1].f * B[2];
        !            30:        A[1].f = A[0].f * B[1] + A[1].f * B[3];
        !            31:        A[0].f = p;
        !            32: 
        !            33:        p = A[2].f * B[0] + A[3].f * B[2];
        !            34:        A[3].f = A[2].f * B[1] + A[3].f * B[3];
        !            35:        A[2].f = p;
        !            36: 
        !            37:        p = A[4].f * B[0] + A[5].f * B[2] + B[4];
        !            38:        A[5].f = A[4].f * B[1] + A[5].f * B[3] + B[5];
        !            39:        A[4].f = p;
        !            40: }
        !            41: 
        !            42: matmult2 (A, B)                        /* same, but updates a double array; this is  */
        !            43:        double  A[6];           /* done only in going up the block hierarchy. */
        !            44:        valtype B[6];
        !            45: {
        !            46:        register double p;
        !            47: 
        !            48:        p = A[0] * B[0].f + A[1] * B[2].f;
        !            49:        A[1] = A[0] * B[1].f + A[1] * B[3].f;
        !            50:        A[0] = p;
        !            51: 
        !            52:        p = A[2] * B[0].f + A[3] * B[2].f;
        !            53:        A[3] = A[2] * B[1].f + A[3] * B[3].f;
        !            54:        A[2] = p;
        !            55: 
        !            56:        p = A[4] * B[0].f + A[5] * B[2].f + B[4].f;
        !            57:        A[5] = A[4] * B[1].f + A[5] * B[3].f + B[5].f;
        !            58:        A[4] = p;
        !            59: }
        !            60: 
        !            61: mat_inverse(Ainv, A)
        !            62:        double Ainv[6];
        !            63:        float  A[6];
        !            64: {
        !            65:        double  det, det_1;
        !            66: 
        !            67:        det = A[0] * A[3] - A[1] * A[2];
        !            68:        if (det == 0.0) {
        !            69:                Ainv[0] = Ainv[3] = 1.0;
        !            70:                Ainv[1] = Ainv[2] = 0.0;
        !            71:                Ainv[4] = Ainv[5] = 0.0;
        !            72:                return;
        !            73:        }
        !            74:        det_1 = 1.0 / det;
        !            75:        Ainv[0] = A[3] * det_1;
        !            76:        Ainv[1] = - A[1] * det_1;
        !            77:        Ainv[2] = - A[2] * det_1;
        !            78:        Ainv[3] = A[0] * det_1;
        !            79:        Ainv[4] = (A[2] * A[5] - A[3] * A[4]) * det_1;
        !            80:        Ainv[5] = (A[1] * A[4] - A[0] * A[5]) * det_1;
        !            81: }
        !            82: 
        !            83: double T[6];
        !            84: 
        !            85: compose (p)                    /* accumulate xforms over block hierarchy */
        !            86:        obj     *p;
        !            87: {
        !            88:        if (p == NULL || p->o_type > TEXT) {
        !            89:                T[0] = T[3] = 1;
        !            90:                T[1] = T[2] =
        !            91:                T[4] = T[5] = 0;
        !            92:                if (p == NULL)
        !            93:                        return;
        !            94:        }
        !            95:        else {
        !            96:                T[0] = p->o_mxx;        T[1] = p->o_myx;
        !            97:                T[2] = p->o_mxy;        T[3] = p->o_myy;
        !            98:                T[4] = p->o_mxt;        T[5] = p->o_myt;
        !            99:        }
        !           100:        while ((p = p->o_parent) != NULL)
        !           101:                if (p->o_type <= TEXT)
        !           102:                        if (p->o_mxx != 1 || p->o_mxy != 0 || p->o_mxt != 0
        !           103:                        ||  p->o_myx != 0 || p->o_myy != 1 || p->o_myt != 0)
        !           104:                                matmult2(T, p->o_xform);
        !           105: }
        !           106: 
        !           107: get_matrix(M0, M1, M2, M3)
        !           108:        double  *M0, *M1, *M2, *M3;
        !           109: {
        !           110:        *M0 = T[0];     *M1 = T[1];     *M2 = T[2];     *M3 = T[3];
        !           111: }
        !           112: 
        !           113: double Xformx (p, flag, x, y)
        !           114:        obj     *p;
        !           115:        int     flag;
        !           116:        double  x, y;
        !           117: {
        !           118:        if (flag)
        !           119:                compose(p);
        !           120:        return x*T[0] + y*T[2] + T[4];
        !           121: }
        !           122: 
        !           123: double Xformy (p, flag, x, y)
        !           124:        obj     *p;
        !           125:        int     flag;
        !           126:        double  x, y;
        !           127: {
        !           128:        if (flag)
        !           129:                compose(p);
        !           130:        return x*T[1] + y*T[3] + T[5];
        !           131: }
        !           132: 
        !           133: double Linx (p, flag, x, y)            /* linear component, only */
        !           134:        obj     *p;
        !           135:        int     flag;
        !           136:        double  x, y;
        !           137: {
        !           138:        if (flag)
        !           139:                compose(p);
        !           140:        return T[0]*x + T[2]*y;
        !           141: }
        !           142: 
        !           143: double Liny (p, flag, x, y)
        !           144:        obj     *p;
        !           145:        int     flag;
        !           146:        double  x, y;
        !           147: {
        !           148:        if (flag)
        !           149:                compose(p);
        !           150:        return T[1]*x + T[3]*y;
        !           151: }
        !           152: 
        !           153: apply (p, M, d)                        /* apply matrix M (determinant d) to object p */
        !           154:        obj     *p;
        !           155:        double  *M, d;
        !           156: {
        !           157:        float   bnd[4];
        !           158: 
        !           159:        if (p->o_type == PLACE) {
        !           160:                matmult (cur_xform, M);
        !           161:                if (d != 1)
        !           162:                        checkscale(sqrt(d));
        !           163:        }
        !           164:        else if (p->o_type <= TEXT) {
        !           165:                matmult (p->o_xform, M);
        !           166:                get_bounds(p, bnd, 0);
        !           167:                track_bounds(bnd[0], bnd[1], bnd[2], bnd[3]);
        !           168:                redo_gbox = 1;
        !           169:        }
        !           170: }
        !           171: 
        !           172: translate (p, x, y)           /* the easy case of applying a transformation */
        !           173:        obj     *p;
        !           174:        double  x, y;
        !           175: {
        !           176:        float   bnd[4];
        !           177:        int     i;
        !           178: 
        !           179:        if (p->o_type == PLACE) {
        !           180:                cur_xform[4].f += x;
        !           181:                cur_xform[5].f += y;
        !           182:        }
        !           183:        else if (p->o_type <= TEXT) {
        !           184:                if (p->o_type == BLOCK  || p->o_mxx != 1 || p->o_myy != 1
        !           185:                                        || p->o_mxy != 0 || p->o_myx != 0
        !           186:                                        || p->o_mxt != 0 || p->o_myt != 0) {
        !           187:                        p->o_mxt += x;
        !           188:                        p->o_myt += y;
        !           189:                }
        !           190:                else {  /* no existing transformation, move center */
        !           191:                        /* DBK: probably should also test to make sure
        !           192:                           there is no higher level transformation?? */
        !           193:                        p->o_x += x;
        !           194:                        p->o_y += y;
        !           195:                        switch (p->o_type) {
        !           196: 
        !           197:                        case LINE:
        !           198:                        case ARROW:
        !           199:                        case SPLINE:
        !           200:                                for (i = 0; i <= p->o_val[N_VAL+3].f; i++) {
        !           201:                                        p->o_val[N_VAL+4+i+i].f += x;
        !           202:                                        p->o_val[N_VAL+5+i+i].f += y;
        !           203:                                }
        !           204:                                break;
        !           205:                        case ARC:
        !           206:                        case SECTOR:
        !           207:                                p->o_val[N_VAL+2].f += x;
        !           208:                                p->o_val[N_VAL+3].f += y;
        !           209:                                p->o_val[N_VAL+4].f += x;
        !           210:                                p->o_val[N_VAL+5].f += y;
        !           211:                                break;
        !           212:                        }
        !           213:                }
        !           214:                get_bounds(p, bnd, 0);
        !           215:                track_bounds(bnd[0], bnd[1], bnd[2], bnd[3]);
        !           216:                redo_gbox = 1;
        !           217:        }
        !           218: }
        !           219: 
        !           220: xlate (p, q)
        !           221:        obj     *p, *q;
        !           222: {
        !           223:        translate (p, q->o_x, q->o_y);
        !           224: }
        !           225: 
        !           226: xlate_to (p, q)                        /* destination given in absolute coordinates */
        !           227:        obj     *p, *q;
        !           228: {
        !           229:        translate (p, q->o_x - p->o_x, q->o_y - p->o_y);
        !           230: }
        !           231: 
        !           232: static double  picscale = 1.0;
        !           233: 
        !           234: rescale (v)            /* implicit scaling from user's "scale = v" statement */
        !           235:        double  v;      /* rather unintuitively, this is like "scale O 1/v".  */
        !           236: {
        !           237:        picscale = v;
        !           238: }
        !           239: 
        !           240: scale_pic()            /* for PIC compatibility--called at end of parse */
        !           241: {
        !           242:        double  sc;
        !           243:        obj     *o;
        !           244:        int     i;
        !           245:        float   bnd[4];
        !           246: 
        !           247:        if (picscale == 0.0)
        !           248:                picscale = 1.0;
        !           249:        if (picscale == 1.0)
        !           250:                return;
        !           251:        sc = 1.0 / picscale;
        !           252:        
        !           253:        for (o = objhead; o != objtail; o = o->o_next) {
        !           254:                if (o->o_type == PLACE || o->o_type == TEXT ||
        !           255:                                                o->o_type == MOVE) {
        !           256:                        o->o_x *= sc;
        !           257:                        o->o_y *= sc;
        !           258:        /* NOTE!! may need to adjust center offset of text */
        !           259:                }
        !           260:                else if (o->o_type < TEXT) {    /* PIC couldn't scale text */
        !           261:                        for (i = 0; i < 6; i++)
        !           262:                                o->o_xform[i].f *= sc;
        !           263:                }
        !           264:                if (o->o_type == BLOCK)         /* skip the contents */
        !           265:                        o = o->o_val[N_VAL].o;
        !           266:        }
        !           267:        /* make arrowheads large to compensate for later shrinkage */
        !           268:        for (o = objhead; o != objtail; o = o->o_next) {
        !           269:                if ((o->o_type == LINE || o->o_type == SPLINE ||
        !           270:                    o->o_type == ARROW) && (o->o_attr & HEAD12) != 0) {
        !           271:                        o->o_val[N_VAL+1].f *= picscale;
        !           272:                        o->o_val[N_VAL+2].f *= picscale;
        !           273:                }
        !           274:                if (o->o_type == ARC && (o->o_attr & HEAD12) != 0) {
        !           275:                        o->o_val[N_VAL+8].f *= picscale;
        !           276:                        o->o_val[N_VAL+9].f *= picscale;
        !           277:                }
        !           278:        }
        !           279:        picscale = 1.0;
        !           280: 
        !           281:        Gbox[2] = Gbox[3] = -(Gbox[0] = Gbox[1] = 32767);
        !           282:        for (o = objhead->o_next; o != objtail; o = o->o_next) {
        !           283:                get_bounds(o, bnd, 1);
        !           284:                track_bounds (bnd[0], bnd[1], bnd[2], bnd[3]);
        !           285:                if (o->o_type == BLOCK)
        !           286:                        o = o->o_val[N_VAL].o;
        !           287:        }
        !           288: #if 0
        !           289:        cur_xform[0].f /= v;
        !           290:        cur_xform[1].f /= v;
        !           291:        cur_xform[2].f /= v;
        !           292:        cur_xform[3].f /= v;
        !           293:        checkscale(v);
        !           294: #endif
        !           295: }
        !           296: 
        !           297: scale (p, n, q)
        !           298:        obj     *p, *q;
        !           299:        int     n;
        !           300: {
        !           301: register double        det;
        !           302:        double  M[6];
        !           303: 
        !           304:        M[0] = exprlist[nexpr-n];
        !           305:        M[3] = (n == 1 ? M[0] : exprlist[nexpr-n+1]);
        !           306:        nexpr = 0;
        !           307:        if ((det = M[0] * M[3]) == 0.0) {
        !           308:                yyerror("can't scale by 0 factor");
        !           309:                return;
        !           310:        }
        !           311:        M[1] = M[2] = M[4] = M[5] = 0.;
        !           312:        if (q != NULL) {
        !           313:                M[4] = (1 - M[0]) * Xformx(q,1,q->o_x,q->o_y);
        !           314:                M[5] = (1 - M[3]) * Xformy(q,0,q->o_x,q->o_y);
        !           315:        }
        !           316:        apply(p, M, det);
        !           317: }
        !           318: 
        !           319: olpscaleobj (p, sx, sy, cx, cy)
        !           320:        obj     *p;
        !           321:         double sx, sy;    /* scale factor in x and y directions */
        !           322:         double cx, cy;    /* center for scaling in real (inches) units */
        !           323: {
        !           324: register double        det;
        !           325:                 double M[6];
        !           326: 
        !           327:        M[0] = sx;
        !           328:        M[3] = sy;
        !           329:        if ((det = M[0] * M[3]) == 0.0) {
        !           330:                yyerror("can't scale by 0 factor");
        !           331:                return;
        !           332:        }
        !           333:        M[1] = M[2] = 0.0;
        !           334:         M[4] = cx * (1. - sx);
        !           335:         M[5] = cy * (1. - sy);
        !           336:         
        !           337:        apply(p, M, det);
        !           338: }
        !           339: 
        !           340: rotate (p, phi, q)
        !           341:        obj     *p, *q;
        !           342:        double  phi;    /* in radians */
        !           343: {
        !           344: register double        x, y;
        !           345:        double  M[6];
        !           346: 
        !           347:        M[3] =   M[0] = Cos(phi);
        !           348:        M[2] = -(M[1] = Sin(phi));
        !           349:        if (q == NULL)
        !           350:                M[4] = M[5] = 0;
        !           351:        else {
        !           352:                x = Xformx(q, 1, q->o_x, q->o_y);
        !           353:                y = Xformy(q, 0, q->o_x, q->o_y);
        !           354:                M[4] = (1 - M[0]) * x + M[1] * y;
        !           355:                M[5] = (1 - M[0]) * y - M[1] * x;
        !           356:        }
        !           357:        apply(p, M, 1);
        !           358: }
        !           359: 
        !           360: void 
        !           361: rotate_point(x, y,  angle, cx, cy, pointx, pointy)
        !           362:         double  x, y;
        !           363:        double  angle;  /* in radians */
        !           364:         double  cx, cy; /* center for rotation in screen units. */
        !           365:         double *pointx, *pointy;    /* rotated point to be passed back */
        !           366: {
        !           367:        double tempx, tempy;
        !           368: 
        !           369:         tempx = x - cx;
        !           370:         tempy = y - cy;
        !           371: 
        !           372:         *pointx = (tempx * cos(angle)) - (tempy* sin(angle)) + cx;
        !           373:         *pointy = (tempx * sin(angle)) + (tempy* cos(angle)) + cy;
        !           374: }
        !           375: 
        !           376: void
        !           377: olprotateobj (p, angle, cx, cy)
        !           378:        obj     *p;
        !           379:        double  angle;  /* in radians */
        !           380:         double  cx, cy; /* center for rotation in real (inches) units. */
        !           381: {
        !           382:        double  M[6];
        !           383: 
        !           384:        M[3] =   M[0] = cos(angle);
        !           385:        M[2] = -(M[1] = sin(angle));
        !           386: 
        !           387: 
        !           388:        M[4] = (1 - M[0]) * cx + M[1] * cy;
        !           389:        M[5] = (1 - M[0]) * cy - M[1] * cx;
        !           390: 
        !           391:        apply(p, M, 1);
        !           392: }
        !           393: 
        !           394: xform (p, n)
        !           395:        obj     *p;
        !           396:        int     n;
        !           397: {
        !           398: register double        det;
        !           399:        double  M[6];
        !           400:        int     i;
        !           401: 
        !           402:        for (i = 0; i < n; ++i)
        !           403:                M[i] = exprlist[i];
        !           404:        while (i < 6)
        !           405:                M[i++] = 0;
        !           406:        nexpr = 0;
        !           407:        if ((det = M[0]*M[3] - M[1]*M[2]) == 0)
        !           408:                yyerror ("singular transformation matrix");
        !           409:        else 
        !           410:                apply(p, M, det);
        !           411: }
        !           412: 
        !           413: reflect (p, q)
        !           414:        obj     *p, *q;
        !           415: {
        !           416:        float   bnd[4];
        !           417:        double  phi, c, s, x0, y0, x1, y1, M[6];
        !           418:        int     axial;
        !           419: 
        !           420:        if (q == NULL)
        !           421:                axial = x0 = x0 = x1 = y1 = 0;
        !           422:        else
        !           423:                switch (q->o_type) {
        !           424:                case ARC:
        !           425:                case ARROW:
        !           426:                case LINE:
        !           427:                case SPLINE:    whatpos(q, START, bnd, bnd+1);
        !           428:                                whatpos(q, END,   bnd+2, bnd+3);
        !           429:                                x0 = Xformx(q, 1, bnd[0], bnd[1]);
        !           430:                                y0 = Xformy(q, 0, bnd[0], bnd[1]);
        !           431:                                x1 = Xformx(q, 0, bnd[2], bnd[3]);
        !           432:                                y1 = Xformy(q, 0, bnd[2], bnd[3]);
        !           433:                                if (axial = (x0 != x1 || y0 != y1))
        !           434:                                        break;
        !           435:                                /* fall through to default case; i.e., use  */
        !           436:                                /* center, for closed lines. otherwise, use */
        !           437:                                /* closest point to p along q as start of q */
        !           438: #if 0      /*MS: The next few lines never get used */                                 
        !           439:                                S = (y1-y0)/(x1-x0);    /* slope of the line  */
        !           440:                                B = y0 - S*x0;          /* intercept term.    */
        !           441:                                s = -1/S;               /* perpendicular slope*/
        !           442:                                x = Xformx(p, 1, p->o_x, p->o_y);
        !           443:                                y = Xformy(p, 0, p->o_x, p->o_y);
        !           444:                                b = y - s*x;
        !           445:                                x0 = (b - B)/(S - s);   y0 = S*x0 + B;
        !           446: #endif                                
        !           447: 
        !           448:                default:
        !           449:                                x0 = Xformx(q, 1, q->o_x, q->o_y);
        !           450:                                y0 = Xformy(q, 0, q->o_x, q->o_y);
        !           451:                                axial = 0;
        !           452:                }
        !           453:        if (!axial) {
        !           454:                M[0] = M[3] = -1;
        !           455:                M[1] = M[2] = 0;
        !           456:                M[4] = 2 * x0;
        !           457:                M[5] = 2 * y0;
        !           458:        }
        !           459:        else {
        !           460:                if (x1 == x0 || y1 == y0) {     /* note: not both */
        !           461:                        s = 0;
        !           462:                        c = (x1 == x0 ? -1 : 1);
        !           463:                }
        !           464:                else if (fabs(x1-x0) == fabs(y1-y0)) {
        !           465:                        c = 0;
        !           466:                        s = (x1-x0 == y1-y0 ? 1 : -1);
        !           467:                }
        !           468:                else {
        !           469:                        c = cos(phi = 2 * atan2(y1-y0, x1-x0));
        !           470:                        s = sin(phi);
        !           471:                }
        !           472:                M[1] = M[2] = s;
        !           473:                M[3] = -(M[0] = c);
        !           474:                M[4] = x0*(1-c) - y0*s;
        !           475:                M[5] = y0*(1+c) - x0*s;
        !           476:        }
        !           477:        apply(p, M, 1);
        !           478: }
        !           479: 
        !           480: olpreflectobj (p, x0, y0, x1, y1)
        !           481:        obj     *p;
        !           482:         double  x0, y0, x1, y1;
        !           483: {
        !           484:        double  phi, c, s, M[6];
        !           485:        int     axial;
        !           486: 
        !           487:         if  (x0 != x1 || y0 != y1)
        !           488:            axial = 1;
        !           489:         else    axial = 0;
        !           490: 
        !           491:        if (!axial) {
        !           492:                M[0] = M[3] = -1;
        !           493:                M[1] = M[2] = 0;
        !           494:                M[4] = 2 * x0;
        !           495:                M[5] = 2 * y0;
        !           496:        }
        !           497:        else {
        !           498:                if (x1 == x0 || y1 == y0) {     /* note: not both */
        !           499:                        s = 0;
        !           500:                        c = (x1 == x0 ? -1 : 1);
        !           501:                }
        !           502:                else if (fabs(x1-x0) == fabs(y1-y0)) {
        !           503:                        c = 0;
        !           504:                        s = (x1-x0 == y1-y0 ? 1 : -1);
        !           505:                }
        !           506:                else {
        !           507:                        c = cos(phi = 2 * atan2(y1-y0, x1-x0));
        !           508:                        s = sin(phi);
        !           509:                }
        !           510:                M[1] = M[2] = s;
        !           511:                M[3] = -(M[0] = c);
        !           512:                M[4] = x0*(1-c) - y0*s;
        !           513:                M[5] = y0*(1+c) - x0*s;
        !           514:        }
        !           515:        apply(p, M, 1);
        !           516: }

unix.superglobalmegacorp.com

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