|
|
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.