|
|
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:misc.c 1.0 */
9: #include "picasso.h"
10: #include "y.tab.h"
11:
12: extern int pic_compat;
13: extern int batch;
14:
15: double getcomp(p, t) /* return component of a position; these must now be */
16: obj *p; /* transformed as there is no later chance to do so. */
17: int t;
18: {
19: float bnd[4];
20:
21: switch (t) {
22: case DOTX: return Xformx(p, 1, p->o_x, p->o_y);
23: case DOTY: return Xformy(p, 1, p->o_x, p->o_y);
24: case DOTRAD:
25: switch (p->o_type) {
26: case SECTOR:
27: case ARC:
28: case BOX:
29: case ARROW:
30: case LINE: return p->o_val[N_VAL].f;
31: case CIRCLE:
32: case ELLIPSE: break; /* fall through to DOTWID case */
33: }
34: case DOTHT:
35: case DOTWID: if (p->o_type <= TEXT) {
36: get_bounds(p, bnd, 1);
37: if (t == DOTHT)
38: return (bnd[3] - bnd[1]);
39: else
40: return (bnd[2] - bnd[0]);
41: }
42: }
43: yyerror("can't happen getcomp");
44: }
45:
46: exprsave(f)
47: double f;
48: {
49: if (nexpr >= nexprlist)
50: exprlist = (float *) grow((char *)exprlist, "exprlist",
51: nexprlist += 256, sizeof(float));
52: exprlist[nexpr] = f;
53: return ++nexpr;
54: }
55:
56: char *sprintgen(fmt)
57: char *fmt;
58: {
59: char buf[1000];
60:
61: sprintf (buf, fmt, exprlist[0], exprlist[1], exprlist[2],
62: exprlist[3], exprlist[4]);
63: nexpr = 0;
64: free(fmt);
65: return tostring(buf);
66: }
67:
68: printexpr(f) /* print expression for debugging */
69: double f;
70: {
71: fprintf(stderr, "%g\n", f);
72: }
73:
74: printpos(p) /* print position for debugging */
75: obj *p;
76: {
77: double x, y;
78:
79: x = Xformx(p, 1, p->o_x, p->o_y);
80: y = Xformy(p, 0, p->o_x, p->o_y);
81: fprintf(stderr, "%g, %g\n", x, y);
82: }
83:
84: char *tostring(s)
85: register char *s;
86: {
87: register char *p;
88:
89: p = malloc(strlen(s)+1);
90: if (p == NULL) {
91: yyerror("out of space in tostring on %s", s);
92: exit(1);
93: }
94: strcpy(p, s);
95: return(p);
96: }
97:
98: obj *makepos(x, y, corner, q) /* make a position cell */
99: double x, y;
100: int corner;
101: obj *q;
102: {
103: obj *p;
104:
105: p = makenode(PLACE, 1, 0);
106: if (q)
107: p->o_parent = q;
108: p->o_x = x;
109: p->o_y = y;
110: p->o_val[0].f = corner;
111: return(p);
112: }
113:
114: obj *makebetween(f, p1, p2) /* make position between p1 and p2 */
115: double f; /* again, transforms must be applied */
116: obj *p1, *p2;
117: {
118: obj *p;
119: double x1, y1, x2, y2;
120:
121: p = makenode(PLACE, 3, 0);
122: x1 = Xformx(p1, 1, p1->o_x, p1->o_y);
123: y1 = Xformy(p1, 0, p1->o_x, p1->o_y);
124: x2 = Xformx(p2, 1, p2->o_x, p2->o_y);
125: y2 = Xformy(p2, 0, p2->o_x, p2->o_y);
126: p->o_x = x1 + f * (x2 - x1);
127: p->o_y = y1 + f * (y2 - y1);
128: p->o_val[0].f = f;
129: p->o_val[1].o = p1;
130: p->o_val[2].o = p2;
131: return(p);
132: }
133:
134: int xdelta[8] = {1,1,1,0,-1,-1,-1,0},
135: ydelta[8] = {-1,0,1,1,1,0,-1,-1};
136:
137: obj *getnth(p, nth) /* find nth point of an object */
138: obj *p;
139: int nth;
140: {
141: float x, y;
142: int n = nth;
143:
144: switch (p->o_type) {
145: default: if (n != 1)
146: yyerror("object has only 1 point defined");
147: return p;
148: case ARC: if (n > 2) {
149: yyerror("arcs have only 2 points defined");
150: return p;
151: }
152: /* else fall through to SECTOR case */
153: case SECTOR: if ((n %= 3) == 0)
154: return p;
155: else if (n == 1) {
156: x = p->o_val[N_VAL+2].f;
157: y = p->o_val[N_VAL+3].f;
158: }
159: else {
160: x = p->o_val[N_VAL+4].f;
161: y = p->o_val[N_VAL+5].f;
162: }
163: break;
164: case BLOCK: while (n--) {
165: p = p->o_next;
166: if (p->o_type <= TEXT)
167: continue;
168: else if (p->o_type == BLOCKEND) {
169: yyerror("[] has less than %d objects",
170: nth);
171: p = p->o_parent;
172: }
173: }
174: return p;
175: case BOX: n %= 8;
176: x = p->o_x + xdelta[n] * p->o_wid / 2;
177: y = p->o_y + ydelta[n] * p->o_ht / 2;
178: break;
179: case ARROW:
180: case LINE:
181: case SPLINE: if (--n > p->o_val[N_VAL+3].f) {
182: yyerror("line has less than %d points", nth);
183: return p;
184: }
185: x = p->o_val[N_VAL + 4 + 2 * n].f;
186: y = p->o_val[N_VAL + 5 + 2 * n].f;
187: break;
188: case CIRCLE:
189: case ELLIPSE: n %= 8;
190: x = xdelta[n] * p->o_wid / 2;
191: y = ydelta[n] * p->o_ht / 2;
192: if (n % 2 == 0) {
193: x *= M_SQRT1_2;
194: y *= M_SQRT1_2;
195: }
196: x += p->o_x;
197: y += p->o_y;
198: break;
199: }
200: /* DBK--Here also there is a question of whether x and y should
201: be transformed */
202: return makepos(x, y, nth, p);
203: }
204:
205: obj *getpos(p, corner) /* find position of point */
206: obj *p;
207: int corner;
208: {
209: float x, y;
210:
211: if (pic_compat && (p->o_type == CIRCLE || p->o_type == ELLIPSE) &&
212: (corner == NE || corner == NW || corner == SW || corner == SE))
213: return getnth(p, corner == NE ? 2 : corner == NW ? 4 :
214: corner == SW ? 6 : 8);
215: if (corner == -1 )
216: if (pic_compat && (p->o_type == LINE || p->o_type == ARROW ||
217: p->o_type == SPLINE))
218: corner = START;
219: else
220: return p;
221: whatpos(p, corner, &x, &y);
222: return makepos(x,y,corner,(corner < EAST || corner > SW)? p: (obj *)0);
223: }
224:
225: whatpos(p, corner, px, py) /* what is the position (no side effect) */
226: obj *p;
227: int corner;
228: float *px, *py;
229: {
230: float x, y, bnd[4];
231:
232: if (corner >= EAST && corner <= SW) {
233: get_bounds(p, bnd, 1);
234: switch (corner) {
235: case NE: x = bnd[2]; y = bnd[3]; break;
236: case SW: x = bnd[0]; y = bnd[1]; break;
237: case SE: x = bnd[2]; y = bnd[1]; break;
238: case NW: x = bnd[0]; y = bnd[3]; break;
239: case NORTH: x = (bnd[0]+bnd[2])/2; y = bnd[3]; break;
240: case SOUTH: x = (bnd[0]+bnd[2])/2; y = bnd[1]; break;
241: case EAST: x = bnd[2]; y = (bnd[1]+bnd[3])/2; break;
242: case WEST: x = bnd[0]; y = (bnd[1]+bnd[3])/2; break;
243: }
244: }
245: else { /* DBK--note that get_bounds returns the transformed position,
246: but the following calculations do not!! */
247: x = p->o_x;
248: y = p->o_y;
249:
250: /* futz around for special cases: */
251:
252: switch (p->o_type) {
253: case BLOCK: if (corner == START)
254: whatpos(p->o_next, START, &x, &y);
255: else if (corner == END)
256: whatpos(p->o_val[N_VAL+1].o->o_prev,END,&x,&y);
257: break;
258: case ARC: if (corner == START) {
259: x = p->o_val[N_VAL+2].f;
260: y = p->o_val[N_VAL+3].f;
261: }
262: else if (corner == END) {
263: x = p->o_val[N_VAL+4].f;
264: y = p->o_val[N_VAL+5].f;
265: }
266: break;
267: case LINE:
268: case SPLINE:
269: case ARROW: switch (corner) {
270: int n;
271: case START: x = p->o_val[N_VAL+4].f;
272: y = p->o_val[N_VAL+5].f;
273: break;
274: case END: n = N_VAL + 4 + 2*p->o_val[N_VAL+3].f;
275: x = p->o_val[n].f;
276: y = p->o_val[n+1].f;
277: break;
278: }
279: break;
280: }
281: }
282: *px = x;
283: *py = y;
284: return 1;
285: }
286:
287: obj *gethere() /* make a place for curx,cury */
288: {
289: return(makepos(curx, cury, 0, (obj *)0));
290: }
291:
292: obj *getlast(n, t) /* find n-th previous occurrence of type t */
293: int n, t;
294: {
295: int k;
296: obj *p;
297:
298: k = n;
299: if (t == TEXTOBJ) /* for purely syntactical reasons */
300: t = TEXT;
301: for (p = objtail->o_prev; p != objhead; p = p->o_prev) {
302: if (p->o_type == BLOCKEND) {
303: p = p->o_parent;
304: if (t != BLOCK && t != OBJECT)
305: continue;
306: }
307: if (t == OBJECT && p->o_type > TEXT)
308: continue;
309: if (t != OBJECT && p->o_type != t)
310: continue;
311: if (--k > 0)
312: continue; /* not there yet */
313: return(p);
314: }
315: yyerror("there is no %dth last", n);
316: return(NULL);
317: }
318:
319: obj *getfirst(n, t) /* find n-th occurrence of type t */
320: int n, t;
321: {
322: int k;
323: obj *p;
324:
325: k = n;
326: if (t == TEXTOBJ)
327: t = TEXT;
328: for (p = objhead->o_next; p != objtail; p = p->o_next) {
329: if (p->o_type == BLOCK
330: && t != BLOCK && t != OBJECT) { /* skip block, */
331: if (p->o_val[N_VAL].o != NULL) /* unless it's */
332: p = p->o_val[N_VAL].o; /* still active */
333: continue;
334: }
335: if (t == OBJECT && p->o_type > TEXT)
336: continue;
337: if (t != OBJECT && p->o_type != t)
338: continue;
339: if (--k > 0)
340: continue; /* not there yet */
341: return(p);
342: }
343: yyerror("there is no %dth", n);
344: return(NULL);
345: }
346:
347: double getblkvar(p, s) /* find variable s2 in block p */
348: obj *p;
349: char *s;
350: {
351: YYSTYPE y, getblk();
352:
353: y = getblk(p, s);
354: free(s);
355: return y.f;
356: }
357:
358: obj *getblock(p, s) /* find variable s in block p */
359: obj *p;
360: char *s;
361: {
362: YYSTYPE y, getblk();
363:
364: y = getblk(p, s);
365: free(s);
366: return y.o;
367: }
368:
369: YYSTYPE getblk(p, s) /* find union type for s in p */
370: obj *p;
371: char *s;
372: {
373: static YYSTYPE bug;
374: struct symtab *stp;
375:
376: if (p->o_type != BLOCK) {
377: yyerror(".%s is not in that block", s);
378: return(bug);
379: }
380: for (stp = p->o_val[N_VAL+1].s; stp != NULL; stp = stp->s_next)
381: if (strcmp(s, stp->s_name) == 0)
382: return(stp->s_val);
383: yyerror("there is no .%s in that []", s);
384: return(bug);
385: }
386:
387: obj *fixpos(p, x, y) /* this, addpos & subpos SHOULD be altered to give */
388: obj *p; /* o_x,o_y as offset from position of p, with p as */
389: double x, y; /* o_parent, but I haven't yet worked out the xform. */
390: {
391: #if 1
392: /* DBK: 3/21/90 -- comment out the following if clause. It has the effect
393: of changing A in the expression A + x,y !!!
394: if (p->o_type == PLACE) {
395: p->o_x += x;
396: p->o_y += y;
397: return p;
398: }
399: end of commented out code *************/
400: x += Xformx(p, 1, p->o_x, p->o_y);
401: y += Xformy(p, 0, p->o_x, p->o_y);
402: #else
403: if (p->o_type == PLACE) {
404: x += p->o_x;
405: y += p->o_y;
406: }
407: else {
408: x += Xformx(p, 1, p->o_x, p->o_y);
409: y += Xformy(p, 0, p->o_x, p->o_y);
410: }
411: #endif
412: return makepos(x, y, 0, (obj *)0);
413: }
414:
415: obj *addpos(p, q)
416: obj *p, *q;
417: {
418: double x, y;
419:
420: x = Xformx(q, 1, q->o_x, q->o_y);
421: y = Xformy(q, 0, q->o_x, q->o_y);
422: /* DBK: see above
423: if (p->o_type == PLACE) {
424: p->o_x += x;
425: p->o_y += y;
426: return p;
427: }
428: */
429: x += Xformx(p, 1, p->o_x, p->o_y);
430: y += Xformy(p, 0, p->o_x, p->o_y);
431: return makepos(x, y, 0, (obj *)0);
432: }
433:
434: obj *subpos(p, q)
435: obj *p, *q;
436: {
437: double x, y;
438:
439: x = Xformx(q, 1, q->o_x, q->o_y);
440: y = Xformy(q, 0, q->o_x, q->o_y);
441: /* DBK: see above
442: if (p->o_type == PLACE) {
443: p->o_x -= x;
444: p->o_y -= y;
445: return p;
446: }
447: */
448: x -= Xformx(p, 1, p->o_x, p->o_y);
449: y -= Xformy(p, 0, p->o_x, p->o_y);
450: return makepos(x, y, 0, (obj *)0);
451: }
452:
453: obj *makenode(type, n, layer)
454: int type, n, layer;
455: {
456: obj *p;
457:
458: if (objbuf && batch)
459: print_buf();
460: p = (obj *) calloc(1, sizeof(obj) + (n-1)*sizeof(YYSTYPE));
461: if (p == NULL) {
462: yyerror("out of space in makenode");
463: exit(1);
464: }
465: if (n > 65535)
466: yyerror("making excessively large object");
467: p->o_next = objtail;
468: p->o_prev = objtail->o_prev;
469: p->o_prev->o_next = objtail->o_prev = p;
470: p->o_parent = cur_block;
471: p->o_x = curx;
472: p->o_y = cury;
473: p->o_nt1 = ntext1;
474: p->o_nt2 = ntext;
475: p->o_text = -1;
476: #if 1
477: /* force all strings in object to have same justification */
478: {
479: int jflags, lastf;
480: jflags = RJUST|LJUST|CENTER|ABOVE|BELOW;
481: lastf = text[ntext-1].t_type & jflags;
482: for ( ; ntext1 < ntext; ntext1++)
483: text[ntext1].t_type = text[ntext1].t_type & ~ jflags | lastf;
484: }
485: #endif
486: ntext1 = ntext; /* ready for next caller */
487: if (layer < -128)
488: layer = -128;
489: else if (layer > 127)
490: layer = 127;
491: if ((p->o_layer = layer) > 0 && layer > top_layer)
492: top_layer = layer;
493: if ((p->o_type = type) <= TEXT) {
494: p->o_mxx = p->o_myy = 1.0; /* initialize xform matrix */
495: p->o_size = n; /* keep count, for copies */
496: }
497: return(p);
498: }
499:
500: freenode (p) /* free space occupied by object p */
501: obj *p;
502: {
503: obj *q, *q1;
504:
505: if (p->o_type == BLOCK) { /* I think there's */
506: freesymtab(p->o_val[N_VAL+1].s); /* a bug here, for */
507: q = p->o_val[N_VAL].o; /* nested blocks. */
508: p->o_prev->o_next = q->o_next;
509: q->o_next->o_prev = p->o_prev;
510: q->o_next = (obj *)NULL;
511: for (q = p->o_next; q != NULL; ) {
512: if (q->o_type == BLOCK)
513: freesymtab(q->o_val[N_VAL+1].s);
514: q1 = q;
515: q = q->o_next;
516: free(q1);
517: }
518: }
519: else {
520: p->o_prev->o_next = p->o_next;
521: p->o_next->o_prev = p->o_prev;
522: }
523: free (p);
524: if (!objbuf) redo_gbox = 1; /* page boundaries are now suspect */
525: }
526:
527: extreme(x, y, bbox) /* record max and min x and y values */
528: double x, y;
529: float *bbox;
530: {
531: if ((float)x < bbox[0]) bbox[0] = x;
532: if ((float)y < bbox[1]) bbox[1] = y;
533: if ((float)x > bbox[2]) bbox[2] = x;
534: if ((float)y > bbox[3]) bbox[3] = y;
535: }
536:
537: track_bounds(x0, y0, x1, y1) /* insert a bounding box into the global box */
538: double x0, y0, x1, y1;
539: {
540: if (x0 < Gbox[0]) Gbox[0] = x0;
541: if (y0 < Gbox[1]) Gbox[1] = y0;
542: if (x1 > Gbox[2]) Gbox[2] = x1;
543: if (y1 > Gbox[3]) Gbox[3] = y1;
544: }
545:
546: get_bounds(p, bbox, flag) /* reconstruct bounding box from center/basis/xform */
547: obj *p;
548: float *bbox;
549: int flag;
550: {
551: static obj *lastp = (obj *)0;
552: static double x0, y0, x1, y1;
553: double w, h, wm, hm, x, y;
554: double owid, oht;
555:
556: if (flag && p == lastp)
557: goto done;
558: x = Xformx(p, 1, p->o_x, p->o_y);
559: y = Xformy(p, 0, p->o_x, p->o_y);
560: if (p->o_type > TEXT) {
561: x0 = x1 = x;
562: y0 = y1 = y;
563: }
564: else {
565: if (p->o_type == TEXT) {
566: x += Linx(p,0,p->o_val[N_VAL-2].f,p->o_val[N_VAL-1].f);
567: y += Liny(p,0,p->o_val[N_VAL-2].f,p->o_val[N_VAL-1].f);
568: }
569: else if (p->o_type == ARC || p->o_type == SECTOR) {
570: x -= Linx(p,0,p->o_val[N_VAL+6].f,p->o_val[N_VAL+7].f);
571: y -= Liny(p,0,p->o_val[N_VAL+6].f,p->o_val[N_VAL+7].f);
572: }
573: owid = p->o_wid + p->o_weight;
574: oht = p->o_ht + p->o_weight;
575: if ( ( p->o_type == ARROW || p->o_type == LINE
576: || p->o_type == SPLINE || p->o_type == ARC)
577: && (p->o_attr & HEAD12)) {
578: w = p->o_val[N_VAL+(p->o_type == ARC ? 8 : 1)].f;
579: owid += w; /* account for width of arrowheads */
580: oht += w;
581: }
582: w = Linx(p, 0, owid, oht) / 2; /* transform main diagonal */
583: h = Liny(p, 0, owid, oht) / 2;
584: wm = Linx(p, 0, -owid, oht) / 2; /* transform other diagonal */
585: hm = Liny(p, 0, -owid, oht) / 2;
586: if (w < 0) w = -w;
587: if (h < 0) h = -h;
588: if (wm < 0) wm = -wm;
589: if (hm < 0) hm = -hm;
590: if (w < wm) w = wm;
591: if (h < hm) h = hm;
592: x0 = x - w;
593: x1 = x + w;
594: y0 = y - h;
595: y1 = y + h;
596: }
597: lastp = p;
598: done: bbox[0] = x0; bbox[1] = y0; bbox[2] = x1; bbox[3] = y1;
599: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.