|
|
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:textgen.c 1.0 */
9:
10: #include <string.h>
11: #include <ctype.h>
12: #include "picasso.h"
13: #include "y.tab.h"
14:
15: extern int pic_compat;
16:
17: obj *textgen()
18: {
19: static double prevh = 0;
20: static double prevw = 0;
21:
22: struct objattr obat;
23: int i, sub, at, with, saw_with = 0;
24: double *bnd, savGbox[4], xwith, ywith;
25: double savcurx, savcury;
26: obj *p, *ppos;
27: Attr *ap;
28:
29: if (pic_compat) { /* in pic, bounding box has size zero */
30: savcurx = curx;
31: savcury = cury;
32: }
33: obat.a_weight = obat.a_pcolor = obat.a_lcolor = obat.a_tcolor = -1;
34: obat.a_ht = obat.a_wid = 0;
35: obat.a_dashpat.a = (float *)0;
36: obat.a_layer = (int)getfval("curlayer");
37: sub = CENTER;
38: at = with = 0;
39: set_text();
40: for (i = 0; i < nattr; i++) {
41: ap = &attr[i];
42: switch (ap->a_type) {
43: default:
44: miscattrs(ap, &obat);
45: break;
46: case WITH:
47: with = ap->a_val.i;
48: saw_with++;
49: break;
50: case AT:
51: ppos = ap->a_val.o;
52: curx = Xformx(ppos, 1, ppos->o_x, ppos->o_y);
53: cury = Xformy(ppos, 0, ppos->o_x, ppos->o_y);
54: at++;
55: break;
56: }
57: }
58: p = makenode(TEXT, N_VAL, obat.a_layer);
59: /* NOTE: the three color attributes reduce to one here; their obj.val
60: * slots are used to record bounding box center. If outline fonts are
61: * implemented, o_fill will be needed, and some adjustments made below
62: */
63: if (obat.a_tcolor == -1)
64: if ((obat.a_tcolor = obat.a_pcolor) == -1)
65: obat.a_tcolor = obat.a_lcolor;
66: p->o_text = obat.a_tcolor;
67: checktextcolor(p);
68: p->o_attr |= EDGED;
69: /* need to save and restore the global bounding box, since text_bounds
70: sets it based on o_x and o_y, which are not properly set yet! */
71: for (i = 0; i < 4; i++)
72: savGbox[i] = Gbox[i];
73: bnd = text_bounds(p);
74: for (i = 0; i < 4; i++)
75: Gbox[i] = savGbox[i];
76: p->o_val[N_VAL-2].f = (bnd[0] + bnd[2]) / 2;
77: p->o_val[N_VAL-1].f = (bnd[1] + bnd[3]) / 2;
78: prevw = p->o_wid = (obat.a_wid > 0 ? obat.a_wid : bnd[2]-bnd[0]);
79: prevh = p->o_ht = (obat.a_ht > 0 ? obat.a_ht : bnd[3]-bnd[1]);
80:
81: if (pic_compat) { /* Here unchanged, or changed to at */
82: if (!saw_with) { /* adjustment w.r.t. Here */
83: p->o_x = curx;
84: p->o_y = cury;
85: }
86: else { /* forces text center to Here, since all corners
87: are at center (size is zero) */
88: p->o_x = curx - p->o_val[N_VAL-2].f;
89: p->o_y = cury - p->o_val[N_VAL-1].f;
90: }
91: }
92: else {
93: if (at == 0 && saw_with == 0)
94: with = isright(hvmode) ? WEST : /* the default for with */
95: isleft(hvmode) ? EAST : /* butts the text box a- */
96: isup(hvmode) ? SOUTH :/* gainst the current point */
97: NORTH; /* in the current direction */
98: /* position of center relative to current point */
99: xwith = ywith = 0.0;
100: switch (with) {
101: case NORTH: ywith = -prevh/2; break;
102: case SOUTH: ywith = prevh/2; break;
103: case EAST: xwith = -prevw/2; break;
104: case WEST: xwith = prevw/2; break;
105: case NE: xwith = -prevw/2; ywith = -prevh/2; break;
106: case SE: xwith = -prevw/2; ywith = prevh/2; break;
107: case NW: xwith = prevw/2; ywith = -prevh/2; break;
108: case SW: xwith = prevw/2; ywith = prevh/2; break;
109: }
110: curx += xwith; /* position of center, temporarily */
111: cury += ywith;
112: /* calculate PLACE for this object based on center */
113: p->o_x = curx - p->o_val[N_VAL-2].f;
114: p->o_y = cury - p->o_val[N_VAL-1].f;
115:
116: /* calculate new postion for Here */
117: if (isright(hvmode))
118: curx += prevw/2;
119: else if (isleft(hvmode))
120: curx -= prevw/2;
121: else if (isup(hvmode))
122: cury += prevh/2;
123: else
124: cury -= prevh/2;
125: }
126:
127: track_bounds (bnd[0]+p->o_x, bnd[1]+p->o_y,
128: bnd[2]+p->o_x, bnd[3]+p->o_y);
129: return(p);
130: }
131:
132: int def_font, def_size, def_space;
133: int cur_font, cur_size, cur_space;
134:
135: set_text()
136: {
137: cur_font = cur_size = cur_space = 0;
138: def_font = (int)getfval("textfont");
139: def_size = (int)getfval("textsize");
140: def_space = (int)getfval("textspace");
141: }
142:
143: reset_font(val) /* user supplied font attribute on object */
144: double val; /* (stored as negative, to distinguish it */
145: { /* from troff escape embedded in a string) */
146: cur_font = -val;
147: }
148:
149: reset_size (op, val)
150: int op;
151: double val;
152: {
153: if (cur_size == 0)
154: cur_size = -def_size;
155: switch (op) {
156: default: cur_size = -val; break;
157: case '+': cur_size -= val; break;
158: case '-': cur_size += val; break;
159: case '*': cur_size *= val; break;
160: case '/': if (val != 0)
161: cur_size /= val;
162: }
163: }
164:
165: reset_space (op, val)
166: int op;
167: double val;
168: {
169: if (cur_space == 0)
170: cur_space = -def_space;
171: switch (op) {
172: default: cur_space = -val; break;
173: case '+': cur_space -= val; break;
174: case '-': cur_space += val; break;
175: case '*': cur_space *= val; break;
176: case '/': if (val != 0)
177: cur_space /= val;
178: }
179: }
180:
181: fix_text(n1, n2) /* fill in default font/size/space values */
182: int n1, n2; /* if space unspecified, set from size. */
183: {
184: if (cur_font == 0)
185: cur_font = -def_font;
186: if (cur_size == 0)
187: cur_size = -def_size;
188: if (cur_space == 0)
189: cur_space = (cur_size==0 ? -def_space : (double)cur_size
190: * def_space/def_size);
191: while (n1 < n2) {
192: if (text[n1].t_font == 0)
193: text[n1].t_font = cur_font;
194: if (text[n1].t_size == 0)
195: text[n1].t_size = cur_size;
196: if (text[n1].t_space == 0)
197: text[n1].t_space = text[n1].t_size == 0 ? cur_space :
198: (short)(text[n1].t_size
199: * (double)def_space/def_size);
200: ++n1;
201: }
202: }
203:
204: int ntextlines = 0;
205:
206: savetext(type, s) /* record text elements for current object */
207: int type; /* breaking up into homogeneous font/size. */
208: char *s;
209: {
210: extern char eqn_delim;
211: extern int eqn_count;
212: int tmp_font = cur_font,
213: tmp_size = cur_size;
214: char *str;
215:
216: ++ntextlines;
217: if ((type & (CENTER|LJUST|RJUST)) == 0)
218: type |= CENTER;
219: if (*s == '\0') /* then save a blank (KLUDGE!!) */
220: save_one(type, cur_font, cur_size, ntextlines, " ");
221: else while (str = parse_text(s, &cur_font, &cur_size))
222: if (*str)
223: save_one(type, cur_font, cur_size, ntextlines, str);
224: free(s);
225: if (cur_font != tmp_font)
226: setfval("textfont",(double)cur_font);
227: if (cur_size != tmp_size)
228: setfval("textsize",(double)cur_size);
229: }
230:
231: save_one(type, font, size, n, str)
232: int type, font, n, size;
233: char *str;
234: {
235: if (ntext >= ntextlist)
236: text = (Text *) grow((char *) text, "text",
237: ntextlist += 200, sizeof(Text));
238: text[ntext].t_type = type;
239: text[ntext].t_font = font;
240: text[ntext].t_size = size;
241: text[ntext].t_space = cur_space;
242: text[ntext].t_line = n;
243: text[ntext].t_val = tostring(str);
244: ntext++;
245: }
246:
247: int
248: copytext(start, end)
249: int start, end;
250: {
251: /* DBK--3/23/90: This is called from copyone(); if copyone is called during
252: the process of assembling a new obj, the calculation of o_nt2 could
253: possibly be upset (too many people updating ntext). However, I don't
254: believe this occurs.
255: */
256: int i;
257: int linediff;
258:
259: linediff = ntextlines - text[start].t_line + 1;
260: for (i = start; i < end; i++, ntext++) {
261: if (ntext >= ntextlist)
262: text = (Text *) grow((char *) text, "text", ntextlist += 200,
263: sizeof(Text));
264: text[ntext] = text[i];
265: text[ntext].t_val = tostring(text[i].t_val);
266: text[ntext].t_line = ntextlines = text[i].t_line + linediff;
267: }
268: return ntext1 = ntext;
269: }
270:
271: double *text_bounds(p) /* returns relative bounding box */
272: obj *p; /* if possible, EQN type text should be sized */
273: { /* by looking for bounding box in dpost file. */
274: static double bnd[4];
275: double ext[4];
276: double w0, w1, dely;
277: double ox, oy;
278: int n1, n2, seq, type;
279:
280: if ((n1=p->o_nt1) >= (n2=p->o_nt2))
281: return bnd;
282: fix_text(n1, n2);
283: dely = abs(text[n1].t_space)/144.;
284: bnd[1] = dely - abs(text[n1].t_size)/144.;
285: switch (text[n1].t_type & (ABOVE | BELOW)) {
286: case ABOVE: bnd[1] += dely; break;
287: case BELOW: bnd[1] -= dely; break;
288: }
289: bnd[3] = bnd[1];
290: bnd[0] = bnd[2] = 0;
291: while (n1 < n2) { /* assumes all text same spacing!!--DBK */
292: seq = text[n1].t_line;
293: bnd[1] -= dely; bnd[3] += dely;
294: type = text[n1].t_type;
295: for (w0 = w1 = 0; n1 < n2 && text[n1].t_line == seq; ++n1) {
296: w1 += (text[n1].t_width = getstringwidth(text[n1].t_val,
297: text[n1].t_font,text[n1].t_size));
298: }
299: switch (type & (CENTER | LJUST | RJUST)) {
300: case CENTER: w1 /= 2; w0 = -w1; break;
301: case RJUST: w0 = -w1; w1 = 0; break;
302: }
303: if (w0 < bnd[0])
304: bnd[0] = w0;
305: if (w1 > bnd[2])
306: bnd[2] = w1;
307: }
308: for (n1 = 0; n1 < 4; n1++)
309: ext[n1] = bnd[n1];
310: if (p->o_type != TEXT) /* text is horizontally centered on o_x,o_y */
311: ext[0] = - (ext[2] = (bnd[2] - bnd[0]) / 2);
312:
313: ox = Xformx(p, 1, p->o_x, p->o_y);
314: oy = Xformy(p, 0, p->o_x, p->o_y);
315: track_bounds(ox + ext[0], oy + ext[1], ox + ext[2], oy + ext[3]);
316: return bnd;
317: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.