|
|
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:print.c 1.0 */
9:
10: #include <assert.h>
11: #include <ctype.h>
12: #include <string.h>
13: #include "picasso.h"
14: #include "y.tab.h"
15:
16: extern int eqn_count;
17: int flyback;
18: int redo_gbox = 0;
19: int objcount = 0;
20:
21: print_buf()
22: {
23: int n;
24: obj *p;
25:
26: if (++objcount > objbuf) {
27: p = objhead->o_next;
28: if (p->o_type != BLOCK)
29: print_obj(p->o_layer, p);
30: else if (p->o_val[N_VAL].o == (obj *)0)
31: return;
32: else for (n = draftlayer; n <= top_layer; n++)
33: print_obj(n,p);
34: freenode(p);
35: }
36: }
37:
38: extern FILE *pipefp, *eqnfp;
39: extern char psfname[];
40:
41: print(c) /* show everything (above draft layers) */
42: int c;
43: {
44: int n;
45:
46: /* Added 10/15/90--DBK. Is there any reason NOT to do this? */
47: redo_gbox = 1;
48: if (pipefp) {
49: pclose(pipefp);
50: pipefp = NULL;
51: if ((eqnfp = fopen(psfname,"r")) == NULL)
52: fatal("cannot read eqn output");
53: }
54: flyback = (c == 'F');
55: if (c != 'N')
56: for (n = draftlayer; n <= top_layer; ++n)
57: print_layer(n);
58: if (eqnfp) {
59: fclose(eqnfp);
60: eqnfp = NULL;
61: eqn_count = 0;
62: unlink(psfname);
63: }
64: }
65:
66: print_layer(n) /* show contents of a single layer (maybe a draft layer) */
67: int n;
68: {
69: obj *p;
70:
71: for (p = objhead->o_next; p!= objtail; p = p->o_next)
72: p = print_obj(n, p);
73: }
74:
75: print_bnd(p, q) /* show everything (non-draft) between given bounds */
76: obj *p, *q;
77: {
78: int n;
79:
80: for (n = draftlayer; n <= top_layer; ++n)
81: print_layer_bnd(n, p, q);
82: }
83:
84: print_layer_bnd(n, p, q) /* show objects in layer n from p to q */
85: int n;
86: obj *p, *q;
87: {
88: obj *r;
89: float x0, y0, x1, y1, bnd[4];
90:
91: if (p->o_x < q->o_x)
92: { x0 = p->o_x; x1 = q->o_x; }
93: else
94: { x0 = q->o_x; x1 = p->o_x; }
95: if (p->o_y < q->o_y)
96: { y0 = p->o_y; y1 = q->o_y; }
97: else
98: { y0 = q->o_y; y1 = p->o_y; }
99:
100: for (r = objhead->o_next; r!= objtail; r = r->o_next)
101: if (r->o_x >= x0 && r->o_x <= x1
102: && r->o_y >= y0 && r->o_y <= y1)
103: r = print_obj(n, r);
104: }
105:
106: obj *print_obj(layer, p)
107: int layer;
108: obj *p;
109: {
110: double r, dx, dy, ox, oy, x0, y0, x1, y1;
111: obj *q;
112: int n;
113:
114: if (redo_gbox) {
115: float bnd[4];
116: Gbox[2] = Gbox[3] = -(Gbox[0] = Gbox[1] = 32767);
117: for (q = objhead->o_next; q != objtail; q = q->o_next) {
118: get_bounds(q, bnd, 1);
119: track_bounds (bnd[0], bnd[1], bnd[2], bnd[3]);
120: if (q->o_type == BLOCK)
121: q = q->o_val[N_VAL].o;
122: }
123: redo_gbox = 0;
124: }
125: openpl("");
126: if (p->o_type != BLOCK && p->o_layer != layer)
127: return p;
128: if (p->o_type <= TEXT && (p->o_mxx!=1 || p->o_myy!=1 || p->o_mxy!=0 ||
129: p->o_myx!=0 || p->o_mxt!=0 || p->o_myt!=0))
130: return print_xform(layer,p);
131:
132: ox = p->o_x;
133: oy = p->o_y;
134: if (p->o_type < TEXT && (p->o_attr & (FILLED | EDGED)))
135: chk_attrs (p);
136: switch (p->o_type) {
137:
138: case TROFF:
139: n = p->o_nt1;
140: if (text[n].t_type & EQNTXT)
141: puteqn(ox, oy, text[n].t_type, atoi(text[n].t_val));
142: else
143: troff(text[n].t_val);
144: return p;
145: case BLOCK:
146: for (q = p->o_next; q != p->o_val[N_VAL].o; q = q->o_next)
147: if (q->o_type <= TEXT || q->o_nt2 > q->o_nt1)
148: q = print_obj(layer,q);
149: p = q;
150: break;
151: case PSFILE:
152: puteps(p);
153: /* CAREFUL!! THIS FLOWS THROUGH INTO BOX!! */
154: case BOX:
155: if (p->o_attr & (FILLED|EDGED)) {
156: x0 = ox - p->o_wid/2; x1 = ox + p->o_wid/2;
157: y0 = oy - p->o_ht/2; y1 = oy + p->o_ht/2;
158: r = p->o_val[N_VAL].f;
159: box(x0, y0, x1, y1, r);
160: }
161: break;
162: case CIRCLE:
163: case ELLIPSE:
164: if (p->o_attr & (FILLED|EDGED))
165: ellipse(ox,oy,p->o_wid/2,0.,0.,p->o_ht/2,0.,2*M_PI,0);
166: break;
167: case SECTOR:
168: case ARC:
169: if (p->o_attr & (FILLED|EDGED)) {
170: register double ang1, ang2;
171:
172: if (p->o_attr & HEAD12) {
173: print_xform(layer, p);
174: break;
175: }
176: r = p->o_val[N_VAL+0].f;
177: x0 = p->o_val[N_VAL+2].f; /* starting point */
178: y0 = p->o_val[N_VAL+3].f;
179: x1 = p->o_val[N_VAL+4].f; /* ending point */
180: y1 = p->o_val[N_VAL+5].f;
181: ang1 = atan2(y0-oy, x0-ox);
182: ang2 = atan2(y1-oy, x1-ox);
183: ellipse(ox, oy, r, 0., 0., r, ang1, ang2, p->o_type);
184: }
185: break;
186: case LINE:
187: case ARROW:
188: case SPLINE:
189: if (p->o_attr & (FILLED|EDGED)) {
190: int c, nxy;
191:
192: if (p->o_attr & HEAD12) {
193: print_xform(layer, p);
194: break;
195: }
196: r = p->o_val[N_VAL+0].f;
197: nxy = p->o_val[N_VAL+3].f; /* segment count */
198: x0 = p->o_val[N_VAL+4].f; /* first point */
199: y0 = p->o_val[N_VAL+5].f;
200: x1 = p->o_val[N_VAL+4+2*nxy].f; /* last point */
201: y1 = p->o_val[N_VAL+5+2*nxy].f;
202: c = (x0 == x1 && y0 == y1); /* flags closure */
203: if (nxy == 1)
204: line(x0, y0, x1, y1);
205: else if (p->o_type == SPLINE)
206: spline(nxy, c, &p->o_val[N_VAL+4]);
207: else
208: pline (nxy, c, &p->o_val[N_VAL+4], r);
209: }
210: break;
211: }
212: if (p->o_nt1 < p->o_nt2)
213: objtext(ox, oy, p);
214: return p;
215: }
216:
217: obj *print_xform (layer,p)
218: int layer;
219: obj *p;
220: {
221: double r, ox, oy, dx, dy, x0, y0, x1, y1, M[4];
222: double b, tx0, ty0, tx1, ty1;
223: valtype *X;
224: obj *q;
225: int n;
226:
227: if (p->o_type == BLOCK) {
228: for (q = p->o_next; q != p->o_val[N_VAL].o; q = q->o_next)
229: if (q->o_type <= TEXT || q->o_nt2 > q->o_nt1)
230: q = print_xform(layer,q);
231: p = q;
232: }
233: if (p->o_layer != layer && p->o_type != BLOCK)
234: return p;
235: #if 0
236: if (p->o_type == TEXT) {
237: ox = Xformx(p->o_parent, 1, p->o_x, p->o_y);
238: oy = Xformy(p->o_parent, 0, p->o_x, p->o_y);
239: }
240: else {
241: #endif
242: ox = Xformx(p, 1, p->o_x, p->o_y);
243: oy = Xformy(p, 0, p->o_x, p->o_y);
244: #if 0
245: }
246: #endif
247: X = (valtype *)0;
248: if (p->o_type < TEXT && (p->o_attr & (FILLED | EDGED)))
249: chk_attrs (p);
250:
251: switch (p->o_type) {
252:
253: case TROFF:
254: n = p->o_nt1;
255: if (text[n].t_type & EQNTXT)
256: puteqn(ox, oy, text[n].t_type, atoi(text[n].t_val));
257: else
258: troff(text[n].t_val);
259: return p;
260: case PSFILE:
261: puteps(p);
262: /* CAREFUL!! THIS FLOWS THROUGH INTO BOX!! */
263: case BOX:
264: if (p->o_attr & (FILLED|EDGED)) {
265: if ((X = (valtype *)malloc(10*sizeof(valtype))) == NULL)
266: yyerror("out of room in print_xform");
267: r = p->o_val[N_VAL].f;
268: X[6].f = X[0].f = -(X[2].f = X[4].f = p->o_wid/2);
269: X[1].f = X[3].f = -(X[5].f = X[7].f = p->o_ht/2);
270: for (n = 0; n < 8; n += 2) {
271: x1 = ox + Linx(p, 0, X[n].f, X[n+1].f);
272: X[n+1].f = oy + Liny(p, 0, X[n].f, X[n+1].f);
273: X[n].f = x1;
274: }
275: X[n] = X[0]; X[++n] = X[1];
276: x1 = Linx(p, 0, r, 0.);
277: r = Liny(p, 0, r, 0.);
278: r = sqrt(x1 * x1 + r * r);
279: pline(4, 1, X, r);
280: }
281: break;
282: case CIRCLE:
283: case ELLIPSE:
284: if (p->o_attr & (FILLED|EDGED)) {
285: get_matrix(&x0, &y0, &x1, &y1);
286: x0 *= p->o_wid/2;
287: y0 *= p->o_wid/2;
288: x1 *= p->o_ht/2;
289: y1 *= p->o_ht/2;
290: ellipse(ox, oy, x0, y0, x1, y1, 0., 2*M_PI, 0);
291: }
292: break;
293: case SECTOR:
294: case ARC:
295: if (p->o_attr & (FILLED|EDGED)) {
296: register double ang1, ang2;
297: double xa, ya;
298: double dx0, dy0, dx1, dy1;
299:
300: r = p->o_val[N_VAL+0].f;
301: x0 = p->o_val[N_VAL+2].f; /* starting point */
302: y0 = p->o_val[N_VAL+3].f;
303: x1 = p->o_val[N_VAL+4].f; /* ending point */
304: y1 = p->o_val[N_VAL+5].f;
305: get_matrix(M, M+1, M+2, M+3);
306: /*
307: * If there are arrowheads and non-zero line thickness, we
308: * should adjust the end points so as to get nice arrowheads.
309: */
310: if (p->o_attr & HEAD12) {
311: dx0 = Xformx(p, 1, x0, y0); /* Remember */
312: dy0 = Xformy(p, 0, x0, y0); /* directions for */
313: dx1 = Xformx(p, 0, x1, y1); /* arrowheads */
314: dy1 = Xformy(p, 0, x1, y1);
315: /* in here we need to change the points used to compute
316: the angles. */
317: dx = p->o_val[N_VAL+8].f;
318: dy = p->o_val[N_VAL+9].f;
319: if (p->o_weight > 0.) {
320: double linex, liney, a;
321:
322: b = p->o_weight / 2 / p->o_val[N_VAL+8].f;
323: b *= sqrt(dx*dx + 4*dy*dy);
324: if (p->o_attr & HEAD2) {
325: linex = - (y1 - p->o_y);
326: liney = (x1 - p->o_x);
327: a = b / sqrt(linex*linex + liney*liney);
328: x1 -= a * linex;
329: y1 -= a * liney;
330: }
331: if (p->o_attr & HEAD1) {
332: linex = (y0 - p->o_y);
333: liney = - (x0 - p->o_x);
334: a = b / sqrt(linex*linex + liney*liney);
335: x0 -= a * linex;
336: y0 -= a * liney;
337: }
338: }
339: }
340: tx0 = Xformx(p, 1, x0, y0); /* transformed starting point */
341: ty0 = Xformy(p, 0, x0, y0);
342: tx1 = Xformx(p, 0, x1, y1); /* transformed ending point */
343: ty1 = Xformy(p, 0, x1, y1);
344: ang1 = atan2(ty0 - oy, tx0 - ox);
345: ang2 = atan2(ty1 - oy, tx1 - ox);
346:
347: dx = M[0] * M[3] - M[1] * M[2];
348: if (dx < 0) { /* reflection */
349: xa = ang1;
350: ang1 = ang2;
351: ang2 = xa;
352: M[0] = -M[0];
353: M[2] = -M[2];
354: }
355: ellipse(ox, oy, r*M[0], r*M[1], r*M[2], r*M[3],
356: ang1, ang2, p->o_type);
357:
358: if (p->o_attr & (HEAD1 | HEAD2)) {
359: ang1 = 0;
360: if (dx < 0) {
361: ang1 = M_PI;
362: dx = -dx;
363: }
364: dy = dx = sqrt(dx);
365: dx *= p->o_val[N_VAL+8].f;
366: dy *= p->o_val[N_VAL+9].f;
367: if (p->o_attr & HEAD1)
368: arrow(tx0-(dy0-oy), ty0+(dx0-ox), tx0, ty0,
369: dx, dy, dy/r/2 + ang1, p->o_attr);
370: if (p->o_attr & HEAD2)
371: arrow(tx1+(dy1-oy), ty1-(dx1-ox), tx1, ty1,
372: dx, dy, -dy/r/2 + ang1, p->o_attr);
373: }
374: }
375: break;
376: case LINE:
377: case ARROW:
378: case SPLINE:
379: if (p->o_attr & (FILLED|EDGED)) {
380: int c, i, nxy;
381:
382: r = p->o_val[N_VAL+0].f;
383: x1 = Linx(p, 0, r, 0.);
384: r = Liny(p, 0, r, 0.);
385: r = sqrt(x1 * x1 + r * r);
386: nxy = p->o_val[N_VAL+3].f; /* segment count */
387: X = (valtype *)malloc((2*nxy+2)*sizeof(valtype));
388: if (X == NULL)
389: yyerror("out of room in print_xform");
390: for (i = 0, n = N_VAL+4; i <= 2 * nxy; ) {
391: register double xx = p->o_val[n++].f,
392: yy = p->o_val[n++].f;
393: X[i++].f = Xformx(p, 0, xx, yy);
394: X[i++].f = Xformy(p, 0, xx, yy);
395: }
396: x0 = X[0].f;
397: y0 = X[1].f;
398: x1 = X[i-2].f;
399: y1 = X[i-1].f;
400: tx0 = ty0 = tx1 = ty1 = 0.;
401: n = 2 * nxy - 2;
402: if (p->o_attr & HEAD12) {
403: get_matrix(M, M+1, M+2, M+3);
404: /* DBK: I added the fabs to eliminate sqrt errors
405: * and make it same as xprint.c. 9/20/90 */
406: dy = dx = sqrt(fabs(M[0]*M[3] - M[1]*M[2]));
407: dx *= p->o_val[N_VAL+1].f;
408: dy *= p->o_val[N_VAL+2].f;
409: if (p->o_weight > 0.) {
410: double linex, liney, a;
411:
412: b = p->o_weight / 2 / p->o_val[N_VAL+1].f;
413: b *= sqrt(dx*dx + 4*dy*dy);
414: if (p->o_attr & HEAD2) {
415: linex = x1 - X[n].f;
416: liney = y1 - X[n+1].f;
417: a = b / sqrt(linex*linex + liney*liney);
418: tx1 = -a * linex;
419: ty1 = -a * liney;
420: x1 = X[n+2].f += tx1;
421: y1 = X[n+3].f += ty1;
422: }
423: if (p->o_attr & HEAD1) {
424: linex = x0 - X[2].f;
425: liney = y0 - X[3].f;
426: a = b / sqrt(linex*linex + liney*liney);
427: tx0 = -a * linex;
428: ty0 = -a * liney;
429: x0 = X[0].f += tx0;
430: y0 = X[1].f += ty0;
431: }
432: }
433: }
434: /* The first two args are just to give a direction to
435: * the second two. To make sure that the direction
436: * isn't reversed, adjust the first two by the same
437: * amount as we adjusted x1 and y1 above.
438: */
439: c = (x0 == x1 && y0 == y1); /* flags closure */
440: if (nxy == 1)
441: line(X[0].f, X[1].f, X[2].f, X[3].f);
442: else if (p->o_type == SPLINE)
443: spline(nxy, c, X);
444: else
445: pline (nxy, c, X, r);
446: if (p->o_attr & HEAD2) {
447: tx1 += X[n].f;
448: ty1 += X[n+1].f;
449: arrow(tx1, ty1, x1, y1, dx, dy, 0.0, p->o_attr);
450: }
451: if (p->o_attr & HEAD1) {
452: tx0 += X[2].f;
453: ty0 += X[3].f;
454: arrow(tx0, ty0, x0, y0, dx, dy, 0.0, p->o_attr);
455: }
456: }
457: break;
458: case TEXT:
459: tmp_xform(p);
460: #if 0
461: dotext(ox, oy, p);
462: #else
463: dotext(p->o_x, p->o_y, p);
464: #endif
465: undo_tmpx();
466: return p;
467: }
468: if (X)
469: free(X);
470: if (p->o_nt1 < p->o_nt2)
471: objtext(ox, oy, p);
472: return p;
473: }
474:
475: objtext(x, y, p)
476: double x, y;
477: obj *p;
478: {
479: double *bnd;
480: int i, t;
481:
482: t = text[p->o_nt1].t_type;
483: for (i = p->o_nt1; i < p->o_nt2; i++)
484: if (text[i].t_type != t)
485: break;
486: if (i >= p->o_nt2 && p->o_type != TEXT) { /* all strings same type */
487: bnd = text_bounds(p);
488: if (t & RJUST)
489: x += (bnd[2] - bnd[0]) / 2;
490: if (t & LJUST)
491: x -= (bnd[2] - bnd[0]) / 2;
492: }
493: dotext(x, y, p);
494: }
495:
496: dotext(x, y, p) /* print text strings of p in proper vertical spacing */
497: double x, y;
498: obj *p;
499: {
500: double h, v, w, dely;
501: int i, j, n, t;
502:
503: i = p->o_nt1;
504: j = text[i].t_line; /* sequence # of first line */
505: n = text[p->o_nt2-1].t_line - j; /* total number of lines (-1) */
506: v = abs(text[i].t_size) / (2 * pgscale);
507: dely = abs(text[i].t_space) / (2 * pgscale);
508: v = n * dely - v/2;
509: new_color(p->o_text);
510: for (h = w = 0; i < p->o_nt2; ++j, v -= 2*dely, h = w = 0) {
511: t = text[i].t_type;
512: if (t & ABOVE)
513: v += dely;
514: else if (t & BELOW)
515: v -= dely;
516: for (n = i; text[n].t_line == j; n++)
517: w += text[n].t_width*72/pgscale;
518: if (t & RJUST)
519: h = w;
520: else if (t & CENTER)
521: h = w/2;
522: newlabel(t, text[i].t_val, abs(text[i].t_font), x-h, y+v,
523: text[i].t_size / pgscale,
524: text[i].t_width * 72 / pgscale);
525: while (++i < n)
526: addlabel(text[i].t_type, text[i].t_val,
527: text[i].t_font, text[i].t_size / pgscale,
528: text[i].t_width * 72 / pgscale);
529: }
530: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.