V10/cmd/picasso/textgen.c
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
/* @(#)picasso:textgen.c 1.0 */
#include <string.h>
#include <ctype.h>
#include "picasso.h"
#include "y.tab.h"
extern int pic_compat;
obj *textgen()
{
static double prevh = 0;
static double prevw = 0;
struct objattr obat;
int i, sub, at, with, saw_with = 0;
double *bnd, savGbox[4], xwith, ywith;
double savcurx, savcury;
obj *p, *ppos;
Attr *ap;
if (pic_compat) { /* in pic, bounding box has size zero */
savcurx = curx;
savcury = cury;
}
obat.a_weight = obat.a_pcolor = obat.a_lcolor = obat.a_tcolor = -1;
obat.a_ht = obat.a_wid = 0;
obat.a_dashpat.a = (float *)0;
obat.a_layer = (int)getfval("curlayer");
sub = CENTER;
at = with = 0;
set_text();
for (i = 0; i < nattr; i++) {
ap = &attr[i];
switch (ap->a_type) {
default:
miscattrs(ap, &obat);
break;
case WITH:
with = ap->a_val.i;
saw_with++;
break;
case AT:
ppos = ap->a_val.o;
curx = Xformx(ppos, 1, ppos->o_x, ppos->o_y);
cury = Xformy(ppos, 0, ppos->o_x, ppos->o_y);
at++;
break;
}
}
p = makenode(TEXT, N_VAL, obat.a_layer);
/* NOTE: the three color attributes reduce to one here; their obj.val
* slots are used to record bounding box center. If outline fonts are
* implemented, o_fill will be needed, and some adjustments made below
*/
if (obat.a_tcolor == -1)
if ((obat.a_tcolor = obat.a_pcolor) == -1)
obat.a_tcolor = obat.a_lcolor;
p->o_text = obat.a_tcolor;
checktextcolor(p);
p->o_attr |= EDGED;
/* need to save and restore the global bounding box, since text_bounds
sets it based on o_x and o_y, which are not properly set yet! */
for (i = 0; i < 4; i++)
savGbox[i] = Gbox[i];
bnd = text_bounds(p);
for (i = 0; i < 4; i++)
Gbox[i] = savGbox[i];
p->o_val[N_VAL-2].f = (bnd[0] + bnd[2]) / 2;
p->o_val[N_VAL-1].f = (bnd[1] + bnd[3]) / 2;
prevw = p->o_wid = (obat.a_wid > 0 ? obat.a_wid : bnd[2]-bnd[0]);
prevh = p->o_ht = (obat.a_ht > 0 ? obat.a_ht : bnd[3]-bnd[1]);
if (pic_compat) { /* Here unchanged, or changed to at */
if (!saw_with) { /* adjustment w.r.t. Here */
p->o_x = curx;
p->o_y = cury;
}
else { /* forces text center to Here, since all corners
are at center (size is zero) */
p->o_x = curx - p->o_val[N_VAL-2].f;
p->o_y = cury - p->o_val[N_VAL-1].f;
}
}
else {
if (at == 0 && saw_with == 0)
with = isright(hvmode) ? WEST : /* the default for with */
isleft(hvmode) ? EAST : /* butts the text box a- */
isup(hvmode) ? SOUTH :/* gainst the current point */
NORTH; /* in the current direction */
/* position of center relative to current point */
xwith = ywith = 0.0;
switch (with) {
case NORTH: ywith = -prevh/2; break;
case SOUTH: ywith = prevh/2; break;
case EAST: xwith = -prevw/2; break;
case WEST: xwith = prevw/2; break;
case NE: xwith = -prevw/2; ywith = -prevh/2; break;
case SE: xwith = -prevw/2; ywith = prevh/2; break;
case NW: xwith = prevw/2; ywith = -prevh/2; break;
case SW: xwith = prevw/2; ywith = prevh/2; break;
}
curx += xwith; /* position of center, temporarily */
cury += ywith;
/* calculate PLACE for this object based on center */
p->o_x = curx - p->o_val[N_VAL-2].f;
p->o_y = cury - p->o_val[N_VAL-1].f;
/* calculate new postion for Here */
if (isright(hvmode))
curx += prevw/2;
else if (isleft(hvmode))
curx -= prevw/2;
else if (isup(hvmode))
cury += prevh/2;
else
cury -= prevh/2;
}
track_bounds (bnd[0]+p->o_x, bnd[1]+p->o_y,
bnd[2]+p->o_x, bnd[3]+p->o_y);
return(p);
}
int def_font, def_size, def_space;
int cur_font, cur_size, cur_space;
set_text()
{
cur_font = cur_size = cur_space = 0;
def_font = (int)getfval("textfont");
def_size = (int)getfval("textsize");
def_space = (int)getfval("textspace");
}
reset_font(val) /* user supplied font attribute on object */
double val; /* (stored as negative, to distinguish it */
{ /* from troff escape embedded in a string) */
cur_font = -val;
}
reset_size (op, val)
int op;
double val;
{
if (cur_size == 0)
cur_size = -def_size;
switch (op) {
default: cur_size = -val; break;
case '+': cur_size -= val; break;
case '-': cur_size += val; break;
case '*': cur_size *= val; break;
case '/': if (val != 0)
cur_size /= val;
}
}
reset_space (op, val)
int op;
double val;
{
if (cur_space == 0)
cur_space = -def_space;
switch (op) {
default: cur_space = -val; break;
case '+': cur_space -= val; break;
case '-': cur_space += val; break;
case '*': cur_space *= val; break;
case '/': if (val != 0)
cur_space /= val;
}
}
fix_text(n1, n2) /* fill in default font/size/space values */
int n1, n2; /* if space unspecified, set from size. */
{
if (cur_font == 0)
cur_font = -def_font;
if (cur_size == 0)
cur_size = -def_size;
if (cur_space == 0)
cur_space = (cur_size==0 ? -def_space : (double)cur_size
* def_space/def_size);
while (n1 < n2) {
if (text[n1].t_font == 0)
text[n1].t_font = cur_font;
if (text[n1].t_size == 0)
text[n1].t_size = cur_size;
if (text[n1].t_space == 0)
text[n1].t_space = text[n1].t_size == 0 ? cur_space :
(short)(text[n1].t_size
* (double)def_space/def_size);
++n1;
}
}
int ntextlines = 0;
savetext(type, s) /* record text elements for current object */
int type; /* breaking up into homogeneous font/size. */
char *s;
{
extern char eqn_delim;
extern int eqn_count;
int tmp_font = cur_font,
tmp_size = cur_size;
char *str;
++ntextlines;
if ((type & (CENTER|LJUST|RJUST)) == 0)
type |= CENTER;
if (*s == '\0') /* then save a blank (KLUDGE!!) */
save_one(type, cur_font, cur_size, ntextlines, " ");
else while (str = parse_text(s, &cur_font, &cur_size))
if (*str)
save_one(type, cur_font, cur_size, ntextlines, str);
free(s);
if (cur_font != tmp_font)
setfval("textfont",(double)cur_font);
if (cur_size != tmp_size)
setfval("textsize",(double)cur_size);
}
save_one(type, font, size, n, str)
int type, font, n, size;
char *str;
{
if (ntext >= ntextlist)
text = (Text *) grow((char *) text, "text",
ntextlist += 200, sizeof(Text));
text[ntext].t_type = type;
text[ntext].t_font = font;
text[ntext].t_size = size;
text[ntext].t_space = cur_space;
text[ntext].t_line = n;
text[ntext].t_val = tostring(str);
ntext++;
}
int
copytext(start, end)
int start, end;
{
/* DBK--3/23/90: This is called from copyone(); if copyone is called during
the process of assembling a new obj, the calculation of o_nt2 could
possibly be upset (too many people updating ntext). However, I don't
believe this occurs.
*/
int i;
int linediff;
linediff = ntextlines - text[start].t_line + 1;
for (i = start; i < end; i++, ntext++) {
if (ntext >= ntextlist)
text = (Text *) grow((char *) text, "text", ntextlist += 200,
sizeof(Text));
text[ntext] = text[i];
text[ntext].t_val = tostring(text[i].t_val);
text[ntext].t_line = ntextlines = text[i].t_line + linediff;
}
return ntext1 = ntext;
}
double *text_bounds(p) /* returns relative bounding box */
obj *p; /* if possible, EQN type text should be sized */
{ /* by looking for bounding box in dpost file. */
static double bnd[4];
double ext[4];
double w0, w1, dely;
double ox, oy;
int n1, n2, seq, type;
if ((n1=p->o_nt1) >= (n2=p->o_nt2))
return bnd;
fix_text(n1, n2);
dely = abs(text[n1].t_space)/144.;
bnd[1] = dely - abs(text[n1].t_size)/144.;
switch (text[n1].t_type & (ABOVE | BELOW)) {
case ABOVE: bnd[1] += dely; break;
case BELOW: bnd[1] -= dely; break;
}
bnd[3] = bnd[1];
bnd[0] = bnd[2] = 0;
while (n1 < n2) { /* assumes all text same spacing!!--DBK */
seq = text[n1].t_line;
bnd[1] -= dely; bnd[3] += dely;
type = text[n1].t_type;
for (w0 = w1 = 0; n1 < n2 && text[n1].t_line == seq; ++n1) {
w1 += (text[n1].t_width = getstringwidth(text[n1].t_val,
text[n1].t_font,text[n1].t_size));
}
switch (type & (CENTER | LJUST | RJUST)) {
case CENTER: w1 /= 2; w0 = -w1; break;
case RJUST: w0 = -w1; w1 = 0; break;
}
if (w0 < bnd[0])
bnd[0] = w0;
if (w1 > bnd[2])
bnd[2] = w1;
}
for (n1 = 0; n1 < 4; n1++)
ext[n1] = bnd[n1];
if (p->o_type != TEXT) /* text is horizontally centered on o_x,o_y */
ext[0] = - (ext[2] = (bnd[2] - bnd[0]) / 2);
ox = Xformx(p, 1, p->o_x, p->o_y);
oy = Xformy(p, 0, p->o_x, p->o_y);
track_bounds(ox + ext[0], oy + ext[1], ox + ext[2], oy + ext[3]);
return bnd;
}