|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.